首先非常感謝兩位大神的經(jīng)驗(yàn)分享,我也是參考這兩位的教程 才能一個(gè)安卓小白的情況,實(shí)現(xiàn)cocos creator導(dǎo)出安卓接入穿山甲廣告成功的。csdn 的 MrLizs 以及 橘子呀c
首先閱讀MrLizs的教程貼,我大部分java代碼都是在這里面復(fù)制的,會(huì)方便很多,一定要看清楚,里面的環(huán)境配置,還有安卓工程配置
https://blog.csdn.net/MrLizs/article/details/106728558;
其次可以參考 橘子呀c 的教程貼,接入過(guò)程中遇到很多問(wèn)題也是在這里找到靈感,banner廣告接入我是參考他的后續(xù)教程的
https://blog.csdn.net/qq_34772097/article/details/101468072
另外也要參考穿山甲的接入文檔。
接下來(lái)請(qǐng)先確保你安卓的環(huán)境配置正確 java 安裝android studio 然后在里面安裝ndk sdk 等等。我用的是android studio3.5,一般要求android studio3.0以上,這里推薦用android studio3.5,可能會(huì)避免版本問(wèn)題導(dǎo)致的打包出錯(cuò)。
其實(shí)修改內(nèi)容很少,但是為了和我一樣的android小白少走彎路,我盡量每步都截圖。文件路徑說(shuō)清楚。所以會(huì)顯得文章偏長(zhǎng),沒(méi)辦法作為一個(gè)小白,太容易遇到坑了,打包apk你都不知道點(diǎn)哪個(gè)
下面是我cocos creator2.4構(gòu)建項(xiàng)目的選項(xiàng),APP ABI 這里我建議是全部勾選,因?yàn)槲耶?dāng)時(shí)沒(méi)有全選后面加好代碼某些機(jī)型真機(jī)運(yùn)行報(bào)錯(cuò)。

我是用cocos creator2.4 導(dǎo)出的正式安卓工程目錄,(cocos creator導(dǎo)出的時(shí)候只要構(gòu)建成功就好 ,編譯步驟在android studio加入代碼后再進(jìn)行)下面圖,是我用android studio打開 cocos creator項(xiàng)目根目錄\build\jsb-default\frameworks\runtime-src\proj.android-studio (這個(gè)就是安卓工程的根目錄 ), 我們大部分代碼修改都是位于項(xiàng)目工程的app底下

接著我們?cè)赼pp文件夾底下新建libs文件夾 ,把下載的穿山甲sdk 文件中 open_ad_sdk.aar放入此文件夾內(nèi)。如下圖:

步驟一:修改build.gradle
文件路徑j(luò)sb-default\frameworks\runtime-src\proj.android-studio\app\build.gradle
如果仔細(xì)看app文件夾底下的build.gradle 文件 就會(huì)知道里面已經(jīng)自動(dòng)引入了app/libs 文件夾底下所有的aar文件,但是接下來(lái)還要修改這個(gè)app文件夾底下的build.gradle文件(上圖已經(jīng)指出的文件)。
這是build.gradle原本的文件頭部?jī)?nèi)容

我們需要在 android 內(nèi)容里面加入一行
compileSdkVersion 28
在defaultConfig內(nèi)容里面修改
minSdkVersion 16
targetSdkVersion 28
并且加入
ndk {
//選擇要添加的對(duì)應(yīng)cpu類型的.so庫(kù)。 // 還可以添加 'x86', 'x86_64', 'mips', 'mips64'
abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64'
}
修改后build.gradle如圖下

然后在build.gradle文件里面 找到 dependencies 項(xiàng)在此內(nèi)容里面添加一行代碼;
我這邊的情況是這行代碼不加的話,后面運(yùn)行項(xiàng)目始終報(bào)錯(cuò)找不到 open_ad_sdk 穿山甲sdk里面的廣告代碼文件,這個(gè)是我們公司的安卓大神幫我找到問(wèn)題。我看上面幾篇教程中并沒(méi)有這一塊的修改說(shuō)明。也許他們的項(xiàng)目中沒(méi)有遇到這個(gè)問(wèn)題吧哈哈。這行代碼你們?nèi)绻尤雸?bào)錯(cuò)可以先試著刪除,不過(guò)一般是沒(méi)什么問(wèn)題的
如下圖:
implementation 'com.android.support:appcompat-v7:28.0.0'

