TapADN SDK 接入指南
SDK 配置
- Unity
- Android
Unity 模块是通过引入 Android 模块后增加桥接文件打包出的 .unitypackage
,方便以 Unity 开发的游戏直接引入。其他引擎/平台的游戏可以通过 Android 原生的方式接入,详见 Android 接入文档。
开发环境要求:
- Unity 2019.4 或更高版本
- Android 5.0(API level 21)或更高版本
Unity 项目 可在 TapTap/TapAD/Demo
找到示例工程来了解其实现过程,注意** Demo 工程需要到真机中才能看到效果,Editor 环境并不会实际生效**。
点击展开 Unity 2020.3.15 之前的版本升级 Gradle 版本
在 Project Settings
-> Player
-> Android Tab
-> Publish Settings
-> Build
,然后勾选Custom Base Gradle Template
将以下更改应用于生成的这个文件: Assets/Plugins/Android/baseProjectTemplate.gradle
如果存在,请移除文件顶部的以下注释:
// GENERATED BY UNITY. REMOVE THIS COMMENT TO PREVENT OVERWRITING WHEN EXPORTING AGAIN
修改文件内容:
dependencies {
// If you are changing the Android Gradle Plugin version, make sure it is compatible with the Gradle version preinstalled with Unity
// See which Gradle version is preinstalled with Unity here https://docs.unity3d.com/Manual/android-gradle-overview.html
// See official Gradle and Android Gradle Plugin compatibility table here https://developer.android.com/studio/releases/gradle-plugin#updating-gradle
// To specify a custom Gradle version in Unity, go do "Preferences > External Tools", uncheck "Gradle Installed with Unity (recommended)" and specify a path to a custom Gradle version
// 将 3.x.0 版本修改为 4.0.1
//classpath 'com.android.tools.build:gradle:3.x.0'
classpath 'com.android.tools.build:gradle:4.0.1'
}
同时,为了将 Gradle 版本和 Android Gradle Plugin 版本对应,需要更新 Gradle 版本,下载 6.1.1 版本的 Gradle,解压后放到自定义的文件夹中,同时不勾选 Unity 中的 Preferences
-> External Tools
-> Android
-> Gradle Installed with Unity(recommend)
,改为选择解压后 Gradle 文件夹的位置,如 <some path\>/gradle-6.1.1
。
无论 Unity 版本都添加一些原生依赖库:在 Project Settings
-> Player
-> Android Tab
-> Publish Settings
-> Build
,勾选Custom Main Gradle Template
将以下更改应用于生成的这个文件: Assets/Plugins/Android/mainTemplate.gradle
如果存在,请移除文件顶部的以下注释:
// GENERATED BY UNITY. REMOVE THIS COMMENT TO PREVENT OVERWRITING WHEN EXPORTING AGAIN
修改文件内容:
- TapADN SDK 从 3.16.3.10 版本开始更新了 glide 的依赖,glide 版本从 4.0.0 更新到了 4.9.0。
- ** 3.16.3.17 加入 Android Dependencies 文件(位于 TapAD/Editor/TapAdDependencies.xml) 方便接入 EDM4U(https://github.com/googlesamples/unity-jar-resolver) 的项目方解决 Android 依赖。**
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
// 加入的依赖库-开始
implementation 'io.reactivex.rxjava2:rxandroid:2.0.1'
implementation 'io.reactivex.rxjava2:rxjava:2.0.1'
implementation 'com.squareup.okhttp3:okhttp:3.12.1'
implementation "com.android.support:appcompat-v7:28.0.0"
implementation "com.android.support:support-annotations:28.0.0"
implementation "com.android.support:support-v4:28.0.0"
implementation "com.github.bumptech.glide:glide:4.9.0"
implementation 'com.android.support:recyclerview-v7:28.0.0'
// 加入的依赖库-结束
// 下面这行是 Unity 的 mainTemplate.gradle 自带的,帮助定位插入位置
// **DEPS**
}
最低支持 Android 5.0(API level 21),编译环境为 Android Studio。
将 TapAD_3.16.3.45.aar
拷贝到游戏目录下的 src/main/libs
目录中。
在游戏目录下 build.gradle
文件中添加代码:
TapADN SDK 从 3.16.3.10 版本开始更新了 glide 的依赖,glide 版本从 4.0.0 更新到了 4.9.0。
repositories{
flatDir{
dirs 'src/main/libs'
}
}
dependencies {
// ...
implementation(name: "TapAD_3.16.3.45", ext: "aar") // 广告 SDK
implementation 'io.reactivex.rxjava2:rxandroid:2.0.1'
implementation 'io.reactivex.rxjava2:rxjava:2.0.1'
implementation 'com.squareup.okhttp3:okhttp:3.12.1'
implementation "com.android.support:appcompat-v7:28.0.0"
implementation "com.android.support:support-annotations:28.0.0"
implementation "com.android.support:support-v4:28.0.0"
implementation "com.github.bumptech.glide:glide:4.9.0"
implementation 'com.android.support:recyclerview-v7:28.0.0'
// ...
}
权限申请
- Unity
- Android
无论 Unity 版本都需加入 Android 相关权限申请,在 Project Settings
-> Player
-> Android Tab
-> Publish Settings
-> Build
,勾选**Custom Main Manifest
**。
将以下更改应用于生成的这个文件: Assets/Plugins/Android/AndroidManifest.xml
如果存在,请移除文件顶部的以下注释:
// GENERATED BY UNITY. REMOVE THIS COMMENT TO PREVENT OVERWRITING WHEN EXPORTING AGAIN
修改文件内容:
<?xml version="1.0" encoding="utf-8"?>
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
package="com.unity3d.player"
xmlns:tools="http://schemas.android.com/tools">
<!-- TapAd 必须的权限-开始 -->
<!-- TargetVersion 31 及以上 通过时,需要该权限) deviceName 和下面的 BLUETOOTEH 互斥-->
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT"/>
<!-- 广告获取坐标(经度、纬度、精度半径(米)、获取时间 毫秒)精准推送 -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<!-- IMEI 、序列号、MEID 、IMSI 、 ICCID 等信息。TargetSdkVersion 4 以及更高需要申请 -->
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<!-- TapAd 必须的权限-结束 -->
<!-- TapAd 可选择权限-开始 -->
<!-- 获取网络状态信息 -->
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<!-- 获取安装应用列表 Android 11 及以上版本才需声明,Android 11 以下版本无需申请 -->
<uses-permission android:name="android.permission.QUERY_ALL_PACKAGES"/>
<!-- (targetVersion 31 以下)deviceName 和上面的 BLUETOOTH_CONNECT 互斥-->
<uses-permission android:name="android.permission.BLUETOOTH"/>
<!-- 允许应用请求安装软件包 -->
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES"/>
<!-- TapAd 可选择权限- 结束 -->
<provider
android:authorities="${applicationId}.com.tds.ad.fileprovider"
android:name="com.tapsdk.tapad.internal.TapADFileProvider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/tapad_ad_file_path"/>
</provider>
...
配置 AndroidManifest.xml
<!-- 广告 SDK 已添加的权限 -->
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<!-- 为了获取更精准的推送数据、建议游戏加上的权限 -->
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<uses-permission android:name="android.permission.QUERY_ALL_PACKAGES" />
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
<uses-permission android:name="android.permission.BLUETOOTH"/>
<!-- targetVersion 31 及以上 建议游戏加上这个权限 -->
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT"/>
<!-- 为了获取更好的广告体验,建议游戏加上以下权限来获取用户信息 -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<!-- 加上下列权限可以提高广告的转化率 -->
<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
<provider
android:authorities="${applicationId}.com.tds.ad.fileprovider"
android:name="com.tapsdk.tapad.internal.TapADFileProvider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/tapad_ad_file_path"/>
</provider>
获取广告权限
在获取 imei 地理位置时,需要用户授予权限。建议先询问权限,再进行初始化工作。
- Unity
- Android
using TapTap.TapAd
TapAdSdk.RequestPermissionIfNecessary();
TapAdManager.get().requestPermissionIfNecessary(activity);
初始化
- Unity
- Android
using TapTap.TapAd
TapAdConfig config = new TapAdConfig.Builder()
.MediaId(your_media_id) // 必选参数,为 TapADN 注册的媒体 ID
.MediaName(your_media_name) // 必选参数,为 TapADN 注册的媒体名称
.MediaKey(your_media_key) // 必选参数,媒体密钥,可以在 TapADN 后台查看(用于传输数据的解密)
.MediaVersion("1") // 必选参数,默认值 "1"
.Channel(your__channel) // 必选参数,渠道
.TapClientId(your_tap_client_id) // 可选参数,TapTap 开发者中心的游戏 Client ID
.EnableDebugLog(false) // 可选参数,是否打开原生 debug 调试信息输出:true 打开、false 关闭。默认 false 关闭
.ShakeEnabled(false) // 可选参数,是否开启摇一摇: true 打开、false 关闭。
.Build();
// CustomControllerWrapper 为实现了 TapTap.TapAd.ICustomController 的类
// onInitedCallback 为可选回调函数,类型是 System.Action,
TapAdSdk.Init(config, new CustomControllerWrapper(this), onInitedCallback);
// ICustomController 接口说明
public interface ICustomController
{
// 是否允许 SDK 主动使用地理位置信息
bool CanUseLocation { get; }
// 当 isCanUseLocation=false 时,可传入地理位置信息,TapAd 使用您传入的地理位置信息
TapAdLocation GetTapAdLocation { get; }
// 是否允许 SDK 主动使用手机硬件参数,如 imei
bool CanUsePhoneState { get; }
// 当 isCanUsePhoneState=false 时,可传入 imei 信息,TapAd 使用您传入的 imei 信息
string GetDevImei { get; }
// 是否允许 SDK 主动使用 ACCESS_WIFI_STATE 权限
bool CanUseWifiState { get; }
// 是否允许 SDK 主动使用 WRITE_EXTERNAL_STORAGE 权限
bool CanUseWriteExternal { get; }
// 开发者可以传入 oaid
// 信通院 OAID 的相关采集——如何获取 OAID:
// 1. 移动安全联盟官网 http://www.msa-alliance.cn/
// 2. 信通院统一 SDK 下载 http://msa-alliance.cn/col.jsp?id=120
string GetDevOaid { get; }
// 是否允许 SDK 主动获取设备上应用安装列表的采集权限
bool Alist { get; }
// 是否允许 SDK 主动获取 ANDROID_ID
bool CanUseAndroidId { get; }
// 用户信息(为了提高广告的推送效率,开发者可以帮助传入一些用户的画像信息)
CustomUser ProvideCustomer();
}
// 地理位置说明
public sealed class TapAdLocation
{
// 纬度
public double latitude;
// 经度
public double longitude;
// 精度
public double accuracy;
// 设置经纬度
public TapAdLocation(double latitude, double longitude, double accuracy)
{
//...
}
}
// 用户信息
public sealed class CustomUser
{
public int realAge;
// 0.男;1.女
public int realSex;
// 角色性别 0.男;1.女
public int avatarSex;
// 角色等级
public int avatarLevel;
// 是否新玩家 0.否;1.是
public int newUserStatus;
// 是否为付费用户 0.否;1.是
public int payedUserStatus;
// 是否通过新手教程 0.否;1.是
public int beginMissionFinished;
// 角色当前付费道具数量
public int avatarPayedToolCnt;
}
TapAdConfig config = new TapAdConfig.Builder()
.withMediaId(your_media_id) // 必选参数。为 TapADN 注册的媒体 ID
.withMediaName(your_media_name) // 必选参数。为 TapADN 注册的媒体名称
.withMediaKey(your_media_key) // 必选参数。媒体密钥,可以在TapADN后台查看
.withMediaVersion("1") // 必选参数。默认值 "1"
.withTapClientId(your_tap_client_id) // 可选参数。TapTap 开发者中心的游戏 Client ID
.enableDebug(true) // 可选参数,是否打开 debug 调试信息输出:true 打开、false 关闭。默认 false 关闭
.withGameChannel(your_app_channel) // 必选参数,渠道
.shakeEnabled(false) // 可选参数,是否开启摇一摇: true 打开、false 关闭。默认 true 开启。
.withCustomController(new TapAdCustomController() {
// 是否允许 SDK 主动使用地理位置信息
@Override
public boolean isCanUseLocation() {
return enableGetLocation;
}
// 当 isCanUseLocation=false 时,可传入地理位置信息,TapAd 使用您传入的地理位置信息
@Override
public TapAdLocation getTapAdLocation() {
return new TapAdLocation(longitude, latitude, accuracy);
}
// 是否允许 SDK 主动使用手机硬件参数,如 imei
@Override
public boolean isCanUsePhoneState() {
return enableGetPhoneState;
}
// 当 isCanUsePhoneState=false 时,可传入 imei 信息,TapAd 使用您传入的 imei 信息
@Override
public String getDevImei() {
return imei;
}
// 是否允许 SDK 主动使用 ACCESS_WIFI_STATE 权限
@Override
public boolean isCanUseWifiState() {
return enableGetWifiState;
}
// 是否允许 SDK 主动使用 WRITE_EXTERNAL_STORAGE 权限
@Override
public boolean isCanUseWriteExternal() {
return enableWriteExternal;
}
// 开发者可以传入 oaid
// 信通院 OAID 的相关采集——如何获取 OAID:
// 1. 移动安全联盟官网 http://www.msa-alliance.cn/
// 2. 信通院统一 SDK 下载 http://msa-alliance.cn/col.jsp?id=120
@Override
public String getDevOaid() {
return oaid;
}
// 是否允许 SDK 主动获取设备上应用安装列表的采集权限
@Override
public boolean alist() {
return enableGetAppList;
}
// 是否允许 SDK 主动获取 ANDROID_ID
@Override
public boolean isCanUseAndroidId() {
return enableGetAndroidId;
}
@Override
public CustomUser provideCustomUser() {
return new CustomUser.Builder()
.withRealAge(age) // 年龄
.withRealSex(sex) // 性别 0:男 1:女
.withAvatarSex(avatarSex) // 角色性别 0:男 1:女
.withAvatarLevel(avatarLevel) // 角色等级
.withNewUserStatus(status) // 是否新玩家 0:否;1:是
.withPayedUserStatus(status) // 是否付费用户 0:否;1:是
.withBeginMissionFinished(finished) // 是否通过新手教程 0:否 1:是
.withAvatarPayedToolCnt(cnt) // 角色当前付费道具数量
.build();
}
})
.build();
TapAdSdk.init(this, config);
上报用户行为
为了获取更优质的广告内容,需要游戏额外提供一些玩家在游戏中的行为数据作为补充。
- Unity
- Android
using TapTap.TapAd
var userActions = new UserAction[3];
var jan1st1970 = new DateTime
(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
for (int i = 0 ; i < 3; i ++) {
var tmp = new UserAction(actionType: i, actionTime: (long)(DateTime.UtcNow - jan1st1970).TotalMilliseconds,
amount: i * 1000, winStatus: i % 2);
userActions[i] = tmp;
}
// CustomUserAction 为实现了 IUserAction 的类
TapAdSdk.UploadUserAction(userActions, new CustomUserAction(this));
// 用户行为数据类说明
public class UserAction
{
// 行为动作类型,可自定义
public int ActionType { get; }
// 行为发生时间(单位:秒)
public long ActionTime { get; }
// 付费金额
public int Amount{ get; }
// 是否胜利.0-失败;1-胜利
public int WinStatus{ get; }
public UserAction(int actionType, long actionTime, int amount, int winStatus)
{
...
}
}
// 上报接口说明
public interface IUserAction
{
// 上报成功
void OnSuccess();
// 上报失败
void OnError(int code, string message);
}
UserAction[] userActions = new UserAction[3];
for (int i = 0 ; i < 3; i ++) {
UserAction tmp = new UserAction.Builder()
.withActionType(i)
.withActionTime(System.currentTimeMillis())
.withAmount(i * 1000)
.withWinStatus(i % 2)
.build();
userActions[i] = tmp;
}
TapAdManager.get().uploadUserAction(userActions, new Callback() {
@Override
public void onSuccess() {
// 上报成功
}
@Override
public void onError(AdException exception) {
// 上报失败
}
});
开屏广告
开屏广告为用户在进入 App 时展示的全屏广告。开屏广告为一个 View
,宽高默认为 match_parent
。
竖屏开屏广告 view
要求 width = 屏幕宽,height 需要 >= 75% 屏幕高,否则会影响计费。
横屏开屏广告 view
要求 width = 屏幕宽,height 需要 = 屏幕高,否则会影响计费。
建议业务逻辑:
- 每次启动应用的时候调用 SDK 接口请求开屏广告。
- SDK 会根据一定规则从候选队列里选取一个返回给游戏,获取成功就可以展示,获取失败的话本次不展示广告。
获取广告
- Unity
- Android
using TapTap.TapAd
TapSplashAd _tapSplashAd = null;
if (TapAdSdk.IsInited == false)
{
Debug.Log("TapAd 需要先初始化!");
return;
}
// 释放之前的广告
if (_tapSplashAd != null)
{
_tapSplashAd.Dispose();
_tapSplashAd = null;
}
int adId = YOUR_AD_ID;
// create AdRequest
var request = new TapAdRequest.Builder()
.SpaceId(adId)
.Build();
_tapSplashAd = new TapSplashAd(request);
// SplashAdLoadListener 为实现了 ISplashAdLoadListener 的类
_tapSplashAd.SetLoadListener(new SplashAdLoadListener(this));
_tapSplashAd.Load();
// Splash 加载接口说明
public interface ISplashAdLoadListener : ICommonLoadListener
{
// 当 Splash 加载完毕
void OnSplashAdLoad(TapSplashAd ad);
}
// 通用加载接口说明
public interface ICommonLoadListener
{
// 加载出错回调
void OnError(int code, string message);
}
TapAdNative tapAdNative = TapAdManager.get().createAdNative(activity);
// 广告后台获取广告位 id
int spaceId = "your_space_id";
tapAdNative.loadSplashAd(new AdRequest.Builder()
.withSpaceId(spaceId)
.build(), new TapAdNative.SplashAdListener() {
@Override
public void onError(int code, String message) {
// 获取失败
}
@Override
public void onSplashAdLoad(TapSplashAd splashAd) {
// 获取成功,可以在这时候播放广告
}
});
播放
- Unity
- Android
using TapTap.TapAd
if (TapAdSdk.IsInited == false)
{
Debug.Log("TapAd 需要先初始化!");
return;
}
if (_tapSplashAd != null)
{
// SplashInteractionListener 为实现了 ISplashAdInteractionListener 的类
_tapSplashAd.SetInteractionListener(new SplashInteractionListener(this));
_tapSplashAd.Show();
}
else
{
Debug.LogErrorFormat($"[Unity::AD] 未加载好视频,无法播放!");
}
// Splash 播放回调接口说明
public interface ISplashAdInteractionListener : ICommonInteractionListener
{
// 点击跳过
void OnAdSkip(TapSplashAd ad);
// 广告时间到
void OnAdTimeOver(TapSplashAd ad);
// 点击广告回调 3.16.3.30 新增
void OnAdClick();
}
// 通用播放回调接口说明
public interface ICommonInteractionListener
{
}
// 注册开屏广告交互事件监听
splashAd.setSplashInteractionListener(new TapSplashAd.AdInteractionListener() {
@Override
public void onAdSkip() {
// 点击了跳过,可以进入游戏
}
@Override
public void onAdTimeOver() {
// 开屏时间到(开屏页已关闭),可以进入游戏
}
@Override
public void onAdClick() {
// 开屏广告点击了转化按钮,会跳转到落地页 3.16.3.30 新增
}
@Override
public void onAdShow() {
// 开屏广告曝光回调接口,3.16.3.41 新增
}
});
// 展示开屏页
splashAd.show(this);
关闭开屏广告
注意 3.16.3.23 版本开始 开屏广告移除了自动关闭逻辑,需要媒体手动关闭。
- Unity
- Android
using TapTap.TapAd
// 场景 1 媒体直接关闭开屏广告
if (_tapSplashAd != null)
{
_tapSplashAd.Dispose();
}
// 场景 2 在收到开屏广告交互事件后选择关闭
public void OnAdSkip(TapSplashAd ad) {
if (ad != null) ad.Dispose();
}
public void OnAdTimeOver(TapSplashAd ad) {
if (ad != null) ad.Dispose();
}
...
// 场景 1 媒体展示开屏中直接关闭广告
if (splashAd != null)
{
splashAd.dispose();
splashAd.destroyView();
}
// 场景 2 在收到开屏广告交互事件后选择关闭
@Override
public void onAdSkip() {
if (splashAd != null)
{
splashAd.dispose();
splashAd.destroyView();
}
}
@Override
public void onAdTimeOver() {
if (splashAd != null)
{
splashAd.dispose();
splashAd.destroyView();
}
}