章鱼广告 SDK-Android 接入文档
注意:
-
本 SDK 最低兼容
Android API 16(Android 4.1 ICS)
-
确保 support v4、v7 包版本不小于 `24.0.0
-
竞胜竞败回传:章鱼广告平台根据媒体传回来的竞胜竞败价格,通过相应算法自动提高出价来获得广告曝光,媒体 RTB 时一定要调用,否则会导致价格出不上去。
一、导入 SDK 依赖
1.1、压缩包目录结构
-
文件目录 目录说明 Octopus/libs/***.aar 项目中依赖的 aar 文件. OctopusSdkDemo 示例工程, 用来方便媒体参考接入. demo-release.apk 示例 APP, 用来演示章鱼广告提供的多种广告展现形式. README.md 章鱼广告 SDK-Android 接入文档.
1.2、导入 SDK 文件
1.2.1、在 app 目录下新建 libs 文件夹.
1.2.2、将 Octopus/libs 目录下的文件拷贝到 libs 文件夹下.
1.2.3、在 app/build.gradle 添加如下代码:
-
android {
compileSdkVersion 28
// 设置gradle编译选项,开发者可以根据自己对平台的选择进行合理配置,为了保证兼容性,默认支持以下两种架构
ndk {
abiFilters 'armeabi-v7a','arm64-v8a'
}
}
repositories {
flatDir {
dirs 'libs'
}
}
dependencies {
// 集成章鱼广告SDK需导入的aar
implementation(name: 'octopus_ad_sdk_1.6.1.9', ext: 'aar')
}
1.3、AndroidManifest 配置
1.3.1、添加访问权限
在 AndroidManifest.xml 文件中添加,建议在您的隐私协议中向开发者声明章鱼聚合 SDK 会获取下述权限并应用于广告投放
-
<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 android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
注意:章鱼广告 SDK 不强制获取可选权限,即使没有获取可选权限 SDK 也能正常运行
1.3.2、overrideLibrary 设置
由于引入的 sdk 支持的最小版本与 app 支持的最小版本可能不一致,需要在 AndroidManifest 文件中添加 overrideLibrary 配置:
-
<uses-sdk tools:overrideLibrary="com.octopus.ad" />
注意:请开发者务必按照上面信息进行注册声明,详情见 Demo。
1.3.3、配置网络权限
在 targetSdkVersion 28 及以上的手机上允许 HTTP(S)网络请求,在“AndroidManifest.xml”做以下配置。
-
<application
...
android:usesCleartextTraffic="true"
>
...
</application>
1.3.4、开启硬件加速
视频广告的 MediaView 内部使用了 TextureView,需要在开启硬件加速的窗口中才能使用。 所以需要在 AndroidManifest.xml 添加如下声明:
-
方式一:
<application
android:hardwareAccelerated="true"
... ...
</application>
方式二:
<activity
android:hardwareAccelerated="true"
... ...
</activity>
1.4、混淆配置
为了保证 Octopus SDK 正常工作, 请务必添加以下 ProGuard 配置打包.
-
# Octopus混淆
-dontwarn com.octopus.**
-keep class com.octopus.** {*;}
二、SDK 初始化
2.1、初始化 SDK
注意:①、初始化 SDK 必须在调用广告接口之前。appId 由运营人员提供
②、建议在 application 里面调用;假如 App 有功能引导,也可点击"立即体验"按钮中调用
③、在主线程中调用 sdk 的初始化(init)方法
2.1.1、如需不需要自定义隐私开关控制,请调用如下方法
-
Octopus.init(applicationContext, appId);
2.1.2、如需自定义隐私开关控制,请调用如下方法
-
Octopus.init(applicationContext, appId , new OctopusAdSdkController());
2.2、隐私信息控制开关
-
/**
* 创建隐私信息控制 实例,媒体可以自主控制是否提供权限给广告sdk使用
* 重要!!重要!!
* 为了保证广告的填充率,注意oaid和imei的配置:
* (1)oaid 开发者可以接入信通院OAID,并传入有效值,如果开发者不传入oaid,sdk会自动获取oaid
* (2)imei的配置与isCanUsePhoneState有关(isCanUsePhoneState配置项默认为true)
* 当isCanUsePhoneState 配置为false,不允许SDK主动获取imei,但是需要接入方主动传入imei
* 当isCanUsePhoneState 配置为true,允许SDK主动获取imei,但必须保证接入方已经动态申请了 Manifest.permission.READ_PHONE_STATE,否则SDK会获取失败
*/
public abstract class OctopusAdSdkController {
/**
* 是否允许SDK主动使用手机硬件参数,如:imei
*
* @return true可以使用,false禁止使用。默认为true
*/
public boolean isCanUsePhoneState() {
return true;
}
/**
* 当isCanUsePhoneState=false时,可传入imei信息,sdk使用您传入的imei信息
* @return imei信息
*/
public String getImei() {
return "";
}
/**
* 开发者可以传入oaid
* 信通院OAID的相关采集——如何获取OAID:
* 1. 移动安全联盟官网http://www.msa-alliance.cn/
* 2. 信通院统一SDK下载http://msa-alliance.cn/col.jsp?id=120
*
* @return oaid
*/
public String getOaid() {
return "";
}
}
2.3、其它特殊设置
2.3.1、设置下载类广告是否直接下载 APP,默认开启下载二次确认弹窗
-
Octopus.setIsDownloadDirect(false); // 是否不弹窗,直接下载。默认为false
2.3.2、设置是否限制个性化广告推荐 (请在用户点击关闭个性化广告推荐时才调用此方法,否则影响广告收益)
-
Octopus.setLimitPersonalAds(false); // 不限制个性化广告推荐。默认为false
2.3.3、设置广告请求超时时长(单位毫秒)
-
Octopus.setTimeout(1000);
三、开屏广告
3.1、添加广告容器
在需要添加开屏广告的 Activity 对应的布局文件添加一个 ViewGroup 来填充广告,例如:
-
<FrameLayout
android:id="@+id/fl_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="@id/rl_bottom" />
3.2、开屏广告接口说明
-
/**
* 先传入adContainer和showAd()配套使用
* @param context 上下文
* @param adSlotId 广告位id,由运营人员提供
* @param adContainer 广告容器
* @param adListener 开屏广告监听器
*/
public SplashAd(Context context, String adSlotId, ViewGroup adContainer, SplashAdListener adListener)
/**
* 不传入adContainer和showAd(ViewGroup adContainer)配套使用
* @param context 上下文
* @param adSlotId 广告位id,由运营人员提供
* @param adListener 开屏广告监听器
*/
public SplashAd(Context context, String adSlotId, SplashAdListener adListener)
/**
* 是否使用SDK内部浏览器打开落地页
* @param isOpenInNativeBrowser 默认false, true使用SDK内部浏览器打开, false使用本地浏览器打开
*/
public void openAdInNativeBrowser(boolean isOpenInNativeBrowser)
/**
* 广告是否加载成功
* @return true表示加载成功
*/
public boolean isLoaded()
/**
* 广告是否加载成功,并且在有效时间内(有做广告预缓存的用这个)
* @return true表示加载成功并且有效
*/
public boolean isValid()
/**
* 广告加载成功后可以获取广告返回价格,单位分
*/
public int getPrice()
/**
* 配合SplashAd(Context context, String adSlotId, ViewGroup adContainer, SplashAdListener adListener)使用
*/
public void showAd()
/**
* 配合SplashAd(Context context, String adSlotId, SplashAdListener adListener)使用
*/
public void showAd(ViewGroup adContainer)
/**
* 资源释放
*/
public void destroy()
3.3、开屏广告回调说明
-
/**
* 开屏广告监听器
*/
SplashAdListener {
/**
* 广告加载成功
*/
void onAdLoaded();
/**
* 素材缓存完成
* @param isSuccess 是否缓存成功
*/
void onAdCacheLoaded(boolean isSuccess);
/**
* 广告展示
*/
void onAdShown();
/**
* 加载失败
* @param errorCode 错误码
*/
void onAdFailedToLoad(int errorCode);
/**
* 广告关闭
*/
void onAdClosed();
/**
* 倒计时回调,返回广告还将被展示的剩余时间。
* 通过这个接口,开发者可以自行决定是否显示倒计时提示,或者还剩几秒的时候显示倒计时
*/
void onAdTick(long millisUnitFinished);
/**
* 广告点击
*/
void onAdClicked();
}
3.4、开屏广告示例
-
创建开屏广告实例:
FrameLayout container = this.findViewById(R.id.fl_container);
SplashAdListener listener = new SplashAdListener() {
@Override
public void onAdLoaded() {
Log.i(TAG, "onAdLoaded");
// 广告在此竞价 mSplashAd.getPrice(); 单位分
// 注意:竞价结束后记得调用竞胜或竞败接口
// 竟胜时候调用(提高ECPM, 提升填充率)
// mSplashAd.sendWinNotice(第二高价格);
// 竟败时候调用(提高ECPM, 提升填充率)
// mSplashAd.sendLossNotice(最高价, ADBidEvent.PRICE_LOW_FILTER,ADBidEvent.OTHER);
}
@Override
public void onAdCacheLoaded(boolean isSuccess) {
Log.i(TAG, "onAdCacheLoaded: " + isSuccess);
// 图片素材和视频资源缓存到本地的回调,在此展示效果最好。
// 注意:视频等资源缓存失败会回调onAdFailedToLoad
// 广告是否加载成功并且在有效时间内
// isSuccess可以用来判断是否缓存成功,没缓存成功也可以播放在线视频
if (mSplashAd.isValid()) {
mSplashAd.showAd();
}
}
@Override
public void onAdShown() {
Log.i(TAG, "onAdShown");
}
@Override
public void onAdFailedToLoad(int errorCode) {
Log.i(TAG, "onAdFailedToLoad:" + errorCode);
jump();
}
@Override
public void onAdClosed() {
Log.i(TAG, "onAdClosed");
jumpWhenAdPageFinish();
}
@Override
public void onAdClicked() {
Log.i(TAG, "onAdClicked");
}
@Override
public void onAdTick(long millisUnitFinished) {
Log.i(TAG, "onAdTick " + millisUnitFinished);
}
};
mSplashAd = new SplashAd(this, slotId, container, listener);
-
开屏页一定要禁止用户对返回按钮的控制,否则将可能导致用户手动退出了 App 而广告无法正常曝光和计费:
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK || keyCode == KeyEvent.KEYCODE_HOME) {
return true;
}
return super.onKeyDown(keyCode, event);
} -
开屏页的 onDestroy 方法中请调用:
@Override
protected void onDestroy() {
if (mSplashAd != null) {
mSplashAd.destroy();
}
super.onDestroy();
} -
解决点击广告后页面跳转问题(点击后应该先跳转到广告落地页,从落地页返回再进入应用主页),请参考 demo 中如下写法
// 如果用户点击广告,需要等待广告页面关闭后再跳转主页面。
public boolean mCanJumpImmediately = false;
// 立即跳转主页面
private void jump() {
startActivity(new Intent(SplashActivity.this, MainActivity.class));
finish();
}
// 如果用户点击广告,需要等待广告页面关闭后再跳转主页面。
private void jumpWhenAdPageFinish() {
if (mCanJumpImmediately) {
jump();
} else {
mCanJumpImmediately = true;
}
}
@Override
protected void onResume() {
super.onResume();
if (mCanJumpImmediately) {
jumpWhenAdPageFinish();
}
mCanJumpImmediately = true;
}
@Override
protected void onPause() {
super.onPause();
mCanJumpImmediately = false;
}
3.5、开屏广告的验证
3.5.1、开屏广告显示,用户点击跳过按钮,可正常跳过(跳转到目标界面)
3.5.2、开屏广告显示,用户正常观看广告若干秒(比如 5 秒),跳过按钮自动消失,可正常跳转(跳转到目标界面)
3.5.3、开屏广告显示,用户点击广告显示广告落地页,关闭广告落地页后跳转到目标界面
- PS:完整流程请参考 Demo 中的 com.octopus.sdk.demo.SplashActivity 的示例代码。
四、原生(信息流)广告
4.1、原生广告接口说明
-
/**
* 原生广告构造方法
* @param context 上下文
* @param adSlotId 广告位id,由运营人员提供
* @param nativeAdListener 原生广告监听
*/
public NativeAd(Context context, String adSlotId, NativeAdListener nativeAdListener)
/**
* 是否使用SDK内部浏览器打开落地页
* @param isOpenInNativeBrowser 默认false, true使用SDK内部浏览器打开, false使用本地浏览器打开
*/
public void openAdInNativeBrowser(boolean isOpenInNativeBrowser)
/**
* 广告加载成功后可以获取广告返回价格,单位分
*/
public int getPrice()
/**
* 加载广告
*/
public void loadAd()
/**
* 广告是否加载成功
* @return true表示加载成功
*/
public boolean isLoaded()
/**
* 广告是否加载成功,并且在有效时间内(有做广告预缓存的用这个)
* @return true表示加载成功并且有效
*/
public boolean isValid()
/**
* 资源释放
*/
public void destroy()
4.2、原生广告回调说明
-
/**
* 原生广告加载监听器
*/
NativeAdListener {
/**
* 广告加载失败
* @param errorCode 错误码
*/
void onAdFailed(int errorCode);
/**
* 广告加载成功
* @param response 原生广告响应数据
*/
void onAdLoaded(NativeAdResponse response);
}
/**
* 原生广告事件监听器
*/
NativeAdEventListener {
/**
* 广告点击
*/
void onAdClick();
/**
* 广告曝光
*/
void onADExposed();
/**
* 广告渲染失败
* @param errorCode 错误码
*/
void onAdRenderFailed(int errorCode);
/**
* 广告关闭
*/
void onAdClose();
}
4.3、原生广告示例
-
创建原生广告实例:
LinearLayout adContainer = findViewById(R.id.ad_container);
mNativeAd = new NativeAd(this, slotId, new NativeAdListener() {
@Override
public void onAdFailed(int errorCode) {
Log.d(TAG, "onAdFailed:" + errorCode);
Toast.makeText(activity, "onAdFailedToLoad reason: " + errorCode, Toast.LENGTH_LONG).show();
}
@Override
public void onAdLoaded(NativeAdResponse response) {
Log.d(TAG, "onAdLoaded");
// 广告是否加载成功并且在有效时间内
if (mNativeAd != null && mNativeAd.isValid()) {
int adWidth = ViewUtil.getScreenWidth(NativeActivity.this);
// 设置广告的宽度单位px(防止SDK获取不到容器的宽度)
response.setAdWidth(adWidth);
showNativeAd(response);
}
// 注意:竞价结束后记得调用竞胜或竞败接口
// 竟胜时候调用(提高ECPM, 提升填充率)
// mNativeAd.sendWinNotice(第二高价格);
// 竟败时候调用(提高ECPM, 提升填充率)
// mNativeAd.sendLossNotice(最高价, ADBidEvent.PRICE_LOW_FILTER,ADBidEvent.OTHER);
});
}
});
// 使用SDK内部浏览器打开落地页(默认为false,设为false的情况下会使用本地浏览器打开)
mNativeAd.openAdInNativeBrowser(true);
mNativeAd.loadAd();
public void showNativeAd(NativeAdResponse response) {
if (response == null) return;
// 渲染原生模板广告有两种方式,二选一
// 方式一:先设置曝光点击监听,再获取原生广告View
response.setNativeAdEventListener(new NativeAdEventListener() {
@Override
public void onAdClick() {
Log.i(TAG, "onAdClick");
}
@Override
public void onADExposed() {
Log.i(TAG, "onADExposed");
}
@Override
public void onAdRenderFailed(int errorCode) {
Log.i(TAG, "onAdRenderFailed");
}
@Override
public void onAdClose() {
Log.i(TAG, "onAdClose");
mAdContainer.removeAllViews();
}
});
// 注册完监听后就可以获取原生广告View
View nativeView = response.getNativeView();
if (nativeView != null && nativeView.getParent() == null) {
mAdContainer.removeAllViews();
mAdContainer.addView(nativeView);
}
// 方式二,直接绑定广告容器和曝光点击监听
response.bindView(mAdContainer, new NativeAdEventListener() {
@Override
public void onAdClick() {
Log.i(TAG, "onAdClick");
}
@Override
public void onADExposed() {
Log.i(TAG, "onADExposed");
}
@Override
public void onAdRenderFailed(int errorCode) {
Log.i(TAG, "onAdRenderFailed");
}
@Override
public void onAdClose() {
Log.i(TAG, "onAdClose");
mAdContainer.removeAllViews();
}
});
} -
在页面的 onDestroy 方法中请调用:
@Override
protected void onDestroy() {
if (mNativeAd != null) {
mNativeAd.destroy();
}
super.onDestroy();
}
- PS:完整流程请参考 Demo 中的 com.octopus.sdk.demo.NativeAdActivity 的示例代码。
五、原生(信息流)自渲染广告
5.1、原生自渲染广告接口说明
-
/**
* 原生广告构造方法
* @param context 上下文
* @param adSlotId 广告位id,由运营人员提供
* @param nativeAdListener 原生广告监听
*/
public NativeAd(Context context, String adSlotId, NativeAdListener nativeAdListener)
/**
* 是否使用SDK内部浏览器打开落地页
* @param isOpenInNativeBrowser 默认false, true使用SDK内部浏览器打开, false使用本地浏览器打开
*/
public void openAdInNativeBrowser(boolean isOpenInNativeBrowser)
/**
* 广告加载成功后可以获取广告返回价格,单位分
*/
public int getPrice()
/**
* 加载广告
*/
public void loadAd()
/**
* 广告是否加载成功
* @return true表示加载成功
*/
public boolean isLoaded()
/**
* 广告是否加载成功,并且在有效时间内(有做广告预缓存的用这个)
* @return true表示加载成功并且有效
*/
public boolean isValid()
/**
* 资源释放
*/
public void destroy()
5.2、原生自渲染广告回调说明
-
/**
* 原生广告加载监听器
*/
NativeAdListener {
/**
* 广告加载失败
* @param errorCode 错误码
*/
void onAdFailed(int errorCode);
/**
* 广告加载成功
* @param response 原生广告响应数据
*/
void onAdLoaded(NativeAdResponse response);
}
/**
* 原生广告事件监听器
*/
NativeAdEventListener {
/**
* 广告点击
*/
void onAdClick();
/**
* 广告曝光
*/
void onADExposed();
/**
* 广告渲染失败
* @param errorCode 错误码
*/
void onAdRenderFailed(int errorCode);
/**
* 广告关闭
*/
void onAdClose();
}
5.3、原生自渲染广告响应说明
-
/**
* 原生广告响应数据
*/
NativeAdResponse {
/**
* 获取广告标题,短文字
*/
String getTitle();
/**
* 获取广告描述,长文字
*/
String getDescription();
/**
* 获取广告按钮文字
*/
String getButtonText();
/**
* 获取 Icon 图片地址
*/
String getIconUrl();
/**
* 获取广告单图图片地址
*/
String getImageUrl();
/**
* 获取图片的地址
*/
List<String> getImgList();
/**
* 获取交互类型
*/
int getInteractionType();
/**
* 获取下载六要素
*/
ComplianceInfo getComplianceInfo();
/**
* 获取下载六要素控件
*/
View getComplianceView(Context context);
/**
* 获取LOGO的Bitmap
*/
Bitmap getLogo(Context context);
/**
* 获取文本LOGO的Bitmap
*/
Bitmap getTextLogo(Context context);
/**
* 获取LOGO的相关信息
*/
ServerResponse.AdLogoInfo getLogoInfo();
/**
* 获取文本LOGO的相关信息
*/
ServerResponse.AdLogoInfo getTextLogoInfo();
/**
* 获取LOGO的链接
*/
String getLogoUrl();
/**
* 获取文本LOGO的链接
*/
String getTextLogoUrl();
/**
* 获取图片的宽度px
*/
int getPictureWidth();
/**
* 获取图片的高度px
*/
int getPictureHeight();
/**
* 判断是不是视频广告
*/
boolean isVideo();
/**
* 获取素材类型
*
* @return MaterialType.SINGLE_IMG 或 MaterialType.VIDEO
*/
int getMaterialType();
/**
* 获取视频播放器组件(视频View对象)
*
* @return 播放器组件
*/
View getVideoView(Context context);
/**
* 获取高斯模糊组件(图片View对象)
*
* @return 高斯模糊组件(图片自适应,不变形)
*/
View getBlurView(Context context);
/**
* 获取原生广告视图
*
* @return 原生广告视图
*/
View getNativeView();
/**
* 添加摇一摇
*
* @param shakeContainer 用于放置摇一摇的容器
* @param shakeViewSize 摇一摇控件的宽高 单位dp
* @param shakeTextSize 摇一摇文案字体大小 单位sp
*/
void addShakeView(ViewGroup shakeContainer, int shakeViewSize, float shakeTextSize);
/**
* 原生模板广告、Banner广告、Draw广告都可以直接设置这个监听,再getNativeView()
*
* @param listener 曝光点击事件监听
*/
void setNativeAdEventListener(NativeAdEventListener listener);
/**
* 原生模板广告也可以调用此方法绑定container和事件监听
* @param adContainer 用于展示广告的容器
* @param listener 曝光点击事件监听
*/
void bindView(ViewGroup adContainer, NativeAdEventListener listener);
/**
* 原生自渲染广告调用此方法绑定container和事件监听
* @param adContainer 用于展示广告的容器
* @param clickViews 可以点击跳转广告的View
* @param listener 曝光点击事件监听
*/
void bindUnifiedView(ViewGroup adContainer, List<View> clickViews, NativeAdEventListener listener);
/**
* 原生自渲染广告调用此方法绑定container和事件监听
*
* @param adContainer 用于展示广告的容器
* @param clickViews 可以点击跳转广告的View
* @param closeViews 可以点击关闭广告的View
* @param listener 曝光点击事件监听
*/
void bindUnifiedView(ViewGroup adContainer, List<View> clickViews, List<View> closeViews, NativeAdEventListener listener);
}
5.4、原生自渲染广告示例
-
创建原生自渲染广告实例:
mNativeAd = new NativeAd(this, slotId, new NativeAdListener() {
@Override
public void onAdFailed(int errorCode) {
Log.d(TAG, "onAdFailed:" + errorCode);
Toast.makeText(activity, "onAdFailedToLoad reason: " + errorCode, Toast.LENGTH_LONG).show();
}
@Override
public void onAdLoaded(NativeAdResponse response) {
Log.d(TAG, "onAdLoaded");
// 广告是否加载成功并且在有效时间内
if (mNativeAd != null && mNativeAd.isValid()) {
unifiedView(response);
}
// 注意:竞价结束后记得调用竞胜或竞败接口
// 竟胜时候调用(提高ECPM, 提升填充率)
// mNativeAd.sendWinNotice(第二高价格);
// 竟败时候调用(提高ECPM, 提升填充率)
// mNativeAd.sendLossNotice(最高价, ADBidEvent.PRICE_LOW_FILTER,ADBidEvent.OTHER);
}
});
//使用SDK内部浏览器打开落地页(默认为false,设为false的情况下会使用本地浏览器打开)
mNativeAd.openAdInNativeBrowser(true);
mNativeAd.loadAd();
//原生自渲染view
private void unifiedView(NativeAdResponse response) {
if (response == null) return;
View unifiedView = LayoutInflater.from(this).inflate(R.layout.item_native_unified_ad_view, null);
RelativeLayout rlContainer = unifiedView.findViewById(R.id.rl_container);
FrameLayout adVideo = unifiedView.findViewById(R.id.ad_video);
ImageView adImage = unifiedView.findViewById(R.id.ad_image);
ImageView adIcon = unifiedView.findViewById(R.id.ad_icon);
TextView adTitle = unifiedView.findViewById(R.id.ad_title);
TextView adDesc = unifiedView.findViewById(R.id.ad_desc);
Button adButton = unifiedView.findViewById(R.id.ad_button);
ImageView adLogo = unifiedView.findViewById(R.id.ad_logo);
ImageView adLogoText = unifiedView.findViewById(R.id.ad_logo_text);
ImageView adClose = unifiedView.findViewById(R.id.ad_close);
FrameLayout adCompliance = unifiedView.findViewById(R.id.ad_compliance);
Log.i("OctopusDemo", TAG
+ "response imageUrl:" + response.getImageUrl()
+ "\n;IconUrl:" + response.getIconUrl()
+ "\n;getTitle:" + response.getTitle()
+ "\n;getDescription:" + response.getDescription()
+ "\n;getButtonText:" + response.getButtonText()
+ "\n;getLogoUrl:" + response.getLogoUrl()
+ "\n;getTextLogoUrl:" + response.getTextLogoUrl()
);
// 返回广告的标题
String title = response.getTitle();
if (!TextUtils.isEmpty(title)) {
adTitle.setVisibility(View.VISIBLE);
adTitle.setText(title);
}
// 返回广告的描述文本信息
String description = response.getDescription();
if (!TextUtils.isEmpty(description)) {
adDesc.setVisibility(View.VISIBLE);
adDesc.setText(description);
}
// 返回广告的AppIcon的图片URL
String iconUrl = response.getIconUrl();
if (!TextUtils.isEmpty(iconUrl)) {
// 需要开发者自己处理图片URL,可使用图片加载框架去处理,本示例使用glide加载仅供参考
Glide.with(this).load(iconUrl).into(adIcon);
}
// 判断是否是视频有两种方式,二选一就可以
if (response.isVideo() || response.getMaterialType() == MaterialType.VIDEO) {
// 获取视频组件
View view = response.getVideoView(this);
if (view != null) {
// 视频容器背景默认设置为黑色
adVideo.setBackgroundColor(Color.BLACK);
// 视频居中展示
FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT, Gravity.CENTER);
adVideo.addView(view, layoutParams);
}
} else {
// 图片渲染有两种,一种是直接拿渲染好的高斯模糊组件,防止图片变形
// 方法一:获取高斯模糊组件
View view = response.getBlurView(this);
FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT, Gravity.CENTER);
adVideo.addView(view, layoutParams);
// 方法二:自己使用广告返回的图片URL
String imageUrl = response.getImageUrl();
if (!TextUtils.isEmpty(imageUrl)) {
// 需要开发者自己处理图片URL,可使用图片加载框架去处理,本示例使用glide加载仅供参考
Glide.with(this).load(imageUrl).into(adImage);
}
}
// 返回点击按钮的文本信息
adButton.setText(response.getButtonText());
// 请开发者务必自己实现加入sdk的logo及广告字样
// 返回广告的logoURL
String logoUrl = response.getLogoUrl();
if (!TextUtils.isEmpty(logoUrl)) {
Glide.with(this).load(logoUrl).into(adLogo);
}
// 返回广告的文字logoURL
String textLogoUrl = response.getTextLogoUrl();
if (!TextUtils.isEmpty(textLogoUrl)) {
Glide.with(this).load(textLogoUrl).into(adLogoText);
}
// 获取交互类型,判断是否是下载广告
if (response.getInteractionType() == NativeAdResponse.INTERACTION_TYPE_DOWNLOAD) {
// 获取广告下载六要素
ComplianceInfo complianceInfo = response.getComplianceInfo();
// 可以选择自己添加下载六要素
// 也可以直接添加下载六要素控件
if (complianceInfo != null) {
// 下载六要素默认为屏幕宽度
// View complianceView = response.getComplianceView(this);
// 下载六要素指定宽度,单位dp,用于缩放文字比例
View complianceView = response.getComplianceView(this, 360);
FrameLayout.LayoutParams complianceParams = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.WRAP_CONTENT);
adCompliance.addView(complianceView, complianceParams);
}
}
// 添加摇一摇 shakeViewSize:摇一摇控件的宽高,单位dp shakeTextSize 摇一摇文案字体大小,单位sp
response.addShakeView(rlContainer, 100, 10);
// 把自定义View添加到广告容器里面
mAdContainer.removeAllViews();
mAdContainer.addView(unifiedView);
// 把允许点击的View添加到集合里面
ArrayList<View> clickViews = new ArrayList<>();
clickViews.add(adImage);
clickViews.add(adButton);
// 把允许关闭的View添加到集合里面
ArrayList<View> closeViews = new ArrayList<>();
closeViews.add(adClose);
// 注册原生自渲染广告的曝光点击事件,必须调用
response.bindUnifiedView(mAdContainer, clickViews, closeViews, new NativeAdEventListener() {
@Override
public void onAdClick() {
Log.i(TAG, "onAdClick");
}
@Override
public void onADExposed() {
Log.i(TAG, "onADExposed");
}
@Override
public void onAdRenderFailed(int errorCode) {
Log.i(TAG, "onAdRenderFailed");
Toast.makeText(NativeUnifiedActivity.this, "onAdRenderFailed reason: " + errorCode, Toast.LENGTH_SHORT).show();
}
@Override
public void onAdClose() {
Log.i(TAG, "onAdClose");
mAdContainer.removeAllViews();
}
});
}
-
R.layout.item_native_unified_ad_view 布局文件:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<RelativeLayout
android:id="@+id/rl_container"
android:layout_width="match_parent"
android:layout_height="200dp">
<FrameLayout
android:id="@+id/ad_video"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<ImageView
android:id="@+id/ad_image"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:adjustViewBounds="true"
android:contentDescription="@null"
android:scaleType="fitXY" />
<FrameLayout
android:id="@+id/ad_compliance"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<ImageView
android:id="@+id/ad_close"
android:layout_width="15dp"
android:layout_height="15dp"
android:layout_alignParentEnd="true"
android:layout_margin="5dp"
android:contentDescription="@null"
android:src="@drawable/oct_close" />
</RelativeLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:layout_marginBottom="10dp">
<ImageView
android:id="@+id/ad_icon"
android:layout_width="60dp"
android:layout_height="60dp"
android:layout_centerVertical="true"
android:adjustViewBounds="true"
android:contentDescription="@null"
android:scaleType="fitCenter"
android:visibility="gone" />
<Button
android:id="@+id/ad_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:layout_marginEnd="5dp"
android:layout_marginRight="5dp"
android:contentDescription="@null"
android:importantForAccessibility="no" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginStart="5dp"
android:layout_marginLeft="5dp"
android:layout_toStartOf="@+id/ad_button"
android:layout_toLeftOf="@+id/ad_button"
android:layout_toEndOf="@+id/ad_icon"
android:layout_toRightOf="@+id/ad_icon"
android:orientation="vertical">
<TextView
android:id="@+id/ad_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#000000"
android:textSize="14sp" />
<TextView
android:id="@+id/ad_desc"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:textColor="#000000"
android:textSize="12sp" />
</LinearLayout>
</RelativeLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginVertical="2dp">
<ImageView
android:id="@+id/ad_logo_text"
android:layout_width="32dp"
android:layout_height="16dp"
android:layout_alignParentStart="true"
android:layout_alignParentLeft="true"
android:layout_marginStart="5dp"
android:layout_marginLeft="5dp"
android:contentDescription="@null"
android:scaleType="fitCenter" />
<ImageView
android:id="@+id/ad_logo"
android:layout_width="13dp"
android:layout_height="13dp"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:layout_marginEnd="5dp"
android:layout_marginRight="5dp"
android:contentDescription="@null"
android:scaleType="fitCenter" />
</RelativeLayout>
</LinearLayout>
-
在页面的 onDestroy 方法中请调用:
@Override
protected void onDestroy() {
if (mNativeAd != null){
mNativeAd.destroy();
}
super.onDestroy();
}
- PS:完整流程请参考 Demo 中的 com.octopus.sdk.demo.NativeUnifiedActivity 的示例代码。
六、Draw(信息流)广告
6.1、Draw 广告接口说明
-
/**
* Draw广告构造方法
* @param context 上下文
* @param adSlotId 广告位id,由运营人员提供
* @param nativeAdListener Draw广告监听
*/
public DrawAd(Context context, String adSlotId, DrawAdListener drawAdListener)
/**
* 是否使用SDK内部浏览器打开落地页
* @param isOpenInNativeBrowser 默认false, true使用SDK内部浏览器打开, false使用本地浏览器打开
*/
public void openAdInNativeBrowser(boolean isOpenInNativeBrowser)
/**
* 广告加载成功后可以获取广告返回价格,单位分
*/
public int getPrice()
/**
* 加载广告
*/
public void loadAd()
/**
* 广告是否加载成功
* @return true表示加载成功
*/
public boolean isLoaded()
/**
* 广告是否加载成功,并且在有效时间内(有做广告预缓存的用这个)
* @return true表示加载成功并且有效
*/
public boolean isValid()
/**
* 资源释放
*/
public void destroy()
6.2、Draw 广告回调说明
-
/**
* Draw广告加载监听器
*/
DrawAdListener {
/**
* 广告加载失败
* @param errorCode 错误码
*/
void onAdFailed(int errorCode);
/**
* 广告加载成功
* @param response Draw广告响应数据
*/
void onAdLoaded(NativeAdResponse response);
}
/**
* Draw广告事件监听器
*/
NativeAdEventListener {
/**
* 广告点击
*/
void onAdClick();
/**
* 广告曝光
*/
void onADExposed();
/**
* 广告渲染失败
* @param errorCode 错误码
*/
void onAdRenderFailed(int errorCode);
/**
* 广告关闭
*/
void onAdClose();
}
6.3、Draw 广告示例
-
创建 Draw 广告实例:
mDrawAd = new DrawAd(this, mSlotId, new DrawAdListener() {
@Override
public void onAdFailed(int errorCode) {
Log.i(TAG, "onAdFailed:" + errorCode);
Toast.makeText(mContext, "onAdFailedToLoad reason: " + errorCode, Toast.LENGTH_LONG).show();
}
@Override
public void onAdLoaded(NativeAdResponse response) {
Log.i(TAG, "onAdLoaded");
// 广告是否加载成功并且在有效时间内
if (mDrawAd != null && mDrawAd.isValid()) {
List<TestItem.NormalVideo> normalVideoList = getTestVideo();
for (TestItem.NormalVideo normalVideo : normalVideoList) {
mDrawList.add(new TestItem(normalVideo, null));
}
int random = (int) (Math.random() * 100);
int index = random % normalVideoList.size();
if (index == 0) {
index++;
}
mDrawList.add(index, new TestItem(null, response));
mRecyclerAdapter.notifyDataSetChanged();
}
// 注意:竞价结束后记得调用竞胜或竞败接口
// 竟胜时候调用(提高ECPM, 提升填充率)
// mDrawAd.sendWinNotice(第二高价格);
// 竟败时候调用(提高ECPM, 提升填充率)
// mDrawAd.sendLossNotice(最高价, ADBidEvent.PRICE_LOW_FILTER,ADBidEvent.OTHER);
}
});
// 使用SDK内部浏览器打开落地页(默认为false,设为false的情况下会使用本地浏览器打开)
mDrawAd.openAdInNativeBrowser(true);
mDrawAd.loadAd();
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder viewHolder, int position) {
DrawViewHolder drawViewHolder = (DrawViewHolder) viewHolder;
item.response.setNativeAdEventListener(new NativeAdEventListener() {
@Override
public void onAdClick() {
Log.i(TAG, "onAdClick");
}
@Override
public void onADExposed() {
Log.i(TAG, "onADExposed");
}
@Override
public void onAdRenderFailed(int errorCode) {
Log.i(TAG, "onAdRenderFailed");
}
@Override
public void onAdClose() {
Log.i(TAG, "onAdClose");
}
});
View nativeView = item.response.getNativeView();
if (nativeView != null && nativeView.getParent() == null) {
drawViewHolder.mVideoContainer.removeAllViews();
drawViewHolder.mVideoContainer.addView(nativeView);
}
} -
在页面的 onDestroy 方法中请调用:
@Override
protected void onDestroy() {
if (mDrawAd != null) {
mDrawAd.destroy();
}
super.onDestroy();
}
- PS:完整流程请参考 Demo 中的 com.octopus.sdk.demo.DrawActivity 的示例代码。
七、插屏广告
7.1、插屏广告接口说明
-
/**
* 插屏广告构造函数
* @param context 上下文
* @param adSlotId 广告位id,由运营人员提供
* @param adListener 插屏广告监听
*/
public InterstitialAd(Context context, String adSlotId, InterstitialAdListener adListener)
/**
* 是否使用SDK内部浏览器打开落地页
* @param isOpenInNativeBrowser 默认false, true使用SDK内部浏览器打开, false使用本地浏览器打开
*/
public void openAdInNativeBrowser(boolean isOpenInNativeBrowser)
/**
* 广告是否加载成功
* @return true表示加载成功
*/
public boolean isLoaded()
/**
* 广告是否加载成功,并且在有效时间内(有做广告预缓存的用这个)
* @return true表示加载成功并且有效
*/
public boolean isValid()
/**
* 广告加载
*/
public void loadAd()
/**
* 广告加载成功后可以获取广告返回价格,单位分
*/
public int getPrice()
/**
* 广告展示
*/
public void show(Activity activity)
/**
* 资源释放
*/
public void destroy()
7.2、插屏广告回调说明
-
/**
* 插屏广告监听器
*/
InterstitialAdListener {
/**
* 广告加载失败
* @param errorCode 错误码
*/
void onAdFailedToLoad(int errorCode);
/**
* 广告加载成功
*/
void onAdLoaded();
/**
* 素材缓存完成
* @param isSuccess 是否缓存成功
*/
void onAdCacheLoaded(boolean isSuccess);
/**
* 广告展示
*/
void onAdShown();
/**
* 广告关闭
*/
void onAdClosed();
/**
* 广告点击
*/
void onAdClick();
}
7.3、插屏广告示例
-
创建插屏广告实例:
mInterstitialAd = new InterstitialAd(this, slotId, new InterstitialAdListener() {
@Override
public void onAdClosed() {
Log.i(TAG, "onAdClosed");
}
@Override
public void onAdClicked() {
Log.i(TAG, "onAdClicked");
}
@Override
public void onAdFailedToLoad(int errorCode) {
Log.i(TAG, "onAdFailedToLoad");
}
@Override
public void onAdShown() {
Log.i(TAG, "onAdShown");
}
@Override
public void onAdLoaded() {
Log.i(TAG, "onAdLoaded");
// 广告在此竞价 mInterstitialAd.getPrice(); 单位分
// 注意:竞价结束后记得调用竞胜或竞败接口
// 竟胜时候调用(提高ECPM, 提升填充率)
// mInterstitialAd.sendWinNotice(第二高价格);
// 竟败时候调用(提高ECPM, 提升填充率)
// mInterstitialAd.sendLossNotice(最高价, ADBidEvent.PRICE_LOW_FILTER,ADBidEvent.OTHER);
}
@Override
public void onAdCacheLoaded(boolean isSuccess) {
Log.i(TAG, "onAdCacheLoaded: " + isSuccess);
// 图片素材和视频资源缓存到本地的回调,在此展示效果最好.
// 注意:视频等资源缓存失败会回调onAdFailedToLoad
// isSuccess可以用来判断是否缓存成功,没缓存成功也可以播放在线视频
showInterstitial();
}
});
// 使用SDK内部浏览器打开落地页(默认为false,设为false的情况下会使用本地浏览器打开)
mInterstitialAd.openAdInNativeBrowser(true);
mInterstitialAd.loadAd();
// 展示插屏广告
private void showInterstitial() {
// 广告是否加载成功并且在有效时间内
if (mInterstitialAd != null && mInterstitialAd.isValid()) {
mInterstitialAd.show(InterstitialActivity.this);
}
} -
在页面的 onDestroy 方法中请调用:
@Override
protected void onDestroy() {
if (mInterstitialAd != null){
mInterstitialAd.destroy();
}
super.onDestroy();
}
- PS: 完整流程请参考 Demo 中的 com.octopus.sdk.demo.InterstitialActivity 的示例代码。
八、全屏视频广告
8.1、全屏视频广告接口说明
-
/**
* 全屏视频广告构造函数
* @param context 上下文
* @param adSlotId 广告位id,由运营人员提供
* @param adListener 全屏视频广告监听
*/
public FullScreenVideoAd(Context context, String adSlotId, FullScreenVideoAdListener adListener)
/**
* 是否使用SDK内部浏览器打开落地页
* @param isOpenInNativeBrowser 默认false, true使用SDK内部浏览器打开, false使用本地浏览器打开
*/
public void openAdInNativeBrowser(boolean isOpenInNativeBrowser)
/**
* 广告是否加载成功
* @return true表示加载成功
*/
public boolean isLoaded()
/**
* 广告是否加载成功,并且在有效时间内(有做广告预缓存的用这个)
* @return true表示加载成功并且有效
*/
public boolean isValid()
/**
* 广告加载
*/
public void loadAd()
/**
* 广告加载成功后可以获取广告返回价格,单位分
*/
public int getPrice()
/**
* 广告展示
*/
public void show(Activity activity)
/**
* 资源释放
*/
public void destroy()
8.2、全屏视频广告回调说明
-
/**
* 全屏视频广告监听器
*/
FullScreenVideoAdListener {
/**
* 广告加载失败
* @param errorCode 错误码
*/
void onAdFailedToLoad(int errorCode);
/**
* 广告加载成功
*/
void onAdLoaded();
/**
* 素材缓存完成
* @param isSuccess 是否缓存成功
*/
void onAdCacheLoaded(boolean isSuccess);
/**
* 广告展示
*/
void onAdShown();
/**
* 广告关闭
*/
void onAdClosed();
/**
* 广告点击
*/
void onAdClick();
}
8.3、全屏视频广告示例
-
创建全屏视频广告实例:
mFullScreenVideoAd = new FullScreenVideoAd(this, mSlotId, new FullScreenVideoAdListener() {
@Override
public void onAdClosed() {
Log.i(TAG, "onAdClosed");
}
@Override
public void onAdClicked() {
Log.i(TAG, "onAdClicked");
}
@Override
public void onAdFailedToLoad(int errorCode) {
Log.i(TAG, "onAdFailedToLoad" + errorCode);
}
@Override
public void onAdShown() {
Log.i(TAG, "onAdShown");
}
@Override
public void onAdLoaded() {
Log.i(TAG, "onAdLoaded");
// 广告在此竞价 mFullScreenVideoAd.getPrice(); 单位分
// 注意:竞价结束后记得调用竞胜或竞败接口
// 竟胜时候调用(提高ECPM, 提升填充率)
// mFullScreenVideoAd.sendWinNotice(第二高价格);
// 竟败时候调用(提高ECPM, 提升填充率)
// mFullScreenVideoAd.sendLossNotice(最高价, ADBidEvent.PRICE_LOW_FILTER,ADBidEvent.OTHER);
}
@Override
public void onAdCacheLoaded(boolean isSuccess) {
Log.i(TAG, "onAdCacheLoaded: " + isSuccess);
// 图片素材和视频资源缓存到本地的回调,在此展示效果最好.
// 注意:视频等资源缓存失败会回调onAdFailedToLoad
// isSuccess可以用来判断是否缓存成功,没缓存成功也可以播放在线视频
showFullScreenVideo();
}
});
// 使用SDK内部浏览器打开落地页(默认为false,设为false的情况下会使用本地浏览器打开)
mFullScreenVideoAd.openAdInNativeBrowser(true);
mFullScreenVideoAd.loadAd();
// 展示全屏视频广告
private void showFullScreenVideo() {
// 广告是否加载成功并且在有效时间内
if (mFullScreenVideoAd != null && mFullScreenVideoAd.isValid()) {
mFullScreenVideoAd.show(FullScreenVideoActivity.this);
}
} -
在页面的 onDestroy 方法中请调用:
@Override
protected void onDestroy() {
if (mFullScreenVideoAd != null) {
mFullScreenVideoAd.destroy();
}
super.onDestroy();
}
- PS: 完整流程请参考 Demo 中的 com.octopus.sdk.demo.FullScreenVideoActivity 的示例代码。
九、激励视频
9.1、激励视频接口说明
-
/**
* 激励视频广告构造函数
* @param context 上下文
* @param slotId 广告位id,由运营人员提供
* @param listener 激励视频广告监听
*/
public RewardVideoAd(Context context, String slotId, RewardVideoAdListener listener)
/**
* 是否使用SDK内部浏览器打开落地页
* @param isOpenInNativeBrowser 默认false, true使用SDK内部浏览器打开, false使用本地浏览器打开
*/
public void openAdInNativeBrowser(boolean isOpenInNativeBrowser)
/**
* 广告加载
*/
public void loadAd()
/**
* 广告是否加载成功
* @return true表示加载成功
*/
public boolean isLoaded()
/**
* 广告是否加载成功,并且在有效时间内(有做广告预缓存的用这个)
* @return true表示加载成功并且有效
*/
public boolean isValid()
/**
* 广告加载成功后可以获取广告返回价格,单位分
*/
public int getPrice()
/**
* 广告展示
*/
public void show(Activity activity)
/**
* 服务端验证可以传入开发者⾃定义的附加参数
*/
public void setExtraData(String extraData)
/**
* 服务端验证可以传入开发者系统中的⽤户id
*/
public void setUserId(String userId)
/**
* 激励视频暂停
*/
public void pause()
/**
* 激励视频恢复
*/
public void resume()
/**
* 资源释放
*/
public void destroy()
9.2、激励视频回调说明
-
/**
* 激励视频广告监听器
*/
RewardVideoAdListener {
/**
* 获得奖励,在该回调中做奖励操作
*/
void onRewarded(RewardItem reward);
/**
* 广告加载失败
*/
void onRewardVideoAdFailedToLoad(int errorCode);
/**
* 广告加载成功
*/
void onRewardVideoAdLoaded();
/**
* 素材缓存完成
* @param isSuccess 是否缓存成功
*/
void onRewardVideoCached(boolean isSuccess);
/**
* 广告曝光展示
*/
void onRewardVideoAdShown();
/**
* 广告关闭
*/
void onRewardVideoAdClosed();
/**
* 广告点击
*/
void onRewardVideoAdClicked();
/**
* 广告播放完成
*/
oid onRewardVideoAdComplete();
}
9.3、激励视频示例
-
创建激励视频实例:
// 加载广告 注意:每次加载的时候都要new一个RewardVideoAd,防止重复同一个广告
private void loadRewardVideo() {
mRewardVideoAd = new RewardVideoAd(this, slotId, new RewardVideoAdListener() {
@Override
public void onRewarded(RewardItem reward) {
Log.d(TAG, "onRewarded:" + reward.getAmount() + "==" + reward.getType());
// 完成激励视频观看时长任务
}
@Override
public void onRewardVideoAdClosed() {
Log.d(TAG, "onRewardVideoAdClosed");
// 激励视频关闭或者跳过
}
@Override
public void onRewardVideoAdShown() {
Log.d(TAG, "onRewardVideoAdShown");
// 激励视频曝光
}
@Override
public void onRewardVideoAdFailedToLoad(int errorCode) {
Log.d(TAG, "onRewardVideoAdFailedToLoad:" + errorCode);
// 广告加载失败或者视频播放失败
}
@Override
public void onRewardVideoAdLoaded() {
Log.d(TAG, "onRewardVideoAdLoaded");
// 广告加载成功,可以直接展示激励视频
// 视频广告的素材加载完毕,比如视频url等,在此回调后,如果视频没缓存过,会播放在线视频,网络不好可能出现加载缓冲,影响体验。
// 注意:竞价结束后记得调用竞胜或竞败接口
// 竟胜时候调用(提高ECPM, 提升填充率)
// mRewardVideoAd.sendWinNotice(第二高价格);
// 竟败时候调用(提高ECPM, 提升填充率)
// mRewardVideoAd.sendLossNotice(最高价, ADBidEvent.PRICE_LOW_FILTER,ADBidEvent.OTHER);
}
@Override
public void onRewardVideoCached(boolean isSuccess) {
Log.i(TAG, "onAdRewardVideoCached: " + isSuccess);
// 视频广告加载后,视频资源缓存到本地的回调,在此回调后,播放本地视频,流畅不阻塞。
// isSuccess可以用来判断是否缓存成功,没缓存成功也可以播放在线视频
showRewardVideo();
}
@Override
public void onRewardVideoAdClicked() {
Log.d(TAG, "onRewardVideoAdClicked");
// 激励视频有点击
}
@Override
public void onRewardVideoAdComplete() {
Log.d(TAG, "onRewardVideoAdComplete");
// 激励视频播放完成
}
});
// 使用SDK内部浏览器打开落地页(默认为false,设为false的情况下会使用本地浏览器打开)
mRewardVideoAd.openAdInNativeBrowser(true);
mRewardVideoAd.loadAd();
}
// 展示激励视频
private void showRewardVideo() {
if (mRewardVideoAd != null && mRewardVideoAd.isValid()) {
mRewardVideoAd.show();
}
} -
在页面的 onPause(),onResume(),onDestroy 方法中请调用:
@Override
public void onPause() {
super.onPause();
mRewardVideoAd.pause();
}
@Override
public void onResume() {
super.onResume();
mRewardVideoAd.resume();
}
@Override
protected void onDestroy() {
if (mRewardedVideoAd != null){
mRewardedVideoAd.destroy();
}
super.onDestroy();
}
服务端回调说明
9.4、服务端回调说明
章鱼广告 SDK 服务器会拿到后台配置的服务器回调链接,并拼接以下参数进行回传:
slotId=%s&appId=%s&transId=%s&userId=%s&extrai=%s&sign=%s&name=%s&count=%s
字段定义 | 字段名称 | 字段类型 | 备注 |
---|---|---|---|
slotId | 签名后的广告位 ID | string | 签名后的广告位 ID,需要可校验 |
appId | APP ID | string | 应用 ID,需要可校验 |
transId | 交易 id | string | 完成观看的唯一交易 ID |
sign | 签名后的 transId | string | 必须验证的签名信息 |
userId | 用户 id | string | 调用 SDK 传入并透传,应用对用户的唯一标识,如无需要则为空 |
extra | 其他信息 | string | 调用 SDK 传入并透传,如无需要则为空 |
name | 奖品名称 | string | 需要就联系运营配置,如无需要则为空 |
count | 奖品数量 | string | 需要就联系运营配置,如无需要则为空 |
具体示例:
http://开发者回调地址/sdk/callback?slotId=%s&appId=%s&transId=%s&userId=%s&extra=%s&sign=%s&name=%s&count=%s
9.5、服务端验证说明
当选择需要服务端验证时,开发者需要按照以上接口进行开发,并向运营提供回调 URL 让运营帮忙配置一下回调 URL。服务端回调是指在用户看完视频达到奖励条件时,章鱼广告 SDK 服务端会向开发者服务端发送一个验证请求,同时客户端会给出 onReward 回调,开发者根据回调进行奖励发放,因为奖励回调和服务端验证请求是同时发送的,开发者后台收到验证请求可能会有延迟或网络原因上的失败,开发者需要平衡用户体验与奖励验证。
补充: 章鱼广告 SDK 后台向上述 URL 发起请求后,您会在服务端收到某个 transId 的请求,如果签名验证正确,那么此 transId 对应的曝光为有效曝光
签名生成方式:
sign = sha256(transid:secret)
其中 transId 为交易 id,secret 运营配置服务端 URL 时获取到的密钥,配置好后跟运营要。
9.6、约定返回参数
字段名称 | 字段定义 | 字段类型 | 备注 |
---|---|---|---|
isValid | 校验结果 | bool | 判定结果,是否发放奖励 |
注意:按照 SDK 要求需要服务器判断的回调 url 是一个 get 请求默认返回的是一个 json 字符串{"isValid": true}
示例:
{
"isValid": true
}
- PS:完整流程请参考 Demo 中的 com.octopus.sdk.demo.RewardVideoActivity 的示例代码。
十、横幅广告
10.1、Banner 广告接口说明
-
/**
* Banner广告构造函数
* @param context 上下文
* @param adSlotId 广告位id,由运营人员提供
* @param adListener Banner广告监听
*/
public BannerAd(Context context, String adSlotId, BannerAdListener adListener)
/**
* 是否使用SDK内部浏览器打开落地页
* @param isOpenInNativeBrowser 默认false, true使用SDK内部浏览器打开, false使用本地浏览器打开
*/
public void openAdInNativeBrowser(boolean isOpenInNativeBrowser)
/**
* 广告是否加载成功
* @return true表示加载成功
*/
public boolean isLoaded()
/**
* 广告是否加载成功,并且在有效时间内(有做广告预缓存的用这个)
* @return true表示加载成功并且有效
*/
public boolean isValid()
/**
* 广告加载
*/
public void loadAd()
/**
* 广告加载成功后可以获取广告返回价格,单位分
*/
public int getPrice()
/**
* 广告展示
*/
public void show()
/**
* 资源释放
*/
public void destroy()
10.2、Banner 广告回调说明
-
/**
* Banner广告监听器
*/
BannerAdListener {
/**
* 广告加载失败
* @param errorCode 错误码
*/
void onAdFailed(int errorCode);
/**
* 广告加载成功
* @param response 原生广告响应数据
*/
void onAdLoaded(NativeAdResponse response);
}
/**
* Draw广告事件监听器
*/
NativeAdEventListener {
/**
* 广告点击
*/
void onAdClick();
/**
* 广告曝光
*/
void onADExposed();
/**
* 广告渲染失败
* @param errorCode 错误码
*/
void onAdRenderFailed(int errorCode);
/**
* 广告关闭
*/
void onAdClose();
}
10.3、Banner 广告示例
-
创建 Banner 广告实例:
mBannerAd = new BannerAd(context, mSlotId, new BannerAdListener() {
@Override
public void onAdFailed(int errorCode) {
Log.i(TAG, "onAdFailed:" + errorCode);
}
@Override
public void onAdLoaded(NativeAdResponse response) {
Log.i(TAG, "onAdLoaded");
// 广告是否加载成功并且在有效时间内
if (mBannerAd != null && mBannerAd.isValid()) {
int adWidth = ViewUtil.getScreenWidth(context);
// 设置广告的宽度单位px(防止SDK获取不到容器的宽度)
response.setAdWidth(adWidth);
showBannerAd(response);
}
// 广告在此竞价 mBannerAd.getPrice(); 单位分
// 注意:竞价结束后记得调用竞胜或竞败接口
// 竟胜时候调用(提高ECPM, 提升填充率)
// mBannerAd.sendWinNotice(第二高价格);
// 竟败时候调用(提高ECPM, 提升填充率)
// mBannerAd.sendLossNotice(最高价, ADBidEvent.PRICE_LOW_FILTER,ADBidEvent.OTHER);
}
});
// 使用SDK内部浏览器打开落地页(默认为false,设为false的情况下会使用系统浏览器打开)
mBannerAd.openAdInNativeBrowser(true);
mBannerAd.loadAd(); -
把 Banner 添加到广告容器中:
public void showBannerAd(NativeAdResponse response) {
if (response == null) return;
response.setNativeAdEventListener(new NativeAdEventListener() {
@Override
public void onAdClick() {
Log.i(TAG, "onAdClick");
}
@Override
public void onADExposed() {
Log.i(TAG, "onADExposed");
}
@Override
public void onAdRenderFailed(int errorCode) {
Log.i(TAG, "onAdRenderFailed");
}
@Override
public void onAdClose() {
Log.i(TAG, "onAdClose");
mAdContainer.removeAllViews();
}
});
// 注册完监听后就可以获取Banner广告View
View nativeView = response.getNativeView();
if (nativeView != null && nativeView.getParent() == null) {
mAdContainer.removeAllViews();
mAdContainer.addView(nativeView);
}
} -
在页面的 onDestroy 方法中请调用:
@Override
protected void onDestroy() {
if (mBannerAd != null){
mBannerAd.destroy();
}
super.onDestroy();
}
- PS: 完整流程请参考 Demo 中的 com.octopus.sdk.demo.BannerActivity 的示例代码。
十一、竞胜竞败回传(媒体 RTB 时调用,提高 ECPM 出价)
-
说明:章鱼广告平台根据媒体传回来的竞胜竞败价格,通过相应算法自动提高出价来获得广告曝光,媒体 RTB 时一定要调用,否则会导致价格出不上去。
-
示例:
splashAd.sendWinNotice(1000); // 价格传竞价第二高价格
splashAd.sendLossNotice(100,ADBidEvent.PRICE_LOW_FILTER,ADBidEvent.CSJ); // 价格传竞价最高的价格
11.1 接口说明**
-
IBidding 接口说明
方法名 含义 sendWinNotice(int secondWinPrice); 竞价成功时上报接口 secondWinPrice 竞价第二名价格,单位是分 (非必填) sendLossNotice(int winPrice, String lossReason, String winBidder); 竞价失败时上报接口 winPrice 胜出者价格 单位分(非必填) lossReason 竞价失败原因(非必填) winBidder 胜出者 (非必填) 枚举值如下 -
ADBidEvent
public class ADBidEvent {
/**
* 竞价失败原因
* 1001 底价过滤
* 1002 bid价格低于最高价
* 1003 素材黑名单过滤
* 1004 竞品过滤
* 1005 超时过滤
* 1006 其它过滤
*/
public static final String BID_PRICE_FILTER = "1001";
public static final String PRICE_LOW_FILTER = "1002";
public static final String ADM_BLACKLIST_FILTER = "1003";
public static final String COMPETE_FILTER = "1004";
public static final String TIMEOUT_FILTER = "1005";
public static final String OTHER_FILTER = "1006";
/**
* 竞价胜出者
* CSJ 穿山甲/头条
* GDT 优量汇/广点通
* KUAISHOU 快手
* BAIDU 百青藤/百度
* SIGMOB sigmob
* OPPO oppo
* VIVO vivo
* HUAWEI 华为
* XIAOMI 小米
* JD 京东
* QM 趣盟
* ONEWAY 万唯
* OTHER 其他家
*/
public static final String CSJ = "CSJ";
public static final String GDT = "GDT";
public static final String KUAISHOU = "KUAISHOU";
public static final String BAIDU = "BAIDU";
public static final String SIGMOB = "SIGMOB";
public static final String OPPO = "OPPO";
public static final String VIVO = "VIVO";
public static final String HUAWEI = "HUAWEI";
public static final String XIAOMI = "XIAOMI";
public static final String OCTOPUS = "OCTOPUS";
public static final String JINGDONG = "JD";
public static final String QUMENG = "QM";
public static final String ONEWAY = "ONEWAY";
public static final String OTHER = "OTHER";
}
十二、Topon(Taku)平台接入广告 SDK 文档
-
Topon(Taku)自定义广告接入地址:https://help.takuad.com/docs/4M5AIa
-
12.1 自定义广告源 adapter 参数
参数填写:
{"app_id":"应用 ID","slot_id":"广告位 ID","is_unified":"是否是自渲染 1:是 0 否"}
广告类型 广告类名称 Topon 配置参数 开屏 com.octopus.ad.topon.OctopusATSplashAdapter {"app_id":"应用 ID","slot_id":"广告位 ID"}
插屏 com.octopus.ad.topon.OctopusATInterstitialAdapter {"app_id":"应用 ID","slot_id":"广告位 ID"}
激励视频 com.octopus.ad.topon.OctopusATRewardVideoAdapter {"app_id":"应用 ID","slot_id":"广告位 ID"}
原生模板 com.octopus.ad.topon.OctopusATNativeAdapter {"app_id":"应用 ID","slot_id":"广告位 ID","is_unified":"0"}
原生自渲染 com.octopus.ad.topon.OctopusATNativeAdapter {"app_id":"应用 ID","slot_id":"广告位 ID","is_unified":"1"}
横幅 com.octopus.ad.topon.OctopusATBannerAdapter {"app_id":"应用 ID","slot_id":"广告位 ID"}
-
12.2 添加广告平台
-
12.3 创建广告源
十三、GroMore(融合)聚合平台自定义广告接入文档
有需要可以找 SDK 开发者索要 aar 文件
添加:octopus_gromore_rh_adapter.aar 文件
自定义广告源 adapter 参数
广告类型 | 广告类名称 |
---|---|
初始化 | com.octopus.ad.gromore.OctopusInit |
开屏 | com.octopus.ad.gromore.OctopusSplashLoader |
插屏 | com.octopus.ad.gromore.OctopusInterstitialLoader |
激励视频 | com.octopus.ad.gromore.OctopusRewardLoader |
原生 | com.octopus.ad.gromore.OctopusNativeLoader |
横幅 | com.octopus.ad.gromore.OctopusBannerLoader |
13.1 添加广告平台
十四、Tobid 聚合平台自定义广告接入文档
有需要可以找 SDK 开发者索要 aar 文件
添加:windmill-octopus-adapter.aar 文件
自定义广告源 adapter 参数
广告类型 | 广告类名称 |
---|---|
初始化 | com.windmill.octopus.OctopusAdapterProxy |
开屏 | com.windmill.octopus.OctopusSplashAdapter |
插屏 | com.windmill.octopus.OctopusInterstitialAdapter |
激励视频 | com.windmill.octopus.OctopusRewardAdapter |
原生 | com.windmill.octopus.OctopusNativeAdapter |
横幅 | com.windmill.octopus.OctopusBannerAdapter |
应用维度参数的 key 填 appId,注意大小写。