步驟二:修改AndroidManifest.xml
文件路徑
jsb-default\frameworks\runtime-src\proj.android-studio\app\AndroidManifest.xml
在app目錄底下打開AndroidManifest.xml
首先添加申請(qǐng)權(quán)限代碼,找到原本的 uses-permission 權(quán)限申請(qǐng)代碼,在之后添加如下代碼
<!-- <!-必要的權(quán)限–>-->
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<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"/>
<!--最好能提供的權(quán)限-->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<!-- 如果有相關(guān)視頻的廣告使用textureview播放,務(wù)必添加,不然黑屏 -->
<uses-permission android:name="android.permission.WAKE_LOCK" />
修改后的如下圖

接著在AndroidManifest.xml 文件中找到 application ,在application內(nèi)容里面加上穿山甲廣告需要的provider 代碼
<provider
android:name="com.bytedance.sdk.openadsdk.TTFileProvider"
android:authorities="${applicationId}.TTFileProvider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths" />
</provider>
<provider
android:name="com.bytedance.sdk.openadsdk.multipro.TTMultiProvider"
android:authorities="${applicationId}.TTMultiProvider"
android:exported="false" />
修改后如下圖

步驟三 添加 file_paths.xml 文件
文件路徑
jsb-default\frameworks\runtime-src\proj.android-studio\res\xml\file_paths.xml
首先在安卓根目錄 proj.android-studio 文件夾底下找到 res文件夾 在里面新建 xml 文件夾,再于xml文件夾內(nèi)新建 file_paths.xml 文件,文件路勁如上面已經(jīng)給出
(另外插一句題外話,如果要修改cocos creator 導(dǎo)出的android項(xiàng)目中文名 res文件夾底下的values/strings.xml 文件里面修改,icon圖標(biāo)文件修改也是位于res文件夾底下mipmap)
文件內(nèi)容代碼
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<!--為了適配所有路徑可以設(shè)置 path = "." -->
<external-path name="tt_external_root" path="." />
<external-path name="tt_external_download" path="Download" />
<external-files-path name="tt_external_files_download" path="Download" />
<files-path name="tt_internal_file_download" path="Download" />
<cache-path name="tt_internal_cache_download" path="Download" />
</paths>
如下圖

