Unity接入今日头条广告(激励广告)
写这篇博客主要是为了使用Eclipse导出Jar包和Res文件去给Unity调用。之前我写过一篇博客(https://www.cnblogs.com/weiqiangwaideshijie/p/7715861.html)是直接将Unity导出Android工程去接入SDK,现在换另外一种模式去接入SDK,使用的通讯框架还是之前的。
一 为了避免不必要的错误,我这边是用Unity去导出一个空的Android工程而不是直接在Eclipse去直接新建一个acivity,再去引用Unity的Classes.jar文件。用Eclipse打开unity导出的空的工程,然后将之前写的通讯框架导入进去,并且删除untiy自带的三个类
二 UnityPlayerActivity引用头条的库文件(箭头所指的),在将头条的Res文件给copy到UnityPlayerActivtiy里面,不要去覆盖,不然Unity自带的一些东西被覆盖掉,导致manifest里面找不到对应的配置和资源。
三 然后配置我们的Manifest清单文件,这个直接CopyDemo里面自己需要的配置就可以了。
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="1" android:versionName="1.0" package="com.usfun.cbddn" android:installLocation="preferExternal"> <supports-screens android:anyDensity="true" android:largeScreens="true" android:normalScreens="true" android:smallScreens="true" android:xlargeScreens="true" /> <!--必须要有的权限--> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.READ_PHONE_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.ACCESS_WIFI_STATE" /> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> <uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" /> <uses-permission android:name="android.permission.GET_TASKS" /> <!--最好能提供的权限--> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <!-- 如果有视频相关的广告且使用textureView播放,请务必添加,否则黑屏 --> <uses-permission android:name="android.permission.WAKE_LOCK" /> <application android:icon="@drawable/app_icon" android:label="@string/app_name" android:isGame="true" android:banner="@drawable/app_banner"> <activity android:label="@string/app_name" android:name="com.cw.androidsdk.MainActivity" android:screenOrientation="fullSensor" android:launchMode="singleTask" android:configChanges="mcc|mnc|locale|touchscreen|keyboard|keyboardHidden|navigation|orientation|screenLayout|uiMode|screenSize|smallestScreenSize|fontScale"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> <category android:name="android.intent.category.LEANBACK_LAUNCHER" /> </intent-filter> <meta-data android:name="unityplayer.UnityActivity" android:value="true" /> </activity> <!-- 以下为头条网盟sdk的配置 start --> <activity android:configChanges="keyboardHidden|orientation|screenSize" android:launchMode="singleTask" android:name="com.bytedance.sdk.openadsdk.activity.TTLandingPageActivity" /> <activity android:configChanges="keyboardHidden|orientation|screenSize" android:launchMode="singleTask" android:name="com.bytedance.sdk.openadsdk.activity.TTVideoLandingPageActivity" /> <activity android:configChanges="keyboardHidden|orientation|screenSize" android:launchMode="singleTask" android:name="com.bytedance.sdk.openadsdk.activity.TTRewardVideoActivity" /> <activity android:configChanges="keyboardHidden|orientation|screenSize" android:launchMode="singleTask" android:name="com.bytedance.sdk.openadsdk.activity.TTFullScreenVideoActivity" /> <activity android:launchMode="singleTask" android:name="com.bytedance.sdk.openadsdk.activity.TTDelegateActivity" android:theme="@android:style/Theme.Translucent.NoTitleBar" /> <service android:name="com.bytedance.sdk.openadsdk.multipro.aidl.BinderPoolService" /> <service android:name="com.ss.android.socialbase.downloader.notification.DownloadNotificationService" /> <service android:name="com.ss.android.socialbase.downloader.downloader.DownloadService" /> <service android:name="com.ss.android.socialbase.downloader.downloader.IndependentProcessDownloadService" android:process=":downloader"> <intent-filter> <action android:name="com.ss.android.socialbase.downloader.remote" /> </intent-filter> </service> <service android:name="com.ss.android.socialbase.downloader.impls.DownloadHandleService" /> <service android:name="com.ss.android.socialbase.appdownloader.AppDownloadHandleService" /> <activity android:launchMode="singleTask" android:name="com.ss.android.socialbase.appdownloader.view.DownloadSizeLimitActivity" android:theme="@android:style/Theme.Dialog" /> <activity android:launchMode="singleTask" android:name="com.ss.android.socialbase.appdownloader.view.DownloadTaskDeleteActivity" android:theme="@android:style/Theme.Dialog" /> <activity android:launchMode="standard" android:name="com.ss.android.downloadlib.activity.InteractionMiddleActivity" /> <receiver android:name="com.ss.android.downloadlib.core.download.DownloadReceiver" /> <!-- authorities前缀请使用自己的app包名 --> <provider android:authorities="com.usfun.cbddn.fileprovider" android:exported="false" android:grantUriPermissions="true" android:name="android.support.v4.content.FileProvider"> <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/file_paths" /> </provider> <provider android:authorities="com.usfun.cbddn.TTMultiProvider" android:exported="false" android:name="com.bytedance.sdk.openadsdk.multipro.TTMultiProvider" /> <!-- 头条网盟sdk的配置 end --> <meta-data android:name="android.max_aspect" android:value="2.4" /> </application> <uses-sdk android:minSdkVersion="14" android:targetSdkVersion="24" /> <uses-feature android:glEsVersion="0x00020000" /> <uses-feature android:name="android.hardware.touchscreen" android:required="false" /> <uses-feature android:name="android.hardware.touchscreen.multitouch" android:required="false" /> <uses-feature android:name="android.hardware.touchscreen.multitouch.distinct" android:required="false" /> </manifest>
四 以上的步骤,我们就把环境给配置好了,最后,按照文档去写入播放广告的代码。我这边直接入奖励广告。(下面有些和Unity交互代码是这个项目不需要的,看加粗倾斜的代码块)
MainActivity
package com.cw.androidsdk; import android.os.Bundle; import com.bytedance.sdk.openadsdk.AdSlot; import com.bytedance.sdk.openadsdk.TTAdConfig; import com.bytedance.sdk.openadsdk.TTAdConstant; import com.bytedance.sdk.openadsdk.TTAdManager; import com.bytedance.sdk.openadsdk.TTAdNative; import com.bytedance.sdk.openadsdk.TTAdSdk; import com.bytedance.sdk.openadsdk.TTAppDownloadListener; import com.bytedance.sdk.openadsdk.TTFullScreenVideoAd; import com.bytedance.sdk.openadsdk.TTRewardVideoAd; import com.sdk.api.SDKAPI; import com.sdk.api.SDKUtility; import com.unity3d.player.UnityPlayer; import com.unity3d.player.UnityPlayerActivity; import java.util.UUID; import org.json.JSONException; import org.json.JSONObject; import android.R.string; import android.app.Activity; import android.app.AlertDialog; import android.content.DialogInterface; import android.content.Intent; import android.graphics.PixelFormat; import android.os.Handler; import android.os.Looper; import android.os.Message; import android.text.TextUtils; import android.util.Log; import android.view.Window; import android.widget.Toast; public class MainActivity extends UnityPlayerActivity { public static Activity CurrentActivity; public static MyHandler myHandler;// private TTAdNative mTTAdNative; private TTRewardVideoAd mttRewardVideoAd; private TTAdManager ttAdManager; @Override protected void onCreate(Bundle arg0) { // TODO Auto-generated method stub super.onCreate(arg0); CurrentActivity=this; myHandler=new MyHandler(); //如果明确某个进程不会使用到广告SDK,可以只针对特定进程初始化广告SDK的content //if (PROCESS_NAME_XXXX.equals(processName)) { // TTAdSdk.init(context, config); //} } @Override protected void onStart() { super.onStart(); } @Override protected void onPause() { super.onPause(); } @Override protected void onResume() { super.onResume(); } public void onNewIntent(Intent newIntent){ super.onNewIntent(newIntent); } @Override protected void onStop() { super.onStop(); } @Override protected void onDestroy() { super.onDestroy(); } @Override protected void onRestart() { super.onRestart(); } public class MyHandler extends Handler { public MyHandler() { } public MyHandler(Looper L) { super(L); } /* * 锟斤拷锟斤拷锟斤拷锟斤拷锟叫达拷梅锟斤拷锟斤拷锟斤拷锟斤拷芨锟斤拷锟较� * */ @Override public void handleMessage(Message msg) { if(msg.what==SDKUtility.Init) { //"5001121" Log.i("android", "Init"); // Toast.makeText(CurrentActivity, "Init", Toast.LENGTH_SHORT).show(); TTAdSdk.init(CurrentActivity, new TTAdConfig.Builder() .appId(SDKAPI.AppID) .useTextureView(false) //使用TextureView控件播放视频,默认为SurfaceView,当有SurfaceView冲突的场景,可以使用TextureView .appName("APP测试媒体") .titleBarTheme(TTAdConstant.TITLE_BAR_THEME_DARK) .allowShowNotify(true) //是否允许sdk展示通知栏提示 .allowShowPageWhenScreenLock(true) //是否在锁屏场景支持展示广告落地页 .debug(false) //测试阶段打开,可以通过日志排查问题,上线时去除该调用 .directDownloadNetworkType(TTAdConstant.NETWORK_STATE_WIFI, TTAdConstant.NETWORK_STATE_3G) //允许直接下载的网络状态集合 .supportMultiProcess(false) //是否支持多进程,true支持 .build()); ttAdManager = TTAdSdk.getAdManager(); mTTAdNative = TTAdSdk.getAdManager().createAdNative(CurrentActivity); // Toast.makeText(CurrentActivity, "初始化", Toast.LENGTH_SHORT).show(); }else if(msg.what==SDKUtility.Load_Full_ScreenVideo) { //901121430 Log.i("android", "loadAd"); // Toast.makeText(CurrentActivity, "loadAd", Toast.LENGTH_SHORT).show(); loadAd(SDKAPI.AdsID, TTAdConstant.HORIZONTAL); else if(msg.what==SDKUtility.LoginIn) { Log.i("android", "LoginIn"); }else if(msg.what==SDKUtility.LoginOut) { Log.i("android", "logout"); }else if(msg.what==SDKUtility.Pay) { }else if(msg.what==SDKUtility.OnExit) { }else if(msg.what==SDKUtility.SubmitExtraDataOnEnterGame) { }else if(msg.what==SDKUtility.SubmitExtraDataOnExitGame) { }else if(msg.what==SDKUtility.GamePause) { Log.i("android", "GamePause" } private boolean mHasShowDownloadActive = false; private void loadAd(String codeId, int orientation) { //step4:创建广告请求参数AdSlot,具体参数含义参考文档 AdSlot adSlot = new AdSlot.Builder() .setCodeId(codeId) .setSupportDeepLink(true) .setImageAcceptedSize(1080, 1920) .setRewardName("金币") //奖励的名称 .setRewardAmount(3) //奖励的数量 .setUserID("user123")//用户id,必传参数 .setMediaExtra("media_extra") //附加参数,可选 .setOrientation(orientation) //必填参数,期望视频的播放方向:TTAdConstant.HORIZONTAL 或 TTAdConstant.VERTICAL .build(); //step5:请求广告 mTTAdNative.loadRewardVideoAd(adSlot, new TTAdNative.RewardVideoAdListener() { @Override public void onError(int code, String message) { Log.i("android", message); // Toast.makeText(CurrentActivity, message, Toast.LENGTH_SHORT).show(); UnityPlayer.UnitySendMessage("TouTiaoSDKMgr", "UnCanPlay", ""); } //视频广告加载后,视频资源缓存到本地的回调,在此回调后,播放本地视频,流畅不阻塞。 @Override public void onRewardVideoCached() { // Toast.makeText(CurrentActivity, "onRewardVideoCached", Toast.LENGTH_SHORT).show(); UnityPlayer.UnitySendMessage("TouTiaoSDKMgr", "CanPlay", ""); } //视频广告的素材加载完毕,比如视频url等,在此回调后,可以播放在线视频,网络不好可能出现加载缓冲,影响体验。 @Override public void onRewardVideoAdLoad(TTRewardVideoAd ad) { Log.i("android", "加载完毕"); mttRewardVideoAd = ad; UnityPlayer.UnitySendMessage("TouTiaoSDKMgr", "CanPlay", ""); // mttRewardVideoAd.setShowDownLoadBar(false); mttRewardVideoAd.setRewardAdInteractionListener(new TTRewardVideoAd.RewardAdInteractionListener() { @Override public void onAdShow() { // Toast.makeText(CurrentActivity, "onAdShow", Toast.LENGTH_SHORT).show(); UnityPlayer.UnitySendMessage("TouTiaoSDKMgr", "AdShow", ""); } @Override public void onAdVideoBarClick() { // Toast.makeText(CurrentActivity, "onAdVideoBarClick", Toast.LENGTH_SHORT).show(); } @Override public void onAdClose() { // Toast.makeText(CurrentActivity, "onAdClose", Toast.LENGTH_SHORT).show(); } //视频播放完成回调 @Override public void onVideoComplete() { //Toast.makeText(CurrentActivity, "onVideoComplete", Toast.LENGTH_SHORT).show(); UnityPlayer.UnitySendMessage("TouTiaoSDKMgr", "OnAdPlayComplete", ""); } //视频播放完成后,奖励验证回调,rewardVerify:是否有效,rewardAmount:奖励梳理,rewardName:奖励名称 @Override public void onRewardVerify(boolean rewardVerify, int rewardAmount, String rewardName) { // Toast.makeText(CurrentActivity, rewardVerify+" "+rewardAmount+" "+rewardName, Toast.LENGTH_SHORT).show(); } @Override public void onVideoError() { // Toast.makeText(CurrentActivity, "onVideoError", Toast.LENGTH_SHORT).show(); UnityPlayer.UnitySendMessage("TouTiaoSDKMgr", "OnPlayFail", ""); } }); mttRewardVideoAd.setDownloadListener(new TTAppDownloadListener() { @Override public void onIdle() { mHasShowDownloadActive = false; } @Override public void onDownloadActive(long totalBytes, long currBytes, String fileName, String appName) { if (!mHasShowDownloadActive) { mHasShowDownloadActive = true; // Toast.makeText(CurrentActivity, "下载中,点击下载区域暂停", Toast.LENGTH_SHORT).show(); } } @Override public void onDownloadPaused(long totalBytes, long currBytes, String fileName, String appName) { // Toast.makeText(CurrentActivity, "下载暂停,点击下载区域继续", Toast.LENGTH_SHORT).show(); } @Override public void onDownloadFailed(long totalBytes, long currBytes, String fileName, String appName) { // Toast.makeText(CurrentActivity, "下载失败,点击下载区域重新下载", Toast.LENGTH_SHORT).show(); } @Override public void onDownloadFinished(long totalBytes, String fileName, String appName) { // Toast.makeText(CurrentActivity, "下载失败,点击下载区域重新下载", Toast.LENGTH_SHORT).show(); } @Override public void onInstalled(String fileName, String appName) { // Toast.makeText(CurrentActivity, "安装完成,点击下载区域打开", Toast.LENGTH_SHORT).show(); } }); } }); } }
SDKAIP
package com.sdk.api; import android.R.integer; import android.R.string; import android.text.GetChars; import android.util.Log; import com.cw.androidsdk.MainActivity; public class SDKAPI { public static String AppID=""; public static String AdsID=""; /* * SDK��ʼ�� * */ public static void OnInit(String appId,String adsId) { Log.i("android", "SDKAPI OnInit"); AppID=appId; AdsID=adsId; Log.i("android", "appId:"+appId); Log.i("android", "adsId:"+adsId); MainActivity.myHandler.sendEmptyMessage(SDKUtility.Init); } /* * ���� * */ public static void OnLogIn() { Log.i("android", "SDKAPI OnLogIn"); MainActivity.myHandler.sendEmptyMessage(SDKUtility.LoginIn); } public static void LoadAd() { Log.i("android", "SDKAPI LoadAd"); MainActivity.myHandler.sendEmptyMessage(SDKUtility.Load_Full_ScreenVideo); } public static void PlayAd() { Log.i("android", "SDKAPI PlayAd"); MainActivity.myHandler.sendEmptyMessage(SDKUtility.Play_Full_SrcennVideo); } /* * �dz� * */ public static void OnLogOut() { Log.i("android", "SDKAPI OnLogOut"); MainActivity.myHandler.sendEmptyMessage(SDKUtility.LoginOut); } /* * ֧�� * */ public static void OnPay(float requestAmount ,int productIndex ,String productName,String orderID ) { Log.i("android", "SDKAPI OnPay"); MainActivity.myHandler.sendEmptyMessage(SDKUtility.Pay); } /* * ��Ϸ��ͣ * */ public static void OnGamePause() { Log.i("android", "SDKAPI OnGamePause"); MainActivity.myHandler.sendEmptyMessage(SDKUtility.GamePause); } /* * �ύ������Ϣ *������Ϸ * �˳���Ϸ *����ؿ�* */ public static void OnSubmitExtraData(int id) { } /* * ������Ϸ�ύ���� * */ public static void OnSubmitExtraDataOnExitGame() { Log.i("android", "SDKAPI OnSubmitExtraDataOnExitGame"); MainActivity.myHandler.sendEmptyMessage(SDKUtility.SubmitExtraDataOnExitGame); } /* * �˳���Ϸ�ύ���� * */ public static void OnSubmitExtraDataOnEnterGame() { Log.i("android", "SDKAPI OnSubmitExtraDataOnEnterGame"); MainActivity.myHandler.sendEmptyMessage(SDKUtility.SubmitExtraDataOnEnterGame); } /* * �˳���Ϸ * */ public static void OnExit() { Log.i("android", "SDKAPI OnExit"); MainActivity.myHandler.sendEmptyMessage(SDKUtility.OnExit); } }
SDKUtility
package com.sdk.api; import android.R.integer; public class SDKUtility { public static final int Init=0; public static final int LoginIn=1; public static final int LoginOut=2; public static final int Pay=3; public static final int GamePause=4; public static final int SubmitExtraDataOnEnterGame=5; public static final int SubmitExtraDataOnExitGame=6; public static final int OnExit=7; public static final int Load_Full_ScreenVideo=9; public static final int Play_Full_SrcennVideo=8; }
五 导出Jar包。注意只要导出Src文件。
用好压去打开jar包,里面就是我们这边写的通讯框架的三个文件(如果之前里面没删除unity自带的三个类,这里到处jar包的时候,就会带有那三个类,在给Unity使用的话,会报错,我们也可以在这里手动删除这三个类)
6 下面就是在Unity里面去调用了,将Jar包,Res文件和引用到的库,manifest文件导入到unity里面,目录如下:
7 编写C#脚本去调用Androidd 的接口并且接受返回的回调。
/************* ** Company: DX **SrtiptName:TouTiaoSDKMgr ** Auth: CW ** Des: 文本描述 ** Ver.: V1.0.0 *************/ using UnityEngine; using System.Collections; using UnityEngine.UI; public class TouTiaoSDKMgr : MonoBehaviour { private AndroidJavaClass _jc = null; private Transform Sendertran; public static TouTiaoSDKMgr Instance; public string appID; public string AdsID; public bool IsCanPlay = false; private E_AdsType _currentAdsType = E_AdsType.Nil; void Awake() { Instance = this; _jc = new AndroidJavaClass("com.sdk.api.SDKAPI"); OnInit(); Debug.Log("Awake"); LoadAd(); } public void OnInit() { Debug.Log("OnInit"); _jc.CallStatic("OnInit", appID, AdsID); } public void LoadAd() { Debug.Log("LoadAd"); _jc.CallStatic("LoadAd"); } public void PlayAd() { Debug.Log("PlayAd"); _jc.CallStatic("PlayAd"); _jc.CallStatic("LoadAd"); } /// <summary> /// 播放视频广告 /// </summary> public void PlayVideoAds(E_AdsType adsType, int id, Transform sender = null) { if (IsCanPlay) { PlayAd(); } } public void AdShow() { } public void OnAdPlayComplete() { } public void OnPlayFail() { } public void CanPlay() { IsCanPlay = true; } public void UnCanPlay() { IsCanPlay = false; } }