小米广告 SDK Android 集成指南
1. SDK介绍
小米广告SDK提供各种广告形式给客户端集成,应用既可以在MIUI系统上运行,也可以在非MIUI系统上运行。
小米广告SDK Demo(含SDK文件):点击查看小米广告SDK
在继续之前,建议您先下载上面的小米广告SDK Demo,该项目包含了小米广告SDK的接入示例代码,有助于您快速理解我们SDK的整个接入流程。
SDK支持的广告形式包括:
- 开屏广告
- 插屏广告
- 游戏视频广告
- BANNER广告
MiAdSDK 包含以下部分:
- AdSdk.jar : SDK的接口部分,放在应用的libs目录下
- AdServer.apk : 放在应用的assets目录下
- analytics_core.apk : 放在应用的assets目录下
2. SDK接入流程
2.1 开发者站准备
2.2 接入准备
-
配置AndroidManifest.xml
在AndroidManifest.xml里添加这些权限:
<uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.READ_PHONE_STATE"/> <uses-permission android:name="android.permission.GET_TASKS"/> <uses-permission android:name="android.permission.SEND_DOWNLOAD_COMPLETED_INTENTS" />
在AndroidManifest.xml里添加以下Activity:
<activity android:name="com.xiaomi.ad.puppet.AdPuppetActivity" android:configChanges="orientation|screenSize" android:label="AD Activity" android:screenOrientation="behind" android:theme="@android:style/Theme.Translucent.NoTitleBar.Fullscreen"> </activity>
在AndroidManifest.xml里将Application设为你自定义的:
<application android:name="你自定义Application,如:com.unity.sampleassets.AdApplication" android:theme="@style/UnityThemeSelector" android:icon="@drawable/app_icon" android:label="@string/app_name" android:isGame="true" android:banner="@drawable/app_banner">
详见Demo中的AndroidManifest.xml
-
配置Proguard
AdSdk.jar已经做过代码的混淆,可以不用做混淆,如果要做混淆的话,需要在配置里如下的keep项
-keep class com.xiaomi.ad.**{*;} -keep class com.miui.analytics.**{*;} -keep class com.xiaomi.analytics.*{public protected *;}
-
初始化AdSdk
在自定义的Application的onCreate调用时初始化AdSdk。 调用如下接口:
AdSdk.initialize(this, appId);
示例如下:
public class AdApplication extends Application { @Override public void onCreate() { super.onCreate(); AdSdk.setMockOn(); //打开模拟模式,仅在初次接入广告时使用(测试用,在开发者站提交应用时请删除本行代码,否则不会有收益) AdSdk.setDebugOn(); // 打开调试,输出调试信息(测试用,在开发者站提交应用时请删除本行代码,否则不会有收益) AdSdk.initialize(this, appId);//appId是你在小米开发者网站上注册的应用ID。 } }
*初次提交应用后记得提醒我们的技术支持,否则不会有广告下发。
如果不初始化仍可能获得广告,但一次后会返回UNKNOW错误。 P.S. 这样的广告不会获得收益。所以一定要自定义Application进行初始化。
2.3 接入
2.3.1 广告位接入
-
SplashAd 开屏广告
请求广告接口:
public static void requestSplashAd(Activity startActivity,String positionId,AdListener adListener)
POSITION_ID 为之前在开发者站获得的,下面是Demo中调用的例子:
//以下代码为开屏广告示例 try { AdPuppetManager.requestSplashAd(MainActivity.this, SPLASH_POSITION_ID, new AdListener() { @Override public void onAdEvent(AdEvent event) { Log.d(TAG, "onAdEvent name:" + event.name()); //这儿会有一系列用户行为相关的回调事件。如果需要,您可以通过event.mType来判断用户的行为类型,从而采取不同的处理方式。 if (AdEvent.TYPE_SKIP == event.mType) { //用户关闭了开屏广告 } else if (AdEvent.TYPE_CLICK == event.mType) { //用户点击了开屏广告 } else if (AdEvent.TYPE_FINISH == event.mType) { //开屏广告展示结束 } else if (AdEvent.TYPE_VIEW == event.mType) { // 开屏广告展示 } } @Override public void onAdError(AdError error) { //这个方法被调用时,表示从服务器端请求开屏广告时,出现错误。 Log.e(TAG, "onAdError:" + error); } @Override public void onAdLoaded() { //这个方法被调用时,表示要展示开屏广告了。如果需要,您可以做一些后续逻辑处理。 Log.d(TAG, "onAdLoaded:"); } }); } catch (Exception e) { e.printStackTrace(); } //以上代码为开屏广告示例
-
InterstitialAd 插屏广告
请求广告接口:
public static void requestInterstitialAd(Activity paramActivity, final String POSITION_ID, AdListener paramAdListener)
展示广告接口:
public static void showInterstitialAd(final String POSITION_ID)
POSITION_ID 为之前在开发者站获得的,下面是Demo中调用的例子:
//此Activity用于模拟游戏界面 public class InterstitialAdActivity extends Activity { public static final String TAG = "AD-InterstitialAd"; //以下的POSITION_ID 需要使用您申请的值替换下面内容 private final static String POSITION_ID = "e244874812b7f465a80d3720d7e65889"; private Button mPlayBtn = null; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.interstitialad); mPlayBtn = (Button) this.findViewById(R.id.play_btn); mPlayBtn.setEnabled(false);//首先将播放插屏按钮设置成不可点击状态,因为此时还不能播放插屏。当然,您也可以将该按钮隐藏掉. mPlayBtn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (AdPuppetManager.isInterstitialAdReady(POSITION_ID)) { AdPuppetManager.showInterstitialAd(POSITION_ID); } } }); AdPuppetManager.requestInterstitialAd(InterstitialAdActivity.this, POSITION_ID, new AdListener() { @Override public void onAdEvent(AdEvent event) { Log.e(TAG, "onAdEvent name:" + event.name()); //这儿会有一系列用户行为相关的回调事件。如果需要,您可以通过event.mType来判断用户的行为类型,从而采取不同的处理方式。 if (AdEvent.TYPE_SKIP == event.mType) { //用户关闭了插播广告 } else if (AdEvent.TYPE_CLICK == event.mType) { //用户点击了插播广告 } } @Override public void onAdError(AdError error) { //这个方法被调用时,表示从服务器端请求插播广告时,出现错误。 Log.e(TAG, "onAdError:" + error.name()); } @Override public void onAdLoaded() { //这个方法被调用时,表示要展示插播广告了。如果需要,您可以做一些后续逻辑处理。 Log.e(TAG, "onAdLoaded:"); } }); } }
-
GameAd 游戏视频广告
请求广告接口:
public static void requestGameVideoAd(Activity paramActivity, final String POSITION_ID, AdListener paramAdListener);
展示广告接口:
public static boolean showGameVideoAd(String POSITION_ID);
POSITION_ID 为之前在开发者站获得的,下面是Demo中调用的例子:
//此Activity用于模拟游戏界面 public class GameVideoAdActivity extends Activity { public static final String TAG = "AD-GameVideoAdActivity"; //以下的POSITION_ID 需要使用您申请的值替换下面内容 private final static String POSITION_ID = "74a7049c5d1824364c8cd738da8645ad"; private Button mPlayBtn = null; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.videoad); mPlayBtn = (Button) this.findViewById(R.id.play_btn); mPlayBtn.setEnabled(false); //首先将播放视频按钮设置成不可点击状态,因为此时还不能播放视频。当然,您也可以将该按钮隐藏掉. mPlayBtn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { AdPuppetManager.showGameVideoAd(POSITION_ID); } }); AdPuppetManager.requestGameVideoAd(GameVideoAdActivity.this, POSITION_ID, new AdListener() { @Override public void onAdEvent(AdEvent event) { Log.e(TAG, "onAdEvent name:" + event.name() + ",type:" + event.mType); //这儿会有一系列用户行为相关的回调事件。如果需要,您可以通过event.mType来判断用户的行为类型,从而采取不同的处理方式。 if (AdEvent.TYPE_SKIP == event.mType) { //用户看完了视频,点击了视频右上角的X号。 } else if (AdEvent.TYPE_FINISH == event.mType) { //用户看完了视频,点击了下载按钮 } } @Override public void onAdError(AdError error) { Log.e(TAG, "onAdError:" + error.name()); //加载广告过程中出现了错误,此时应该隐藏掉视频播放入口。 mPlayBtn.setEnabled(false); } @Override public void onAdLoaded() { Log.e(TAG, "onAdLoaded:"); //当onAdLoaded方法被回调时,表示视频广告已下载到本地,可以展示视频广告播放按钮了。 mPlayBtn.setEnabled(true); } }); } }
3. 游戏引擎最佳接入方案
以GameAd视频广告为例
-
Cocos2d-x
Cocos2d-x项目中的代码
void cocosRequestAd() { JniMethodInfo methodInfo; bool hasContext = JniHelper::getStaticMethodInfo(methodInfo, "org/cocos2dx/cpp/AppActivity", "getContext", "()Landroid/content/Context;"); jobject activityObject; if (hasContext) { activityObject = methodInfo.env->CallStaticObjectMethod(methodInfo.classID, methodInfo.methodID); } else { return; } // 修改requestAd为Android项目里Activity中相应的函数名 bool hasMethod = JniHelper::getMethodInfo(methodInfo, "org/cocos2dx/cpp/AppActivity","requestAd", "(Ljava/lang/String;)V"); if (hasMethod) { // 修改为相应的POSITION_ID jstring msg = methodInfo.env->NewStringUTF(POSITION_ID); methodInfo.env->CallVoidMethod(activityObject, methodInfo.methodID,msg); } else { return; } } extern "C" { // 修改adCallback为Android项目里Activity中相应的函数名 JNIEXPORT void JNICALL Java_org_cocos2dx_cpp_AppActivity_adCallback(JNIEnv *env, jobject instance, jstring msg_) { const char *msg = env->GetStringUTFChars(msg_, 0); //TODO env->ReleaseStringUTFChars(msg_, msg); } }
Android项目中的代码
public void requestGameVideoAd(final String POSITION_ID) { AdPuppetManager.requestGameVideoAd(UnityPlayerActivity.this, POSITION_ID, new AdListener() { @Override public void onAdEvent(final AdEvent event) { adCallback("GameVideoAd ad event" + event.name()); } @Override public void onAdError(final AdError error) { adCallback("GameVideoAd ad error:" + error.name()); } @Override public void onAdLoaded() { adCallback("GameVideoAd ad load"); } }); } public void requestInterstitialAd(final String POSITION_ID) { AdPuppetManager.requestInterstitialAd(UnityPlayerActivity.this, POSITION_ID, new AdListener() { @Override public void onAdEvent(final AdEvent event) { adCallback("InterstitialAd ad event" + event.name()); } @Override public void onAdError(final AdError error) { adCallback("InterstitialAd ad error:" + error.name()); } @Override public void onAdLoaded() { adCallback("InterstitialAd ad load"); } }); } //此方法应在收到requestGameVideoAd参数中的AdListener的onAdLoaded()的回调后调用,达到预加载的效果 public void showGameVideoAd(final String POSITION_ID) { AdPuppetManager.showGameVideoAd(POSITION_ID); } //此方法应在收到requestInterstitialAd参数中的AdListener的onAdLoaded()的回调后调用,达到预加载的效果 public void showInterstitialAd(final String POSITION_ID) { if (AdPuppetManager.isInterstitialAdReady(POSITION_ID)) { AdPuppetManager.showInterstitialAd(POSITION_ID); } } public native void adCallback(String msg);
-
Unity3D
Unity3D项目中的代码
using UnityEngine; using System.Collections; using System.Runtime.InteropServices; public class UnityRequestAd : MonoBehaviour { AndroidJavaClass androidJavaClass; AndroidJavaObject androidJavaObject; void Start () { androidJavaObject = null; androidJavaClass = new AndroidJavaClass ("com.unity3d.player.UnityPlayer"); } void OnGUI () { if (GUI.Button (new Rect (100, 100, 500, 200), "Ad Test Button")) { if (androidJavaClass != null) { androidJavaObject = androidJavaClass.GetStatic<AndroidJavaObject> ("currentActivity"); } else { return; } if (androidJavaObject != null) { // 修改requestAd为Android项目里Activity中对应的函数名 // 修改为相应的POSITION_ID androidJavaObject.Call ("requestAd","POSITION_ID"); } else { return; } } } // 修改adCallback为Android项目里Activity中相应的函数名 void adCallback (string msg) { print (msg); //TODO } }
Android项目中的代码
public void requestGameVideoAd(final String POSITION_ID) { AdPuppetManager.requestGameVideoAd(UnityPlayerActivity.this, POSITION_ID, new AdListener() { @Override public void onAdEvent(final AdEvent event) { UnityPlayer.UnitySendMessage("Main Camera", "adCallback", "GameVideoAd ad event:" + event.name()); } @Override public void onAdError(final AdError error) { UnityPlayer.UnitySendMessage("Main Camera", "adCallback", "GameVideoAd ad error:" + error.name()); } @Override public void onAdLoaded() { UnityPlayer.UnitySendMessage("Main Camera", "adCallback", "GameVideoAd ad load"); } }); } public void requestInterstitialAd(final String POSITION_ID) { AdPuppetManager.requestInterstitialAd(UnityPlayerActivity.this, POSITION_ID, new AdListener() { @Override public void onAdEvent(final AdEvent event) { UnityPlayer.UnitySendMessage("Main Camera", "adCallback", "InterstitialAd ad event:" + event.name()); } @Override public void onAdError(final AdError error) { UnityPlayer.UnitySendMessage("Main Camera", "adCallback", "InterstitialAd ad error:" + error.name()); } @Override public void onAdLoaded() { UnityPlayer.UnitySendMessage("Main Camera", "adCallback", "InterstitialAd ad load"); } }); } //此方法应在收到requestGameVideoAd参数中的AdListener的onAdLoaded()的回调后调用,达到预加载的效果 public void showGameVideoAd(final String POSITION_ID) { AdPuppetManager.showGameVideoAd(POSITION_ID); } //此方法应在收到requestInterstitialAd参数中的AdListener的onAdLoaded()的回调后调用,达到预加载的效果 public void showInterstitialAd(final String POSITION_ID) { if (AdPuppetManager.isInterstitialAdReady(POSITION_ID)) { AdPuppetManager.showInterstitialAd(POSITION_ID); } }
4. FAQ
Q:如何实现预加载? A:对于插屏类型广告和游戏视屏类型广告,请求广告的回调里有个onLoaded(),此函数表示广告加载完毕,收到此回调后随时可以调用显示广告的方法。
Q:如何判断是否可以展示广告? A:可以使用AdPuppetManager.isInterstitialAdReady(POSITION_ID) 判断插屏广告是否可以展示, AdPuppetManager.isGameVideoReady(POSITION_ID) 判断游戏视屏广告是否可以展示 。
Q:cocos2D为什么无法加载? A:如果用自带的命令打包会把asserts里的文件给删掉,建议在eclipse 或者Android Studio来打包,保证成功率和方便我们进行技术支持。
Q:为什么视频暂停了(见下图)? A:本sdk的视频与UnityAD的视频有冲突,如果在同一个app里会导致此情况的发生。
Q:为什么无法加载? A:建议先看看Demo,仍旧无法解决请找我们的技术支持。
文档版本:0.3.9
最后更新日期:2016-10-08