步驟四 修改邏輯代碼文件
文件路徑
jsb-default\frameworks\runtime-src\proj.android-studio\src\org\cocos2dx\javascript
接下來(lái)是java調(diào)用穿山甲sdk展示廣告了
首先在proj.android-studio\src\org\cocos2dx\javascript新建TTAdManagerHolder.java 穿山甲sdk配置代碼文件,代碼如下
package org.cocos2dx.javascript;
import android.content.Context;
import com.bytedance.sdk.openadsdk.TTAdConfig;
import com.bytedance.sdk.openadsdk.TTAdConstant;
import com.bytedance.sdk.openadsdk.TTAdManager;
import com.bytedance.sdk.openadsdk.TTAdSdk;
/**
* 可以用一個(gè)單例來(lái)保存TTAdManager實(shí)例,在需要初始化sdk的時(shí)候調(diào)用
*/
public class TTAdManagerHolder {
private static boolean sInit;
public static TTAdManager get() {
if (!sInit) {
throw new RuntimeException("TTAdSdk is not init, please check.");
}
return TTAdSdk.getAdManager();
}
public static void init(Context context) {
doInit(context);
}
//step1:接入網(wǎng)盟廣告sdk的初始化操作,詳情見接入文檔和穿山甲平臺(tái)說(shuō)明
private static void doInit(Context context) {
if (!sInit) {
TTAdSdk.init(context, buildConfig(context));
sInit = true;
}
}
private static TTAdConfig buildConfig(Context context) {
return new TTAdConfig.Builder()
.appId("5001121")//這里填入穿山甲后臺(tái)創(chuàng)建的應(yīng)用id
.useTextureView(true) //使用TextureView控件播放視頻,默認(rèn)為SurfaceView,當(dāng)有SurfaceView沖突的場(chǎng)景,可以使用TextureView
.appName("你的應(yīng)用名稱" )
.titleBarTheme(TTAdConstant.TITLE_BAR_THEME_DARK)
.allowShowNotify(true) //是否允許sdk展示通知欄提示
.allowShowPageWhenScreenLock(true) //是否在鎖屏場(chǎng)景支持展示廣告落地頁(yè)
.debug(true) //測(cè)試階段打開,可以通過(guò)日志排查問(wèn)題,上線時(shí)去除該調(diào)用
.directDownloadNetworkType(TTAdConstant.NETWORK_STATE_WIFI) //允許直接下載的網(wǎng)絡(luò)狀態(tài)集合
.supportMultiProcess(true) //是否支持多進(jìn)程,true支持
.asyncInit(true) //異步初始化sdk,開啟可減少初始化耗時(shí)
//.httpStack(new MyOkStack3())//自定義網(wǎng)絡(luò)庫(kù),demo中給出了okhttp3版本的樣例,其余請(qǐng)自行開發(fā)或者咨詢工作人員。
.build();
}
}
android studio 中如下圖

接著打開proj.android-studio\src\org\cocos2dx\javascript\AppActivity.java 文件
import 引入包的 代碼下加入
import org.cocos2dx.lib.Cocos2dxJavascriptJavaBridge;
import android.util.Log;
import com.bytedance.sdk.openadsdk.AdSlot;
import com.bytedance.sdk.openadsdk.TTAdConstant;
import com.bytedance.sdk.openadsdk.TTAdManager;
import com.bytedance.sdk.openadsdk.TTAdNative;
import com.bytedance.sdk.openadsdk.TTRewardVideoAd;
在AppActivity類里面加入如下代碼
//初始化代碼
static public AppActivity activity;
private String TAG = "cocos日志";
private TTAdNative mTTAdNative;
private TTRewardVideoAd mttRewardVideoAd;
如下圖

在AppActivity類里面的onCreate方法里面加入如下代碼
//穿山甲廣告
TTAdManagerHolder.init(this);
activity = this;
//step1:初始化sdk
TTAdManager ttAdManager = TTAdManagerHolder.get();
//step2:(可選,強(qiáng)烈建議在合適的時(shí)機(jī)調(diào)用):申請(qǐng)部分權(quán)限,如read_phone_state,防止獲取不了imei時(shí)候,下載類廣告沒(méi)有填充的問(wèn)題。
TTAdManagerHolder.get().requestPermissionIfNecessary(this);
//step3:創(chuàng)建TTAdNative對(duì)象,用于調(diào)用廣告請(qǐng)求接口
mTTAdNative = ttAdManager.createAdNative(getApplicationContext());
loadAd("你的激勵(lì)視頻廣告位id", TTAdConstant.VERTICAL);
如下圖

