# octopus-android-sdk
**Repository Path**: zy_octopus/octopus-android-sdk
## Basic Information
- **Project Name**: octopus-android-sdk
- **Description**: 广告Android SDK
- **Primary Language**: Java
- **License**: Not specified
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 0
- **Created**: 2024-03-12
- **Last Updated**: 2025-10-27
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# Octopus SDK-Android接入文档
**注意:**
- 本 SDK 最低兼容 `Android API 16(Android 4.1 ICS)`
- 确保 support v4、v7包版本不小于 `24.0.0
- 竞胜竞败回传:Octopus平台根据媒体传回来的竞胜竞败价格,通过相应算法自动提高出价来获得广告曝光,媒体RTB时一定要调用,否则会导致价格出不上去。
- 媒体接入信通院 `oaid-sdk`,在初始化的时候可以通过OctopusAdSdkController里面的getOaid()传入获取到的oaid
## 一、导入SDK依赖
**1.1、压缩包目录结构**
- | 文件目录 | 目录说明 |
| -------------------- | -------------------------------------------- |
| Octopus/libs/***.aar | 项目中依赖的aar文件. |
| OctopusSdkDemo | 示例工程, 用来方便媒体参考接入. |
| demo-release.apk | 示例APP, 用来演示广告提供的多种广告展现形式. |
| README.md | Octopus SDK-Android接入文档. |
**1.2、导入SDK文件**
1.2.1、在 app 目录下新建 libs 文件夹.
1.2.2、将Octopus/libs目录下的文件拷贝到libs文件夹下.
1.2.3、在 app/build.gradle 添加如下代码:
- ```groovy
android {
compileSdkVersion 28
// 设置gradle编译选项,开发者可以根据自己对平台的选择进行合理配置,为了保证兼容性,默认支持以下两种架构
ndk {
abiFilters 'armeabi-v7a','arm64-v8a'
}
}
repositories {
flatDir {
dirs 'libs'
}
}
dependencies {
// 集成Octopus SDK需导入的aar
implementation(name: 'octopus_ad_sdk_2.5.10.24', ext: 'aar')
}
```
**1.3、AndroidManifest配置**
1.3.1、添加访问权限
在AndroidManifest.xml文件中添加,建议在您的隐私协议中向开发者声明Octopus SDK会获取下述权限并应用于广告投放
必需权限:
- ```xml
```
可选权限:
- ```xml
```
注意:Octopus SDK不强制获取可选权限,即使没有获取可选权限SDK也能正常运行
1.3.2、overrideLibrary设置
由于引入的sdk支持的最小版本与app支持的最小版本可能不一致,需要在AndroidManifest文件中添加overrideLibrary配置:
- ```xml
```
注意:请开发者务必按照上面信息进行注册声明,详情见Demo。
1.3.3、配置网络权限
在targetSdkVersion 28及以上的手机上允许HTTP(S)网络请求,在“AndroidManifest.xml”做以下配置。
- ```xml
...
```
1.3.4、开启硬件加速
视频广告的MediaView内部使用了TextureView,需要在开启硬件加速的窗口中才能使用。
所以需要在AndroidManifest.xml 添加如下声明:
- ```xml
方式一:
方式二:
```
**1.4、混淆配置**
为了保证Octopus SDK正常工作, 请务必添加以下ProGuard配置打包.
- ```java
# Octopus混淆
-dontwarn com.octopus.**
-keep class com.octopus.** {*;}
```
---
## 二、SDK初始化
**2.1、初始化SDK**
注意:①、初始化SDK必须在调用广告接口之前。appId由运营人员提供
②、建议在application里面调用;假如App有功能引导,也可点击"立即体验"按钮中调用
③、在主线程中调用sdk的初始化(init)方法
2.1.1、如需不需要自定义隐私开关控制,请调用如下方法
- ```java
Octopus.init(applicationContext, appId);
```
2.1.2、如需自定义隐私开关控制,请调用如下方法
- ```java
Octopus.init(applicationContext, appId , new OctopusAdSdkController());
```
**2.2、隐私信息控制开关**
- ```java
/**
* 创建隐私信息控制 实例,媒体可以自主控制是否提供权限给Octopus 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 {
/**
* 2.5.9.28版本开始
* 是否允许SDK主动使用地理位置信息
*
* @return true可以获取,false禁止获取。默认为true
*/
@Override
public boolean isCanUseLocation() {
return super.isCanUseLocation();
}
/**
* 2.5.9.28版本开始
* 开发者可以传入地理位置,经纬度信息
* longitude 经度
* latitude 纬度
* type 坐标系类型,默认 0:WGS-84(GPS) 1:GCJ-02(高德) 2:BAIDU(百度)
* time 地理位置获取时间戳单位毫秒
*/
@Override
public OctLocation getLocation() {
return super.getLocation();
}
/**
* 是否允许SDK主动使用手机硬件参数,如:imei
*
* @return true可以使用,false禁止使用。默认为true
*/
public boolean isCanUsePhoneState() {
return super.isCanUsePhoneState();
}
/**
* 当isCanUsePhoneState=false时,可传入imei信息,sdk使用您传入的imei信息
* @return imei信息
*/
public String getImei() {
return super.getImei();
}
/**
* 开发者可以传入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 super.getOaid();
}
/**
* 1.6.3.7版本开始
* 是否允许SDK主动获取oaid
* @return 默认true 允许 , false 不允许
*/
@Override
public boolean isCanUseOaid() {
return true;
}
}
```
**2.3、其它特殊设置**
2.3.1、设置下载类广告是否直接下载APP,默认开启下载二次确认弹窗
- ```java
Octopus.setIsDownloadDirect(false); // 是否不弹窗,直接下载。默认为false
```
2.3.2、设置是否限制个性化广告推荐 (请在用户点击关闭个性化广告推荐时才调用此方法,否则影响广告收益)
- ```java
Octopus.setLimitPersonalAds(false); // 不限制个性化广告推荐。默认为false
```
2.3.3、设置广告请求超时时长(单位毫秒)
- ```java
Octopus.setTimeout(1000);
```
## 三、开屏广告
**3.1、添加广告容器**
在需要添加开屏广告的Activity对应的布局文件添加一个ViewGroup来填充广告,例如:
- ```xml
```
**3.2、开屏广告接口说明**
- ```java
/**
* 先传入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、开屏广告回调说明**
- ```java
/**
* 开屏广告监听器
*/
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、开屏广告示例**
- 创建开屏广告实例:
```java
FrameLayout container = this.findViewById(R.id.fl_container);
SplashAdListener listener = new SplashAdListener() {
@Override
public void onAdLoaded() {
Log.i(TAG, "onAdLoaded");
// 新版本支持开启广告预缓存,减少请求响应时间,需要的话联系运营开启。
// 开启预缓存后,展示之前要先判断广告是否过期,避免展示过期广告影响收益。
if (mSplashAd.isValid()) {
mSplashAd.showAd();
} else {
jump();
}
// 广告在此竞价 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可以用来判断是否缓存成功,没缓存成功也可以播放在线视频
}
@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而广告无法正常曝光和计费:
```java
@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方法中请调用:
```java
@Override
protected void onDestroy() {
if (mSplashAd != null) {
mSplashAd.destroy();
}
super.onDestroy();
}
```
* 解决点击广告后页面跳转问题(点击后应该先跳转到广告落地页,从落地页返回再进入应用主页),请参考demo中如下写法
```java
// 如果用户点击广告,需要等待广告页面关闭后再跳转主页面。
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、原生广告接口说明**
- ```java
/**
* 原生广告构造方法
* @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、原生广告回调说明**
- ```java
/**
* 原生广告加载监听器
*/
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、原生广告示例**
- 创建原生广告实例:
```java
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方法中请调用:
```java
@Override
protected void onDestroy() {
if (mNativeAd != null) {
mNativeAd.destroy();
}
super.onDestroy();
}
```
- **PS:完整流程请参考Demo中的com.octopus.sdk.demo.NativeAdActivity的示例代码。**
## 五、原生(信息流)自渲染广告
**5.1、原生自渲染广告接口说明**
- ```java
/**
* 原生广告构造方法
* @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、原生自渲染广告回调说明**
- ```java
/**
* 原生广告加载监听器
*/
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、原生自渲染广告响应说明**
- ```java
/**
* 原生广告响应数据
*/
NativeAdResponse {
/**
* 获取广告标题,短文字
*/
String getTitle();
/**
* 获取广告描述,长文字
*/
String getDescription();
/**
* 获取广告按钮文字
*/
String getButtonText();
/**
* 获取 Icon 图片地址
*/
String getIconUrl();
/**
* 获取广告单图图片地址
*/
String getImageUrl();
/**
* 获取图片的地址
*/
List 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 clickViews, NativeAdEventListener listener);
/**
* 原生自渲染广告调用此方法绑定container和事件监听
*
* @param adContainer 用于展示广告的容器
* @param clickViews 可以点击跳转广告的View
* @param closeViews 可以点击关闭广告的View
* @param listener 曝光点击事件监听
*/
void bindUnifiedView(ViewGroup adContainer, List clickViews, List closeViews, NativeAdEventListener listener);
}
```
**5.4、原生自渲染广告示例**
- 创建原生自渲染广告实例:
```java
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 clickViews = new ArrayList<>();
clickViews.add(adImage);
clickViews.add(adButton);
// 把允许关闭的View添加到集合里面
ArrayList 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
```
* 在页面的onDestroy方法中请调用:
```java
@Override
protected void onDestroy() {
if (mNativeAd != null){
mNativeAd.destroy();
}
super.onDestroy();
}
```
- **PS:完整流程请参考Demo中的com.octopus.sdk.demo.NativeUnifiedActivity的示例代码。**
## 六、Draw(信息流)广告
**6.1、Draw广告接口说明**
- ```java
/**
* 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广告回调说明**
- ```java
/**
* 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广告实例:
```java
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 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方法中请调用:
```java
@Override
protected void onDestroy() {
if (mDrawAd != null) {
mDrawAd.destroy();
}
super.onDestroy();
}
```
- **PS:完整流程请参考Demo中的com.octopus.sdk.demo.DrawActivity的示例代码。**
## 七、插屏广告
**7.1、插屏广告接口说明**
- ```java
/**
* 插屏广告构造函数
* @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、插屏广告回调说明**
- ```java
/**
* 插屏广告监听器
*/
InterstitialAdListener {
/**
* 广告加载失败
* @param errorCode 错误码
*/
void onAdFailedToLoad(int errorCode);
/**
* 广告加载成功
*/
void onAdLoaded();
/**
* 素材缓存完成
* @param isSuccess 是否缓存成功
*/
void onAdCacheLoaded(boolean isSuccess);
/**
* 广告展示
*/
void onAdShown();
/**
* 广告关闭
*/
void onAdClosed();
/**
* 广告点击
*/
void onAdClick();
}
```
**7.3、插屏广告示例**
- 创建插屏广告实例:
```java
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方法中请调用:
```java
@Override
protected void onDestroy() {
if (mInterstitialAd != null){
mInterstitialAd.destroy();
}
super.onDestroy();
}
```
- **PS: 完整流程请参考Demo中的com.octopus.sdk.demo.InterstitialActivity的示例代码。**
## 八、全屏视频广告
**8.1、全屏视频广告接口说明**
- ```java
/**
* 全屏视频广告构造函数
* @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、全屏视频广告回调说明**
- ```java
/**
* 全屏视频广告监听器
*/
FullScreenVideoAdListener {
/**
* 广告加载失败
* @param errorCode 错误码
*/
void onAdFailedToLoad(int errorCode);
/**
* 广告加载成功
*/
void onAdLoaded();
/**
* 素材缓存完成
* @param isSuccess 是否缓存成功
*/
void onAdCacheLoaded(boolean isSuccess);
/**
* 广告展示
*/
void onAdShown();
/**
* 广告关闭
*/
void onAdClosed();
/**
* 广告点击
*/
void onAdClick();
}
```
**8.3、全屏视频广告示例**
- 创建全屏视频广告实例:
```java
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方法中请调用:
```java
@Override
protected void onDestroy() {
if (mFullScreenVideoAd != null) {
mFullScreenVideoAd.destroy();
}
super.onDestroy();
}
```
- **PS: 完整流程请参考Demo中的com.octopus.sdk.demo.FullScreenVideoActivity的示例代码。**
## 九、激励视频
**9.1、激励视频接口说明**
- ```java
/**
* 激励视频广告构造函数
* @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、激励视频回调说明**
- ```java
/**
* 激励视频广告监听器
*/
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、激励视频示例**
* 创建激励视频实例:
```java
// 加载广告 注意:每次加载的时候都要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方法中请调用:
```java
@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、服务端回调说明**
Octopus 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。服务端回调是指在用户看完视频达到奖励条件时,Octopus SDK服务端会向开发者服务端发送一个验证请求,同时客户端会给出 onReward 回调,开发者根据回调进行奖励发放,因为奖励回调和服务端验证请求是同时发送的,开发者后台收到验证请求可能会有延迟或网络原因上的失败,开发者需要平衡用户体验与奖励验证。
补充:
Octopus 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广告接口说明**
- ```java
/**
* 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广告回调说明**
- ```java
/**
* 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广告实例:
```java
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添加到广告容器中:
```java
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方法中请调用:
```java
@Override
protected void onDestroy() {
if (mBannerAd != null){
mBannerAd.destroy();
}
super.onDestroy();
}
```
- **PS: 完整流程请参考Demo中的com.octopus.sdk.demo.BannerActivity的示例代码。**
## 十一、竞胜竞败回传(媒体RTB时调用,提高ECPM出价)
- 说明:Octopus平台根据媒体传回来的竞胜竞败价格,通过相应算法自动提高出价来获得广告曝光,媒体RTB时一定要调用,否则会导致价格出不上去。
- 示例:
```java
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
```java
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)平台接入Octopus 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_adapter.aar文件**
**自定义广告源adapter参数**
| 广告类型 | 广告类名称 |
| -------- | ------------------------------------------------ |
| 初始化 | com.octopus.ad.gromore.OctopusInit |
| 开屏 | com.octopus.ad.gromore.OctopusSplashLoader |
| 插屏 | com.octopus.ad.gromore.OctopusInterstitialLoader |
| 全屏视频 | com.octopus.ad.gromore.OctopusFullVideoLoader |
| 激励视频 | com.octopus.ad.gromore.OctopusRewardLoader |
| 原生 | com.octopus.ad.gromore.OctopusNativeLoader |
| 横幅 | com.octopus.ad.gromore.OctopusBannerLoader |
**13.1 添加广告平台**

## 十四、Tobid聚合平台自定义广告接入文档
[Tobid自定义广告接入文档地址: ]: https://doc.sigmob.com/ToBid使用指南/高级功能说明/自定义广告网络/
**Tobid平台已经官聚章鱼SDK,有需要可以直接用Tobid官网适配器文件**
**也可以用我们的自定义适配器aar文件,添加:octopus_tobid_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,注意大小写。
## 十五、Adscope轻变聚合平台自定义广告接入文档
**Adscope平台已经官聚章鱼SDK,有需要可以直接用Adscope官网适配器文件**
**也可以用我们的自定义适配器aar文件,添加:octopus_adscope_adapter.aar文件**
****
**自定义广告源adapter参数**
| 广告类型 | 广告类名称 |
| -------- | --------------------------------------------------- |
| 初始化 | xyz.adscope.amps.adapter.oct.OCTInitMediation |
| 开屏 | xyz.adscope.amps.adapter.oct.OCTSplashAdapter |
| 插屏 | xyz.adscope.amps.adapter.oct.OCTInterstitialAdapter |
| 激励视频 | xyz.adscope.amps.adapter.oct.OCTRewardVideoAdapter |
| 原生 | xyz.adscope.amps.adapter.oct.OCTNativeAdapter |
| 横幅 | xyz.adscope.amps.adapter.oct.OCTBannerAdapter |