支持的广告类型
- 开屏广告
- 激励视频
- 模板渲染插屏
- 模板渲染Banner
文件修改记录
- res/xml/file_paths.xml ?
- 工程级build.gradle ?
- res/layout/splash.xml?
- res/values/strings.xml?
- 应用级build.gradle ?
- 清单文件AndroidManifest.xml?
- appsrcorgcocos2dxjavascriptCocosApplication.java?
- appsrcorgcocos2dxjavascriptSplashActivity.java?
- appsrcorgcocos2dxjavascriptAppActivity.java?
注释 ?代表改文件有修改 ?代表新增文件
详细修改内容
修改Android Gradle Plugin Version为3.4.3,修改Gradle Version为5.1.1
res/xml/file_paths.xml ?
在对应目录下创建新文件,文件内容如下
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<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>
工程级build.gradle ?
修改并添加依赖源
buildscript {
repositories {
google()
jcenter()
maven { url 'https://repo1.maven.org/maven2/' }
}
dependencies {
classpath 'com.android.tools.build:gradle:3.4.3'
}
}
allprojects {
repositories {
google()
jcenter()
flatDir {
dirs 'libs'
}
maven {url 'https://artifact.bytedance.com/repository/pangle'}
maven { url 'https://repo1.maven.org/maven2/' }
}
}
res/layout/splash.xml?
在对应目录下创建新文件,文件内容如下
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="#000000">
<FrameLayout
android:id="@+id/splash_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#000000"
>
</FrameLayout>
</LinearLayout>
res/values/strings.xml?
修改文件内容,按照需要自动修改
<resources>
<string name="app_name" translatable="false">应用名称</string>
<string name="app_id" translatable="false">穿山甲ID</string>
<string name="splash_id" translatable="false">开屏广告ID</string>
<string name="video_id" translatable="false">激励视频ID</string>
<string name="express_id" translatable="false">模板渲染插屏ID</string>
<string name="banner_id" translatable="false">模板渲染BannerID</string>
<string name="um_id" translatable="false">友盟ID</string>
<string name="um_channel" translatable="false">友盟平台标识</string>
</resources>
应用级build.gradle ?
因为怕麻烦,直接关闭混淆
minifyEnabled false
shrinkResources false
修改并添加引入
dependencies {
implementation fileTree(dir: '../libs', include: ['*.jar', '*.aar'])
implementation fileTree(dir: 'libs', include: ['*.jar', '*.aar'])
implementation fileTree(dir: "C:/CocosDashboard/resources/.editors/Creator/2.4.5/resources/cocos2d-x/cocos/platform/android/java/libs", include: ['*.jar'])
implementation project(':libcocos2dx')
implementation 'com.pangle.cn:ads-sdk:3.5.0.6'
implementation('com.android.support:support-v4:24.2.0')
implementation 'com.umeng.umsdk:common:9.4.0'
implementation 'com.umeng.umsdk:asms:1.2.3'
}
清单文件AndroidManifest.xml?
根据提供的code自行修改
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.leningmeng.jsdzz.vivoo"
android:installLocation="auto">
<uses-feature android:glEsVersion="0x00020000" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<!--穿山甲uses-permission-->
<!--必要权限-->
<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" />
<!--demo场景用到的权限,不是必须的-->
<uses-permission android:name="android.permission.RECEIVE_USER_PRESENT" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<uses-permission android:name="android.permission.EXPAND_STATUS_BAR" />
<!-- 穿山甲3400版本新增:建议添加“query_all_package”权限,穿山甲将通过此权限在Android R系统上判定广告对应的应用是否在用户的app上安装,避免投放错误的广告,以此提高用户的广告体验。若添加此权限,需要在您的用户隐私文档中声明! -->
<uses-permission
android:name="android.permission.QUERY_ALL_PACKAGES"
tools:ignore="QueryAllPackagesPermission" />
<!--穿山甲uses-permission-->
<application
android:name="org.cocos2dx.javascript.CocosApplication"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:usesCleartextTraffic="true">
<!-- Tell Cocos2dxActivity the name of our .so -->
<meta-data
android:name="android.app.lib_name"
android:value="cocos2djs" />
<activity
android:name="org.cocos2dx.javascript.SplashActivity"
android:configChanges="orientation|keyboardHidden|screenSize|screenLayout"
android:label="@string/app_name"
android:launchMode="singleTask"
android:screenOrientation="portrait"
android:taskAffinity=""
android:theme="@android:style/Theme.NoTitleBar.Fullscreen">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name="org.cocos2dx.javascript.AppActivity"
android:configChanges="orientation|keyboardHidden|screenSize|screenLayout"
android:label="@string/app_name"
android:launchMode="singleTask"
android:screenOrientation="portrait"
android:taskAffinity=""
android:theme="@android:style/Theme.NoTitleBar.Fullscreen">
</activity>
<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" />
</application>
</manifest>
appsrcorgcocos2dxjavascriptCocosApplication.java?
新建CocosApplication并添加内容,注意R.string需要重新引用
package org.cocos2dx.javascript;
import android.app.Application;
import com.bytedance.sdk.openadsdk.TTAdConfig;
import com.bytedance.sdk.openadsdk.TTAdConstant;
import com.bytedance.sdk.openadsdk.TTAdManager;
import com.bytedance.sdk.openadsdk.TTAdSdk;
import com.leningmeng.jsdzz.vivoo.R;
import com.umeng.analytics.MobclickAgent;
import com.umeng.commonsdk.UMConfigure;
public class CocosApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
TTAdSdk.init(this,
new TTAdConfig.Builder()
.appId(this.getString(R.string.app_id))
.useTextureView(true) //默认使用SurfaceView播放视频广告,当有SurfaceView冲突的场景,可以使用TextureView
.appName(this.getString(R.string.app_name))
.titleBarTheme(TTAdConstant.TITLE_BAR_THEME_DARK)//落地页主题
.allowShowNotify(true) //是否允许sdk展示通知栏提示
.debug(true) //测试阶段打开,可以通过日志排查问题,上线时去除该调用
.directDownloadNetworkType(TTAdConstant.NETWORK_STATE_WIFI) //允许直接下载的网络状态集合,没有设置的网络下点击下载apk会有二次确认弹窗,弹窗中会披露应用信息
.supportMultiProcess(false) //是否支持多进程,true支持
.asyncInit(true) //是否异步初始化sdk,设置为true可以减少SDK初始化耗时。3450版本开始废弃~~
.build());
TTAdManager ttAdManager = TTAdSdk.getAdManager();
ttAdManager.requestPermissionIfNecessary(this);
UMConfigure.init(this, this.getString(R.string.um_id), this.getString(R.string.um_channel), UMConfigure.DEVICE_TYPE_PHONE, "");
MobclickAgent.setPageCollectionMode(MobclickAgent.PageMode.AUTO);
}
}
appsrcorgcocos2dxjavascriptSplashActivity.java?
新建SplashActivity文件
package org.cocos2dx.javascript;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.FrameLayout;
import com.bytedance.sdk.openadsdk.AdSlot;
import com.bytedance.sdk.openadsdk.TTAdNative;
import com.bytedance.sdk.openadsdk.TTAdSdk;
import com.bytedance.sdk.openadsdk.TTSplashAd;
import com.leningmeng.jsdzz.vivoo.R;
public class SplashActivity extends Activity {
private FrameLayout mSplashContainer;
String TAG = "SplashActivity";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.splash);
mSplashContainer = (FrameLayout) findViewById(R.id.splash_container);
TTAdNative mTTAdNative = TTAdSdk.getAdManager().createAdNative(this);
AdSlot adSlot = new AdSlot.Builder()
.setCodeId(this.getString(R.string.splash_id))
.setImageAcceptedSize(1080, 1920)
.build();
mTTAdNative.loadSplashAd(adSlot, new TTAdNative.SplashAdListener() {
@Override
public void onError(int i, String s) {
Log.e(TAG,s);
jumpToAppActivity();
}
@Override
public void onTimeout() {
Log.e(TAG,"onTimeout");
jumpToAppActivity();
}
@Override
public void onSplashAdLoad(TTSplashAd ttSplashAd) {
Log.e(TAG,"onSplashAdLoad");
if (ttSplashAd == null) {
return;
}
//获取SplashView
View view = ttSplashAd.getSplashView();
if (view != null && mSplashContainer != null && !SplashActivity.this.isFinishing()) {
mSplashContainer.removeAllViews();
//把SplashView 添加到ViewGroup中,注意开屏广告view:width =屏幕宽;height >=75%屏幕高
mSplashContainer.addView(view);
//设置不开启开屏广告倒计时功能以及不显示跳过按钮,如果这么设置,您需要自定义倒计时逻辑
//ad.setNotAllowSdkCountdown();
ttSplashAd.setSplashInteractionListener(new TTSplashAd.AdInteractionListener(){
@Override
public void onAdClicked(View view, int i) {
}
@Override
public void onAdShow(View view, int i) {
}
@Override
public void onAdSkip() {
jumpToAppActivity();
}
@Override
public void onAdTimeOver() {
jumpToAppActivity();
}
});
}else {
jumpToAppActivity();
}
}
});
}
/**
* 跳转到AppActivity
*/
public void jumpToAppActivity(){
Intent intent = new Intent(this, AppActivity.class);
startActivity(intent);
SplashActivity.this.finish();
}
}
appsrcorgcocos2dxjavascriptAppActivity.java?
替换import引用部分
import org.cocos2dx.lib.Cocos2dxActivity;
import org.cocos2dx.lib.Cocos2dxGLSurfaceView;
import org.cocos2dx.lib.Cocos2dxJavascriptJavaBridge;
import android.os.Bundle;
import android.content.Intent;
import android.content.res.Configuration;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.Gravity;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import com.bytedance.sdk.openadsdk.AdSlot;
import com.bytedance.sdk.openadsdk.TTAdConstant;
import com.bytedance.sdk.openadsdk.TTAdNative;
import com.bytedance.sdk.openadsdk.TTAdSdk;
import com.bytedance.sdk.openadsdk.TTNativeExpressAd;
import com.bytedance.sdk.openadsdk.TTRewardVideoAd;
import com.leningmeng.jsdzz.vivoo.R;
import java.util.List;
替换protected void onCreate为以下内容
String TAG = "AppActivity";
protected Boolean isVideoComplete = false;
protected static String videoCallBackName = "";
static Handler handler;
TTNativeExpressAd bannerAd;
LinearLayout BannerLayout;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Workaround in
// https://stackoverflow.com/questions/16283079/re-launch-of-activity-on-home-button-but-only-the-first-time/16447508
if (!isTaskRoot()) {
// Android launched another instance of the root activity into an existing task
// so just quietly finish and go away, dropping the user back into the activity
// at the top of the stack (ie: the last state of this task)
// Don't need to finish it again since it's finished in super.onCreate .
return;
}
// DO OTHER INITIALIZATION BELOW
SDKWrapper.getInstance().init(this);
handler = new Handler() {
public void handleMessage(Message msg) {
switch (msg.what) {
case 1:
playVideoAd(); //播放视频广告
break;
case 2:
showExpressAd(); //展示模板渲染插屏
break;
case 3:
showBannerAd(); //展示模板渲染插屏
break;
case 4:
hideBannerAd(); //展示模板渲染插屏
break;
default:
break;
}
}
};
BannerLayout= new LinearLayout(AppActivity.this);
BannerLayout.setOrientation(LinearLayout.VERTICAL);
BannerLayout.setGravity(Gravity.CENTER|Gravity.BOTTOM);
FrameLayout.LayoutParams lParams = new FrameLayout.LayoutParams(
FrameLayout.LayoutParams.MATCH_PARENT,
FrameLayout.LayoutParams.MATCH_PARENT);
AppActivity.this.addContentView(BannerLayout,lParams);
}
/**
* 监听Cocos端发送的Banner展示请求
*/
public static void onCocosShowBannerAd() {
Message msg = new Message();
msg.what = 3;
handler.sendMessage(msg);
}
/**
* 监听Cocos端发送的Banner销毁请求
*/
public static void onCocosHideBannerAd() {
Message msg = new Message();
msg.what = 4;
handler.sendMessage(msg);
}
/**
* 展示Banner广告
*/
public void showBannerAd(){
Log.e(TAG,"展示Banner广告");
TTAdNative mTTAdNative = TTAdSdk.getAdManager().createAdNative(this);
AdSlot adSlot = new AdSlot.Builder()
.setCodeId(this.getString(R.string.banner_id)) //广告位id
.setSupportDeepLink(true)
.setAdCount(1)
.setExpressViewAcceptedSize(600,90) //期望模板广告view的size,单位dp
.build();
mTTAdNative.loadBannerExpressAd(adSlot, new TTAdNative.NativeExpressAdListener() {
//请求失败回调
@Override
public void onError(int code, String message) {
Log.e(TAG,message);
}
//请求成功回调
@Override
public void onNativeExpressAdLoad(List<TTNativeExpressAd> ads) {
Log.e(TAG,"Banner广告请求成功"+ads.size());
bannerAd = ads.get(0);
bannerAd.render();
bannerAd.setExpressInteractionListener(new TTNativeExpressAd.ExpressAdInteractionListener() {
//广告点击回调
@Override
public void onAdClicked(View view, int type) {
Log.e(TAG,"onAdClicked");
}
//广告展示回调
@Override
public void onAdShow(View view, int type) {
Log.e(TAG,"onAdShow");
}
//广告渲染失败回调
@Override
public void onRenderFail(View view, String msg, int code) {
Log.e(TAG,"onRenderFail");
}
//广告渲染成功回调
@Override
public void onRenderSuccess(View view, float width, float height) {
Log.e(TAG,"onRenderSuccess");
BannerLayout.removeAllViews();
BannerLayout.addView(bannerAd.getExpressAdView());
}
});
}
});
}
public void hideBannerAd(){
if(bannerAd != null){
bannerAd.destroy();
bannerAd = null;
}
}
/**
* 监听Cocos端发送的插屏广告展示请求
*/
public static void onCocosShowExpressAd() {
Message msg = new Message();
msg.what = 2;
handler.sendMessage(msg);
}
/**
* 展示模板渲染插屏
*/
public void showExpressAd() {
TTAdNative mTTAdNative = TTAdSdk.getAdManager().createAdNative(this);
AdSlot adSlot = new AdSlot.Builder()
.setCodeId(this.getString(R.string.express_id)) //广告位id
.setSupportDeepLink(true)
.setAdCount(1)
.setExpressViewAcceptedSize(300, 300) //期望模板广告view的size,单位dp
.build();
mTTAdNative.loadInteractionExpressAd(adSlot, new TTAdNative.NativeExpressAdListener() {
//请求广告失败
@Override
public void onError(int code, String message) {
}
//请求广告成功
@Override
public void onNativeExpressAdLoad(final List<TTNativeExpressAd> ads) {
ads.get(0).render();
ads.get(0).setExpressInteractionListener(new TTNativeExpressAd.AdInteractionListener() {
//广告关闭回调
@Override
public void onAdDismiss() {
}
//广告点击回调
@Override
public void onAdClicked(View view, int type) {
}
//广告展示回调
@Override
public void onAdShow(View view, int type) {
}
//广告渲染失败回调
@Override
public void onRenderFail(View view, String msg, int code) {
}
//广告渲染成功回调
@Override
public void onRenderSuccess(View view, float width, float height) {
//在渲染成功回调时展示广告,提升体验
ads.get(0).showInteractionExpressAd(AppActivity.this);
}
});
}
});
}
/**
* 监听Cocos端发送的激励视频播放请求
*
* @param callBackName 激励视频完成回调方法名
*/
public static void onCocosPlayVideoAd(String callBackName) {
videoCallBackName = callBackName;
Message msg = new Message();
msg.what = 1;
handler.sendMessage(msg);
}
TTRewardVideoAd videoAd;
public void playVideoAd() {
isVideoComplete = false;
TTAdNative mTTAdNative = TTAdSdk.getAdManager().createAdNative(this);
AdSlot adSlot = new AdSlot.Builder()
.setCodeId(this.getString(R.string.video_id))
.setOrientation(TTAdConstant.VERTICAL)//TTAdConstant.HORIZONTAL 或 TTAdConstant.VERTICAL
.build();
mTTAdNative.loadRewardVideoAd(adSlot, new TTAdNative.RewardVideoAdListener() {
@Override
public void onError(int i, String s) {
Log.e(TAG, s);
}
@Override
public void onRewardVideoAdLoad(TTRewardVideoAd ttRewardVideoAd) {
Log.e(TAG, "onRewardVideoAdLoad");
videoAd = ttRewardVideoAd;
if (videoAd != null) {
videoAd.setRewardAdInteractionListener(new TTRewardVideoAd.RewardAdInteractionListener() {
@Override
public void onAdShow() {
Log.e(TAG, "onAdShow");
}
@Override
public void onAdVideoBarClick() {
Log.e(TAG, "onAdVideoBarClick");
}
@Override
public void onAdClose() {
Log.e(TAG, "onAdClose");
if (isVideoComplete) {
//激励回调
toCocos(videoCallBackName);
}
}
@Override
public void onVideoComplete() {
Log.e(TAG, "onVideoComplete");
isVideoComplete = true;
}
@Override
public void onVideoError() {
Log.e(TAG, "onVideoError");
}
@Override
public void onRewardVerify(boolean b, int i, String s, int i1, String s1) {
Log.e(TAG, "onRewardVerify");
}
@Override
public void onSkippedVideo() {
Log.e(TAG, "onSkippedVideo");
}
});
} else {
Log.e(TAG, "请先加载广告");
}
}
@Override
public void onRewardVideoCached() {
Log.e(TAG, "onRewardVideoCached");
videoAd.showRewardVideoAd(AppActivity.this, TTAdConstant.RitScenes.CUSTOMIZE_SCENES, "scenes_test");
}
});
}
public void toCocos(final String msg) {
Log.e(TAG, msg);
this.runOnGLThread(new Runnable() {
@Override
public void run() {
Cocos2dxJavascriptJavaBridge.evalString(msg + "();");
}
});
}
Cocos端代码示例
激励视频
cc.ad.videoCallBack = function () {
obj.success && obj.success();
}
jsb.reflection.callStaticMethod("org/cocos2dx/javascript/AppActivity", "onCocosPlayVideoAd", "(Ljava/lang/String;)V", "cc.ad.videoCallBack");
banner和插屏
//展示Banner
jsb.reflection.callStaticMethod("org/cocos2dx/javascript/AppActivity", "onCocosShowBannerAd", "()V");
//隐藏Banner
jsb.reflection.callStaticMethod("org/cocos2dx/javascript/AppActivity", "onCocosHideBannerAd", "()V");
//展示插屏
jsb.reflection.callStaticMethod("org/cocos2dx/javascript/AppActivity", "onCocosShowExpressAd", "()V");