在AppActivity里最底下增加以下方法:
//播放廣告方法,js中調(diào)用此方法。傳入廣告位id codeId
static public void showAd(String codeId) {
Log.e(activity.TAG, "java廣告方法");
activity.runOnUiThread(new Runnable() {
@Override
public void run() {
if (activity.mttRewardVideoAd != null) {
//step6:在獲取到廣告后展示
//該方法直接展示廣告
activity.mttRewardVideoAd.showRewardVideoAd(activity);
//展示廣告,并傳入廣告展示的場(chǎng)景
activity.mttRewardVideoAd = null;
} else {
Log.e(activity.TAG, "請(qǐng)先加載廣告");
}
}
});
}
public void sendReward() {
Log.e(activity.TAG,"獎(jiǎng)勵(lì)發(fā)放java調(diào)用");
activity.runOnGLThread(new Runnable() {
@Override
public void run() {
String js = "adController.adEnd()";
Cocos2dxJavascriptJavaBridge.evalString(js);
Log.e(activity.TAG,"獎(jiǎng)勵(lì)發(fā)放完畢");
}
});
}
private void loadAd(final String codeId, int orientation) {
//step4:創(chuàng)建廣告請(qǐng)求參數(shù)AdSlot,具體參數(shù)含義參考文檔
AdSlot adSlot = new AdSlot.Builder()
.setCodeId(codeId)
.setSupportDeepLink(true)
.setImageAcceptedSize(1080, 1920)
.setRewardAmount(1) //獎(jiǎng)勵(lì)的數(shù)量
.setUserID("1111")//用戶id,必傳參數(shù),穿山甲后臺(tái)可以看到你的用戶id
.setOrientation(orientation) //必填參數(shù),期望視頻的播放方向:TTAdConstant.HORIZONTAL 或 TTAdConstant.VERTICAL
.build();
//step5:請(qǐng)求廣告
mTTAdNative.loadRewardVideoAd(adSlot, new TTAdNative.RewardVideoAdListener() {
@Override
public void onError(int code, String message) {
Log.e(TAG, message);
}
//視頻廣告加載后,視頻資源緩存到本地的回調(diào),在此回調(diào)后,播放本地視頻,流暢不阻塞。
@Override
public void onRewardVideoCached() {
Log.e(TAG, "rewardVideoAd video cached");
}
//視頻廣告的素材加載完畢,比如視頻url等,在此回調(diào)后,可以播放在線視頻,網(wǎng)絡(luò)不好可能出現(xiàn)加載緩沖,影響體驗(yàn)。
@Override
public void onRewardVideoAdLoad(TTRewardVideoAd ad) {
Log.e(TAG, "視頻廣告已經(jīng)加載");
mttRewardVideoAd = ad;
mttRewardVideoAd.setRewardAdInteractionListener(new TTRewardVideoAd.RewardAdInteractionListener() {
@Override
public void onAdShow() {
Log.e(TAG, "視頻廣告播放");
}
@Override
public void onAdVideoBarClick() {
Log.e(TAG, "rewardVideoAd bar click");
}
@Override
public void onAdClose() {
Log.e(TAG, "rewardVideoAd close");
//關(guān)閉后再次加載廣告
loadAd(codeId, TTAdConstant.VERTICAL);
}
//視頻播放完成回調(diào)
@Override
public void onVideoComplete() {
Log.e(TAG,"rewardVideoAd complete");
}
@Override
public void onVideoError() {
Log.e(TAG,"rewardVideoAd error");
}
//視頻播放完成后,獎(jiǎng)勵(lì)驗(yàn)證回調(diào),rewardVerify:是否有效,rewardAmount:獎(jiǎng)勵(lì)梳理,rewardName:獎(jiǎng)勵(lì)名稱
@Override
public void onRewardVerify(boolean rewardVerify, int rewardAmount, String rewardName, int var4, String var5) {
Log.e(TAG,"廣告播放完成回調(diào)");
//發(fā)放獎(jiǎng)勵(lì)
sendReward();
}
@Override
public void onSkippedVideo() {
}
});
}
});
}
如下圖


