写在前面
没记错的话这边帖子在一个月前就开始起稿了,当时是想纪录一下穿山甲的接入过程。然而,项目开了加急,除了敲代码,其他活动基本处于瘫痪状态。现在终于有点时间来整理一下,把这段时间开发中遇到的问题,如何解决的都纪录一下。主要内容
一、穿山甲的接入
对android studio基本不熟,除了会打个包,其他基本看一眼就两眼发蒙。后面查了些资料,总算是接通了。参考资料:
很幸运的找到前辈们写的接入文章,来回参考这些文章才让我把事情顺利做完。非常感谢前辈们的无私分享。1、穿山甲视频广告接入
a、导包:看xxx\jsb-link\frameworks\runtime-src\proj.android-studio\app下是否有libs文件夹,没有就新建一个,导入android-gif-drawable-1.2.6.aar.zip (258.9 KB) open_ad_sdk.zip (2.7 MB) 如此操作之后就可以了,不用再在build.gradle中添加什么依赖了。 b、在manifest中添加权限。 c、添加两个provider。provider的位置是在AndroidManifest.xml文件的如下位置<application>
<activity .../>
...
<provider
android:name="com.bytedance.sdk.openadsdk.TTFileProvider" //TTFileProvider报红?试试依赖中添加: implementation 'com.android.support:support-v4:27.1.1'
android:authorities="包名.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="包名.TTMultiProvider"
android:exported="false" />
...
</application>
d、添加file_paths文件。右键项目名–>new–>xml–>App Actions xml file,填上名字‘file_paths‘,然后修改其中内容为:
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<!--为了适配所有路径可以设置 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>
e、开始撸代码。
org.cocos2dx.javascript.AppActivity 同级目录新建TTAdManagerHolder、TTApplication类
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;
public class TTAdManagerHolder {
public static TTAdNative mTTAdNative;
public static TTRewardVideoAd mttRewardVideoAd;
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:接入网盟广告sdk的初始化操作,详情见接入文档和穿山甲平台说明
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("后台配置的应用id") //
.useTextureView(true) //使用TextureView控件播放视频,默认为SurfaceView,当有SurfaceView冲突的场景,可以使用TextureView
.appName("应用名字")
.titleBarTheme(TTAdConstant.TITLE_BAR_THEME_DARK)
.allowShowNotify(true) //是否允许sdk展示通知栏提示
.allowShowPageWhenScreenLock(true) //是否在锁屏场景支持展示广告落地页
.debug(true) //测试阶段打开,可以通过日志排查问题,上线时去除该调用
.directDownloadNetworkType(TTAdConstant.NETWORK_STATE_WIFI, TTAdConstant.NETWORK_STATE_3G) //允许直接下载的网络状态集合
.supportMultiProcess(false)//是否支持多进程
//.httpStack(new MyOkStack3())//自定义网络库,demo中给出了okhttp3版本的样例,其余请自行开发或者咨询工作人员。
.build();
}
}
//激励视频广告
public static void loadReawrdAd(final String codeId) {
AdSlot adSlot = new AdSlot.Builder()
.setCodeId(codeId)
.setSupportDeepLink(true)
.setImageAcceptedSize(1080, 1920)
.setRewardAmount(1) //奖励的数量
.setUserID("")//用户id,必传参数
.setOrientation(TTAdConstant.VERTICAL) //必填参数,期望视频的播放方向:TTAdConstant.HORIZONTAL 或 TTAdConstant.VERTICAL
.build();
//step5:请求广告
mTTAdNative.loadRewardVideoAd(adSlot, new TTAdNative.RewardVideoAdListener() {
@Override
public void onError(int code, String message) {
Log.e(TAG, message);//加载失败
}
//视频广告加载后,视频资源缓存到本地的回调,在此回调后,播放本地视频,流畅不阻塞。
@Override
public void onRewardVideoCached() {
Log.e(TAG, "rewardVideoAd video cached");
}
@Override
public void onRewardVideoAdLoad(TTRewardVideoAd ad) {
Log.e(TAG, "rewardVideoAd loaded:"+ad);//加载成功
mttRewardVideoAd = ad;
mttRewardVideoAd.setRewardAdInteractionListener(new TTRewardVideoAd.RewardAdInteractionListener() {
@Override
public void onAdShow() {
Log.e(TAG, "rewardVideoAd show");
}
@Override
public void onAdVideoBarClick() {
Log.e(TAG, "rewardVideoAd bar click");
}
@Override
public void onAdClose() {
Log.e(TAG, "rewardVideoAd close");
//关闭后再次加载广告
//codeId = getRewardVideoId();
loadReawrdAd(codeId);
}
//视频播放完成回调
@Override
public void onVideoComplete() {
Log.e(TAG,"rewardVideoAd complete");
AppActivity._ins.jsLog("<=rewardVideoAd complete==>");
}
@Override
public void onVideoError() {
Log.e(TAG,"rewardVideoAd error");
//codeId = getRewardVideoId();
//loadReawrdAd(codeId );
}
//视频播放完成后,奖励验证回调,rewardVerify:是否有效,rewardAmount:奖励梳理,rewardName:奖励名称
@Override
public void onRewardVerify(boolean rewardVerify, int rewardAmount, String rewardName) {
Log.e(TAG,"rewardVideoAd rewardVerify:"+rewardVerify);
//AppActivity.sendTTRewardVerify(rewardVerify); //发放奖励,在这里发放奖励,不知为什么有时会接收失败,我习惯在 onAdClose()里发放奖励。
}
@Override
public void onSkippedVideo() {
}
});
}
});
}
public static void setmTTAdNative(TTAdNative mTTAdNative){
TTAdManagerHolder.mTTAdNative = mTTAdNative;
}
,
package org.cocos2dx.javascript;
import android.app.Application;
public class TTApplication extends Application {
public void onCreate() {
super.onCreate();
TTAdManagerHolder.init(this);
}
}
并在 AndroidManifest.xml中添加一行
<application
...
android:name="org.cocos2dx.javascript.TTApplication"
...
>
f、在AppActivity中的调用
public class AppActivity extends Cocos2dxActivity {
protected void onCreate(Bundle savedInstanceState) {
...
TTAdManager ttAdManager = TTAdManagerHolder.get();
TTAdManagerHolder.get().requestPermissionIfNecessary(this);
TTAdManagerHolder.setmTTAdNative(ttAdManager.createAdNative(getApplicationContext()));
TTAdManagerHolder.loadReawrdAd("123456789");
...
}
//展示穿山甲 视频 广告
public static void showTTReward() {
AppActivity._ins.runOnUiThread(new Runnable() {
@Override
public void run() {
if (TTAdManagerHolder.mttRewardVideoAd != null) {
TTAdManagerHolder.mttRewardVideoAd.showRewardVideoAd(AppActivity._ins);
TTAdManagerHolder.mttRewardVideoAd = null;
} else {
Log.e(AppActivity._ins.TAG, "请先加载广告");
}
}
});
}
}
五一快乐:grin: 2020.4.30
从中遇到的问题:
2、穿山甲插屏广告接入
参照其他前辈们的接入文章。 从中遇到的问题:3、穿山甲信息流广告接入
在接这个之前都不知到这是个什么东西,官方给的解释是“在用户浏览阅读APP的推荐列表页、文章详情页、视频详情页中的原生图文及视频广告”,现在搞完了也不清楚,感觉就是接了一个卡片广告。坐等高手指点②。a、需要一个layout.xml文件。右键项目名-->new-->xml-->Layout xml file,填上名字‘activity_native_express.xml‘,然后修改其中内容为:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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">
<RelativeLayout
android:id="@+id/express_container"
android:layout_width="match_parent"
android:layout_height="350dp"
android:layout_alignParentBottom="true"/>
</RelativeLayout>
(靠底,高350像素,按需调节,信息流广告将展示再express_container中)
b、创建一个空view然后嵌入在cocos的界面上
//我这里写在TTAdManagerHolder, 然后在AppActivity的oncreate中调用的
public static void creatrView(){
//原生的view直接添加到cocos的view内
//R代表你是哪个包名的R文件,然后把创建好的view嵌入在你的cocosview里,不要使用setContentView(R.layout.activity_native_express);创建view
View layout = LayoutInflater.from(AppActivity._ins).inflate(R.layout.activity_native_express, null);
mFrameLayout = new FrameLayout(AppActivity._ins);
mFrameLayout.addView(layout);
FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,ViewGroup.LayoutParams.MATCH_PARENT);
lp.bottomMargin = 0;
AppActivity._ins.addContentView(mFrameLayout,lp);
mExpressContainer = (RelativeLayout)AppActivity._ins.findViewById(R.id.express_container);
//mFrameLayout.addView(view, layoutParams);
//如已绘制SurfaceView则在surfaceView上一层绘制,必须addView之后使用
//getGLSurfaceView().setZOrderMediaOverlay(true);
//cocos的view是否在上层
//getGLSurfaceView().setZOrderOnTop(true);
AppActivity._ins.getGLSurfaceView().getHolder().setFormat(PixelFormat.TRANSLUCENT);
mExpressContainer.setVisibility(View.GONE);
}
其中AppActivity._ins:
public class AppActivity extends Cocos2dxActivity {
...
public static AppActivity _ins;
...
protected void onCreate(Bundle savedInstanceState) {
...
AppActivity._ins = this;
...
}
}
c、撸代码
public static TTNativeExpressAd mttNEAd;
public static View NEView = new View();
public static FrameLayout mFrameLayout; //在creatrView中创建的
public static RelativeLayout mExpressContainer;//在creatrView中创建的
//信息流广告 TTNativeAd
public static void loadTTNativeAd(final String codeId){
AdSlot adSlot = new AdSlot.Builder()
.setCodeId(codeId) //广告位id
.setSupportDeepLink(true)
.setAdCount(1) //请求广告数量为1到3条
.setExpressViewAcceptedSize(350,600) //期望个性化模板广告view的size,单位dp
.setImageAcceptedSize(350,600) //这个参数设置即可,不影响个性化模板广告的size
.build();
mTTAdNative.loadNativeExpressAd(adSlot, new TTAdNative.NativeExpressAdListener() {
@Override
public void onError(int code, String message) {
Log.e(TAG,"loadTTNativeAd error:"+message);
}
@Override
public void onNativeExpressAdLoad(List<TTNativeExpressAd> ads) {
if (ads == null || ads.size() == 0){
Log.e(TAG,"loadFeedAd ad is null");
return;
}
mttNEAd = ads.get(0);
bindAdListener(mttNEAd);
bindDislike(mttNEAd, false);
mttNEAd.render();//调用render开始渲染广告
}
private void bindAdListener(TTNativeExpressAd ad) {
ad.setExpressInteractionListener(new TTNativeExpressAd.ExpressAdInteractionListener() {
@Override
public void onAdClicked(View view, int type) {
Log.e(TAG,"信息流广告被点击");
}
@Override
public void onAdShow(View view, int type) {
Log.e(TAG,"信息流广告展示在mExpressContainer中");
}
@Override
public void onRenderFail(View view, String msg, int code) {
Log.e(TAG,"信息流 render fail");
// loadTTNativeAd(nextCodeId);
}
@Override
public void onRenderSuccess(final View view, float width, float height) {
Log.e(TAG,"信息流广告"+idx+"渲染成功");
NEView = view;
}
});
}
/**
* 设置广告的不喜欢,注意:强烈建议设置该逻辑,如果不设置dislike处理逻辑,则模板广告中的 dislike区域不响应dislike事件。
* @param ad
* @param customStyle 是否自定义样式,true:样式自定义
*/
private void bindDislike(TTNativeExpressAd ad, boolean customStyle) {
//使用默认模板中默认dislike弹出样式
ad.setDislikeCallback(AppActivity._ins, new TTAdDislike.DislikeInteractionCallback() {
@Override
public void onSelected(int position, String value) {
//用户选择不喜欢原因后,移除广告展示
Log.e(TAG,"dislike 移除广告展示");
mExpressContainer.removeAllViews();
}
@Override
public void onCancel() {
Log.e(TAG,"dislike 移除广告展示");
}
});
}
});
}
//显示信息流广告
public static void showTTNativeAd(){
AppActivity._ins.runOnUiThread(new Runnable() {
@Override
public void run() {
mExpressContainer.removeAllViews();
mExpressContainer.addView(NEView);
mExpressContainer.setVisibility(View.VISIBLE);
}
});
}
//关闭信息流广告
public static void closeTTNativeAd(){
AppActivity._ins.runOnUiThread(new Runnable() {
@Override
public void run() {
mExpressContainer.setVisibility(View.GONE);
/*销毁
mExpressContainer.removeAllViews();
if(mttNEAd != null){
mttNEAd.destroy();
mttNEAd = null;
}
NEView = null;
*/
}
});
}
从中遇到的问题:
哎,天天加班,头发掉一地。周末快乐
2020.5.10