另外提一句,大家看看就好。上面的java代碼中方法是會(huì)隨著穿山甲sdk變動(dòng)的,不過(guò)頻率還是比較低的。要注意結(jié)合穿山甲官方文檔和demo。比如onRewardVerify這個(gè)方法,老版本是只有三個(gè)參數(shù),我從別的教程中復(fù)制的代碼也只有三個(gè)參數(shù),2020-11-24號(hào)下載的sdk中封裝的onRewardVerify是五個(gè)參數(shù),所以運(yùn)行報(bào)錯(cuò)。之后看到的文檔中是五個(gè)參數(shù),所以這塊也要改成五個(gè)參數(shù),大家根據(jù)自己的情況決定。反正報(bào)錯(cuò)這塊多看日志多百度。我也是安卓小白,但也能解決。
這個(gè)時(shí)候編輯器報(bào)錯(cuò),關(guān)于sdk的引入這些文件都有紅線,可以點(diǎn)擊android studio 按鈕file-》invalidate 按鈕重啟,這樣編輯器就能識(shí)別到文件并且ctrl+鼠標(biāo)左鍵點(diǎn)擊就可以跳轉(zhuǎn)
或者鼠標(biāo)雙擊類名 然后alt+enter 鍵可以import class引入類

這里點(diǎn)擊真機(jī)運(yùn)行選擇你要編譯的項(xiàng)目,項(xiàng)目運(yùn)行成功,廣告播放成功

以下為補(bǔ)充說(shuō)明
另外記得選中你自己的項(xiàng)目名而不是instantapp ,我們修改的文件夾都是proj.android-studio\app底下的build.gradle AndroidManifest.xml 還有skd文件夾libs也是放于app目錄下。如果想編譯instant,記得把a(bǔ)pp文件夾底下的修改,在proj.android-studio\game文件夾底下找到相應(yīng)的文件一起改。
打包測(cè)試

如果遇到真機(jī)運(yùn)行正常,打測(cè)試包build APKS 的時(shí)候報(bào)錯(cuò)沒(méi)有找到穿山甲sdk,可以修改 proj.android-studio\settings.gradle,將:instantapp去掉,這樣就不會(huì)編譯instantapp,如下圖

關(guān)于js調(diào)用java播放廣告代碼,js 代碼 再你想要播放廣告的時(shí)候
/**
* js調(diào)用java廣告播放
* @param type 區(qū)分回調(diào)事件
* @param paragram 回調(diào)事件的參數(shù)
*/
adPlay(type,paragram=false){
this.adType = type;
this.adParagram = paragram;
if(cc.sys.isNative && cc.sys.os == cc.sys.OS_ANDROID) {
cc.log('廣告播放')
jsb.reflection.callStaticMethod("org/cocos2dx/javascript/AppActivity", "showAd","(Ljava/lang/String;)V","你的廣告位id");
}
},
關(guān)于java調(diào)用js 廣告回調(diào)代碼 j
java方面代碼位于AppActivity類修改 sendReward方法中
// java調(diào)用js的全局方法adController的子方法adEnd()
String js = "adController.adEnd()";
Cocos2dxJavascriptJavaBridge.evalString(js);
js方面代碼聲明全局方法adEnd,記得在onload里面,調(diào)用廣告前初始化
/**
* js端廣告回調(diào)全局方法
*/
var self = this;
let foo = {
adEnd : function(){
console.info("js端廣告回調(diào)成功");
//復(fù)活
if(self.adType == "復(fù)活"){
self.revivalAction((self.paragram);
}
}
window["adController"]=foo;
最后補(bǔ)充一個(gè)坑,如果遇到,真機(jī)調(diào)試可以,打包測(cè)試包也可以,但是打包正式包報(bào)錯(cuò)有proguard字眼的。且試過(guò)加了穿山甲文檔中混淆代碼沒(méi)用的??梢栽囋囄疫@個(gè)方法,禁用proguard,但是不推薦。修改proj.android-studio\app\build.gradle文件 ,搜索找到minifyEnabled 與 shrinkResources 修改為false,我是個(gè)安卓小白,暫時(shí)找不到更好的辦法。這個(gè)坑當(dāng)時(shí)困擾很久,幸得群里面道友指點(diǎn)。果然還是做php后端還有小程序網(wǎng)站更適合我
minifyEnabled false
shrinkResources false
最后,如果文章對(duì)你有幫助記得點(diǎn)贊喔,如果接入過(guò)程遇到其他問(wèn)題,可以在下方留言,我會(huì)不定時(shí)看下問(wèn)題,解答我會(huì)的