跳到主要内容

章鱼聚合 SDK-Android 接入文档

注意:

  • 本 SDK 最低兼容 Android API 16(Android 4.1 ICS)
  • 确保 support v4、v7 包版本不小于 24.0.0
  • 集成前请和章鱼聚合 SDK 人员确认所有使用的依赖库版本号
  • 媒体接入信通院 oaid_sdk 的时候需要将压缩包内 Octopus\assets\下的 supplierconfig.json 文件复制到项目 app 工程 assets 目录里,路径:工程\app\src\main\assets\

一、导入 SDK 依赖

1.1、压缩包目录结构

  • 文件目录目录说明
    Octopus/assets/supplierconfig.json接入信通院 oaid_sdk 的时候需要用到的 json 文件.
    Octopus/libs/***.aar项目中依赖的 aar 文件.
    OctopusDemo示例工程, 用来方便媒体参考接入.
    app-release.apk示例 APP, 用来演示章鱼聚合广告提供的多种广告展现形式.
    whiteList.txt渠道白名单,媒体如果设置了资源混淆,需要添加这个配置.
    章鱼聚合 SDK-Android 接入文档.html章鱼聚合 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

    // 如果集成京东SDK,则可能会遇到如下报错:
    // Default interface methods are only supported starting with Android N (--min-api 24): void
    // com.jd.ad.sdk.bl.dynamicrender.DynamicRenderView$IDynamicRenderCallback.onAnimationEnd()
    // 添加以下代码可解决
    compileOptions {
    sourceCompatibility JavaVersion.VERSION_1_8
    targetCompatibility JavaVersion.VERSION_1_8
    }

    // 设置gradle编译选项,开发者可以根据自己对平台的选择进行合理配置,为了保证兼容性,默认支持以下五种架构
    ndk {
    abiFilters 'armeabi-v7a','x86','arm64-v8a','x86_64','armeabi'
    }


    repositories {
    flatDir {
    dirs 'libs'
    }
    }

    dependencies {
    // 怎么判断你的项目是support版本还是Androidx版本
    // 如果你的项目添加的是support依赖,则你的项目是support版本,例如:
    implementation "com.android.support:appcompat-v7:28.0.0"
    implementation "com.android.support:support-v4:28.0.0"
    implementation "com.android.support:recyclerview-v7:28.0.0"
    // 如果你的项目添加的是Androidx依赖,则你的项目是androidx版本,例如:
    implementation 'androidx.appcompat:appcompat:1.0.0'
    implementation 'androidx.legacy:legacy-support-v4:1.0.0'
    implementation 'androidx.recyclerview:recyclerview:1.2.1'


    // 集成章鱼聚合SDK需导入的aar(必选)
    implementation(name: 'octopus_group_sdk_3.2.13.6', ext: 'aar')

    // 开发者可根据APP需要导入以下广告aar文件

    // 1、集成章鱼广告需导入的aar
    implementation(name: 'octopus_ad_sdk_1.5.9.11', ext: 'aar')
    // 2、集成京东广告需导入的aar(注意:区分support和androidx)
    //***如果你的项目是support版本,则导入以下aar
    implementation(name: 'jad_yun_sdk_v2.0.2', ext: 'aar')
    //***如果你的项目是androidx版本,则导入以下aar
    implementation(name: 'jad_yun_sdk_v2.1.2', ext: 'aar')
    // 3、集成趣萌广告需导入的aar(注意:区分support和androidx)
    //***如果你的项目是support版本,则导入以下aar
    implementation(name: 'qumeng-3.461.11.427', ext: 'aar')
    //***如果你的项目是androidx版本,则导入以下aar
    implementation(name: 'qumeng-3.461.11.427x', ext: 'aar')
    // 4、集成广点通广告需导入的aar
    implementation(name: 'GDTSDK.unionNormal.4.540.1410', ext: 'aar')
    // 5、集成穿山甲广告需导入的aar
    implementation(name: 'open_ad_sdk_5.7.0.6', ext: 'aar')
    // 6、集成快手广告需导入的aar
    implementation(name: 'kssdk-ad-3.3.51.1-publishRelease-97f3383ba2', ext: 'aar')
    // 7、集成百度广告需导入的aar
    implementation(name: 'Baidu_MobAds_SDK-release_v9.313', ext: 'aar')
    // 8、集成Oneway广告需导入的aar
    implementation(name: 'Oneway-2.5.4-release', ext: 'aar')
    // 9、集成Sigmob广告需导入的aar
    implementation(name: 'wind-common-1.4.9', ext: 'aar')
    implementation(name: 'wind-sdk-4.12.6', ext: 'aar')

    // 集成信通院oaid_sdk需导入的aar
    implementation(name: 'oaid_sdk_1.0.25', 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.REQUEST_INSTALL_PACKAGES" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

    <!--可选权限-->
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />

    <!-- 如果有视频相关的广告且使用textureView播放,请务必添加,否则黑屏 -->
    <uses-permission android:name="android.permission.WAKE_LOCK" />

    <!--获取应用安装列表的权限属于个人信息,由渠道引入,媒体可以通过以下配置,主动移除这个权限-->
    <uses-permission
    android:name="android.permission.QUERY_ALL_PACKAGES"
    tools:node="remove" />

    <!--获取手机状态的权限可能涉及到获取个人信息,由渠道引入,媒体可以通过以下配置,主动移除这个权限-->
    <uses-permission
    android:name="android.permission.READ_PHONE_STATE"
    tools:node="remove" />

    <!--必要权限,解决安全风险漏洞,发送和注册广播事件需要调用带有传递权限的接口-->
    <permission
    android:name="${applicationId}.openadsdk.permission.TT_PANGOLIN"
    android:protectionLevel="signature" />
    <uses-permission android:name="${applicationId}.openadsdk.permission.TT_PANGOLIN" />

​ 注意:章鱼聚合 SDK 不强制获取可选权限,即使没有获取可选权限 SDK 也能正常运行;获取可选权限将帮助 Octopus 优化投放广告精准 度和用户的交互体验,提高 eCPM。

​ 1.3.2、overrideLibrary 设置

​ 由于引入的 sdk 支持的最小版本与 app 支持的最小版本可能不一致,需要在 AndroidManifest 文件中添加 overrideLibrary 配置:

  • <uses-sdk tools:overrideLibrary="com.octopus.ad,com.octopus.group,com.bun.miitmdid,
    com.kwad.sdk,com.bytedance.sdk.openadsdk,com.jd.ad.sdk" />

​ 注意:请开发者务必按照上面信息进行注册声明,详情见 Demo。

​ 1.3.3、provider 配置

  • <!--targetSDKVersion >= 24时才需要添加这些个provider。请开发者根据自己的包名来替换${applicationId}这个值-->
    <!--GDT Sdk安装广告下载的APP需要用到这个-->
    <provider
    android:name="com.qq.e.comm.GDTFileProvider"
    android:authorities="${applicationId}.gdt.fileprovider"
    android:exported="false"
    android:grantUriPermissions="true">
    <meta-data
    android:name="android.support.FILE_PROVIDER_PATHS"
    android:resource="@xml/gdt_file_path" />
    </provider>

    <!--CSJ Sdk安装广告下载的APP需要用到这个-->
    <provider
    android:name="com.bytedance.sdk.openadsdk.TTFileProvider"
    android:authorities="${applicationId}.TTFileProvider"
    android:exported="false"
    android:grantUriPermissions="true">
    <meta-data
    android:name="android.support.FILE_PROVIDER_PATHS"
    android:resource="@xml/file_paths" />
    </provider>

​ 1.3.4、配置网络权限

​ 在 targetSdkVersion 28 及以上的手机上允许 HTTP(S)网络请求,在“AndroidManifest.xml”做以下配置。

  • <application
    ...
    android:usesCleartextTraffic="true"
    >
    ...
    </application>

​ 1.3.5、开启硬件加速

​ 视频广告的 MediaView 内部使用了 TextureView,需要在开启硬件加速的窗口中才能使用。 ​ 所以需要在 AndroidManifest.xml 添加如下声明:

  • 方式一:
    <application

    android:hardwareAccelerated="true"
    ... ...

    </application>

    方式二:
    <activity

    android:hardwareAccelerated="true"
    ... ...

    </activity>

1.4、混淆配置

​ 为了保证 Octopus SDK 正常工作, 请务必按照以下 ProGuard 配置打包.

  • -ignorewarnings

    -dontoptimize
    -dontpreverify

    -keepattributes Signature
    -keepattributes *Annotation*

    -dontwarn android.app.**
    -dontwarn android.support.**
    -dontwarn sun.misc.**
    -dontwarn org.apache.**

    -keep class **.R$* {*;}
    -keep class sun.misc.**{*;}
    -keep class android.support.** { *; }
    -keep class android.app.**{*;}

    -keepclassmembers class * extends android.app.Activity {
    public void *(android.view.View);
    }

    -keepclassmembers enum * {
    public static **[] values();
    public static ** valueOf(java.lang.String);
    }

    # androidx 混淆
    -keep class com.google.android.material.** {*;}
    -keep class androidx.** {*;}
    -keep public class * extends androidx.**
    -keep interface androidx.** {*;}
    -dontwarn com.google.android.material.**
    -dontnote com.google.android.material.**
    -dontwarn androidx.**

    # 移动安全联盟oaid混淆
    -keep class XI.CA.XI.**{*;}
    -keep class XI.K0.XI.**{*;}
    -keep class XI.XI.K0.**{*;}
    -keep class XI.xo.XI.XI.**{*;}
    -keep class com.asus.msa.SupplementaryDID.**{*;}
    -keep class com.asus.msa.sdid.**{*;}
    -keep class com.bun.lib.**{*;}
    -keep class com.bun.miitmdid.**{*;}
    -keep class com.huawei.hms.ads.identifier.**{*;}
    -keep class com.samsung.android.deviceidservice.**{*;}
    -keep class com.zui.opendeviceidlibrary.**{*;}
    -keep class org.json.**{*;}
    -keep public class com.netease.nis.sdkwrapper.Utils {public <methods>;}

    # Octopus混淆
    -dontwarn com.octopus.group.**
    -dontwarn com.octopus.ad.**
    -keep class com.octopus.group.** {*; }
    -keep class com.octopus.ad.** {*; }

    # 聚合混淆

    # 如果接入了京东广告,需要添加如下配置
    -keep class com.jd.ad.sdk.** { *; }

    # 如果接入了广点通广告,需要添加如下配置
    -keep class com.qq.e.** {
    public protected *;
    }

    # 如果接入了穿山甲广告,需要添加如下配置
    -keep class com.bytedance.sdk.openadsdk.** {*;}
    -keep public interface com.bytedance.sdk.openadsdk.downloadnew.** {*;}
    -keep class com.pgl.sys.ces.* {*;}

    # 如果接入了快手联盟,需要添加如下配置
    -keep class com.kwad.sdk.** { *;}
    -keep class com.ksad.download.** { *;}
    -keep class com.kwai.filedownloader.** { *;}

    # 如果接入了百度广告,需要添加如下配置
    -keep class com.baidu.mobads.** { *; }
    -keep class com.style.widget.** {*;}
    -keep class com.component.** {*;}
    -keep class com.baidu.ad.magic.flute.** {*;}
    -keep class com.baidu.mobstat.forbes.** {*;}

    # 如果接入了Sigmob广告,需要添加如下配置
    -keep class sun.misc.Unsafe.**{ *; }
    -keep class com.sigmob.**{*;}
    -keep interface com.sigmob.**{*;}
    -keep class com.czhj.**{*;}
    -keep interface com.czhj.**{*;}

    # 优化
    -optimizations !code/simplification/arithmetic,!field/*,!class/merging/*

    # 保护内部类
    -keepattributes Exceptions,InnerClasses,Signature,Deprecated,SourceFile,LineNumberTable,*Annotation*,EnclosingMethod

二、SDK 初始化

2.1、初始化 SDK

​ 注意:①、初始化 SDK 必须在调用广告接口之前。appId 由运营人员提供

​ ②、建议在 application 里面调用;假如 App 有功能引导,也可点击"立即体验"按钮中调用

​ ③、在主线程中调用 sdk 的初始化(init)方法

​ 2.1.1、如需不需要自定义隐私开关控制,请调用如下方法

  • OctopusGroup.init(applicationContext, appId);

​ 2.1.2、如需自定义隐私开关控制,请调用如下方法

  • OctopusGroup.init(applicationContext, appId, new OctopusCustomController());

​ 2.1.3、如需传入自己获取的 oaid,请调用如下初始化方法

  • OctopusGroup.init(applicationContext, appId, new OctopusCustomController(), "DEVICE_OAID");

2.2、隐私信息控制开关

  • public abstract class OctopusCustomController {
    /**
    * 是否允许SDK主动使用地理位置信息
    *
    * @return true可以获取,false禁止获取。默认为true
    */
    public boolean isCanUseLocation() {
    return true;
    }

    /**
    * 是否允许SDK主动使用ACCESS_WIFI_STATE权限
    *
    * @return true可以使用,false禁止使用。默认为true
    */
    public boolean isCanUseWifiState() {
    return true;
    }
    /**
    * 是否允许SDK主动使用手机硬件参数,如:imei,imsi
    *
    * @return true可以使用,false禁止使用。默认为true
    */
    public boolean isCanUsePhoneState() {
    return true;
    }

    /**
    * 是否能使用Oaid
    * @return true可以使用,false禁止使用。默认为true
    */
    public boolean isCanUseOaid() {
    return true;
    }

    /**
    * 是否能使用Gaid
    *
    * @return true可以使用,false禁止使用。默认为true
    */
    public boolean isCanUseGaid() {
    return true;
    }
    }

2.3、其它特殊设置

​ 2.3.1、如果正在使用的 oaid_sdk 版本不是 1.0.25,需要传入正在使用的 oaid_sdk 版本号

  • OctopusGroup.setOaidVersion("x.x.x"); // 传入自己的oaid_sdk版本号

​ 2.3.2、如果需要点击广告后不直接下载,而是弹出二次确认弹框

  • // 设置是否直接下载: true:直接下载,false:二次弹窗确认,默认为true
    OctopusGroup.setDownloadDirect(false);

​ 2.3.3、如果需要关闭个性化广告推荐 (请在用户点击关闭个性化广告推荐时才调用此方法,否则影响广告收益):

  • // 设置是否允许个性化广告推荐,不允许后将获取不到广告: true:允许,false:不允许,默认为true
    OctopusGroup.setSupportPersonalized(false);

三、开屏广告

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、开屏广告接口说明

  • /**
    * 开屏广告构造函数
    * @param context 必须传入Activity的上下文
    * @param adTypeId 聚合SDK的广告位id,由运营人员提供
    * @param adListener 开屏广告监听器
    * @param usableTime 超时时间
    */
    public SplashAd(Context context, String adTypeId, AdListener adListener, long usableTime)

    /**
    * @param widthDp 广告宽度dp值
    * @param heightDp 广告高度dp值
    * /
    public void loadAd(int widthDp,int heightDp)

    /**
    * 当媒体选择不展示此次广告时,请调用此方法,方便后续数据分析
    */
    public void reportNotShow()

    /**
    * 展示广告
    * @param parent 广告容器
    */
    public void show(ViewGroup parent){}

3.3、开屏广告回调说明

  • /**
    * 开屏广告监听器
    */
    AdListener {
    /**
    * 广告加载成功
    */
    @Override
    public void onAdLoaded()

    /**
    * 广告展示
    */
    @Override
    public void onAdShown()

    /**
    * 加载失败
    * @param errorCode 错误码
    */
    @Override
    public void onAdFailedToLoad(int errorCode)

    /**
    * 广告关闭
    */
    @Override
    public void onAdClosed()

    /**
    * 倒计时回调,返回广告还将被展示的剩余时间。
    * 通过这个接口,开发者可以自行决定是否显示倒计时提示,或者还剩几秒的时候显示倒计时
    */
    @Override
    public void onAdTick(long millisUnitFinished)

    /**
    * 广告点击
    */
    @Override
    public void onAdClicked()
    }

3.4、开屏广告示例

  • 注意: 在主线程中调用广告对象的创建(new Ad())和加载(load)方法

  • 创建开屏广告实例:

    // 广告容器
    mAdContainer = this.findViewById(R.id.fl_container);
    // 开屏广告请求超时时长
    int totalTime = 5000;
    mSplashAd = new SplashAd(this, "7046", new AdListener() {
    @Override
    public void onAdLoaded() {
    Log.i("OctopusGroupDemo", "onAdLoaded");
    if (mSplashAd != null) {
    Log.i("OctopusGroupDemo", "ad ecpm = " + mSplashAd.getECPM());
    mSplashAd.show(mAdContainer);
    }
    }

    @Override
    public void onAdShown() {
    Log.i("OctopusGroupDemo", "onAdShown");
    }

    @Override
    public void onAdFailedToLoad(int errorCode) {
    Log.i("OctopusGroupDemo", "onAdFailedToLoad:" + errorCode);
    jump();
    }

    @Override
    public void onAdClosed() {
    Log.i("OctopusGroupDemo", "onAdClosed");
    jumpWhenAdPageFinish();
    }

    @Override
    public void onAdTick(long millisUnitFinished) {
    Log.i("OctopusGroupDemo", "onAdTick millisUnitFinished == " + millisUnitFinished);
    }

    @Override
    public void onAdClicked() {
    Log.i("OctopusGroupDemo", "onAdClicked");
    }
    }, totalTime); // 广告请求超时时长,建议5秒以上,该参数单位为ms
    mSplashAd.loadAd(360,640); // 第一个参数是宽度,第二个参数是高度 单位是dp
  • 开屏页一定要禁止用户对返回按钮的控制,否则将可能导致用户手动退出了 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.demo.SplashActivity 的示例代码。

四、原生(信息流)广告

4.1、原生广告接口说明

  • /**
    * 原生广告构造方法
    * @param context 必须传入Activity的上下文
    * @param adTypeId 聚合SDK的广告位id,由运营人员提供
    * @param adListener 原生广告监听
    * @param usableTime 广告请求超时时长,单位毫秒,建议5秒(5000)以上
    */
    public NativeAd(Context context, String adTypeId, NativeAdListener adListener, long asableTime)

    /**
    * 广告加载,只加载一条广告
    * @param adWidthDp 广告view的宽度,单位为dp, 特别说明:假如广告有左右间距,故广告view的宽度 = 屏幕宽度 - 左右间距总和
    * @param adHeightDp 广告view的高度,单位为dp,特别说明:0表示高度自适应
    */
    public void loadAd(float adWidthDp, float adHeightDp)

    /**
    * 恢复广告状态
    */
    public void resume()

    /**
    * 资源释放
    */
    public void destroy()

4.2、原生广告回调说明

  • /**
    * 原生广告监听器
    */
    NativeAdListener {
    /**
    * 广告加载失败
    * @param code
    */
    void onAdFailed(int code);

    /**
    * 广告加载成功
    * @param view 广告view
    */
    void onAdLoaded(View view);

    /**
    * 广告展示
    */
    void onAdShown();

    /**
    * 广告关闭
    */
    void onAdClosed();

    /**
    * 广告点击
    */
    void onAdClick();
    }

4.3、原生广告示例

  • 注意: 在主线程中调用广告对象的创建(new Ad())和加载(load)方法

  • 创建原生广告实例:

    private NativeAd mNativeAd;
    //广告容器
    private FrameLayout mAdContainer;
    //特别说明:context 必须传入 Activity
    mNativeAd = new NativeAd(NativeAdActivity.this, "7045", new NativeAdListener() {
    @Override
    public void onAdFailed(int code) {
    Log.i("OctopusGroupDemo",TAG + " Native ad onAdFailed " + code);
    }

    @Override
    public void onAdLoaded(View view) {
    Log.i("OctopusGroupDemo",TAG + " Native ad onAdLoaded");
    Log.i("OctopusGroupDemo", "ad ecpm = " + mNativeAd.getECPM());
    if (mAdContainer.getChildCount() > 0) {
    mAdContainer.removeAllViews();
    }
    // 广告可见才会产生曝光,否则将无法产生收益。
    mAdContainer.addView(view);
    }

    @Override
    public void onAdShown() {
    Log.i("OctopusGroupDemo",TAG + " Native ad onAdShown");
    }

    @Override
    public void onAdClosed() {
    Log.i("OctopusGroupDemo",TAG + " Native ad onAdClosed");
    //移除广告
    if (mAdContainer != null && mAdContainer.getChildCount() > 0) {
    mAdContainer.removeAllViews();
    }
    }

    @Override
    public void onAdClick() {
    Log.i("OctopusGroupDemo",TAG + " Native ad onAdClick");
    }
    }, 5000);//第四个参数是:广告请求超时时长,建议设置为5000毫秒;

    /*
    * 加载广告
    * 广告view的宽度,单位为dp, 特别说明:假如广告有左右间距,故广告view的宽度 = 屏幕宽度 - 左右间距总和
    * 广告view的高度,单位为dp,特别说明:0表示高度自适应
    */
    mNativeAd.loadAd(UiUtil.getScreenWidthDp(this), 0);
  • 在页面的 onResume 和 onDestroy 方法中请调用:

    @Override
    protected void onResume() {
    super.onResume();
    // 必须要在Activity.onResume()时通知到广告数据,以便重置广告恢复状态
    if (mNativeAd != null) {
    mNativeAd.resume();
    }
    }

    @Override
    protected void onDestroy() {
    if (mNativeAd != null){
    mNativeAd.destroy();
    }
    super.onDestroy();
    }

  • PS:完整流程请参考 Demo 中的 com.octopus.demo.NativeAdActivity 的示例代码。

五、插屏广告

5.1、插屏广告接口说明

  • /**
    * 插屏广告构造函数
    * @param context Activity的上下文
    * @param adTypeId 聚合SDK的广告位id,由运营人员提供
    * @param adListener 插屏广告监听
    * @param usableTime 广告超时时长,单位毫秒,建议5秒(5000)以上
    */
    public InterstitialAd(Context context, String adTypeId, InterstitialAdListener adListener, long usableTime)

    /**
    * 广告加载
    */
    public void loadAd()

    /**
    * 广告是否加载成功
    * @return true表示加载成功;false则失败
    */
    public boolean isLoaded()

    /**
    * 广告展示
    * @param activity
    */
    public void showAd(@NonNull Activity activity)

    /**
    * 资源释放
    */
    public void destroy()

5.2、插屏广告回调说明

  • /**
    * 插屏广告监听器
    */
    InterstitialAdListener {
    /**
    * 广告加载失败
    * @param code
    */
    void onAdFailed(int code);

    /**
    * 广告加载成功
    */
    void onAdLoaded();

    /**
    * 广告展示
    */
    void onAdShown();

    /**
    * 广告关闭
    */
    void onAdClosed();

    /**
    * 广告点击
    */
    void onAdClick();
    }

5.3、插屏广告示例

  • 注意: 在主线程中调用广告对象的创建(new Ad())和加载(load)方法

  • 创建插屏广告实例:

    /**
    * context 必须传入 Activity类型
    */
    mInterstitialAd = new InterstitialAd(this, "7047", new InterstitialAdListener() {
    @Override
    public void onAdFailed(int code) {
    Log.i("OctopusGroupDemo",TAG + " onAdFailed ");
    Toast.makeText(InterstitialActivity.this, R.string.load_ad_fail, Toast.LENGTH_LONG).show();
    }

    @Override
    public void onAdLoaded() {
    Log.i("OctopusGroupDemo",TAG + " onAdLoaded");
    Toast.makeText(InterstitialActivity.this, R.string.load_ad_success, Toast.LENGTH_LONG).show();
    //插屏广告加载成功直接显示插屏
    if (mInterstitialAd != null && mInterstitialAd.isLoaded()) {
    Log.i("OctopusGroupDemo", "ad ecpm = " + mInterstitialAd.getECPM());
    // 广告展示需要传入Activity
    mInterstitialAd.showAd(InterstitialActivity.this);
    }
    }

    @Override
    public void onAdShown() {
    Log.i("OctopusGroupDemo",TAG + " onAdShown");
    }

    @Override
    public void onAdClosed() {
    Log.i("OctopusGroupDemo",TAG + " onAdClosed");
    }

    @Override
    public void onAdClick() {
    Log.i("OctopusGroupDemo",TAG + " onAdClick");
    }
    }, 5000);//超时时间,单位为毫秒,建议5000以上

    //插屏广告加载
    mInterstitialAd.loadAd();
  • 在页面的 onDestroy 方法中请调用:

    @Override
    protected void onDestroy() {
    if (mInterstitialAd != null){
    mInterstitialAd.destroy();
    }
    super.onDestroy();
    }

  • PS: 完整流程请参考 Demo 中的 com.octopus.demo.InterstitialActivity 的示例代码。

六、激励视频

6.1、激励视频接口说明

  • /**
    * 激励视频广告构造函数
    * @param context 上下文
    * @param adTypeId 聚合SDK的广告位id,由运营人员提供
    * @param adListener 激励视频广告监听
    * @param usableTime 广告超时时长,单位毫秒,建议10秒(10000)以上
    */
    public RewardedVideoAd(Context context, String adTypeId, RewardedVideoAdListener adListener,long usableTime)

    /**
    * 广告加载
    */
    public void loadAd()

    /**
    * 广告是否加载成功
    * @return true表示加载成功;false则失败
    */
    public boolean isLoaded()

    /**
    * 广告展示
    * @param activity
    */
    public void showAd(@NonNull Activity activity)

    /**
    * 资源释放
    */
    public void destroy()

6.2、激励视频回调说明

  • /**
    * 激励视频广告监听器
    */
    RewardedVideoAdListener {

    /**
    * 获得奖励,在该回调中做奖励操作
    */
    void onRewarded();

    /**
    * 广告加载失败
    */
    void onRewardedVideoAdFailedToLoad(int i);

    /**
    * 广告加载成功
    */
    void onRewardedVideoAdLoaded();

    /**
    * 广告展示
    */
    void onRewardedVideoAdShown();

    /**
    * 广告关闭
    */
    void onRewardedVideoAdClosed();

    /**
    * 广告点击
    */
    void onRewardedVideoClick();
    }

6.3、激励视频示例

  • 注意: 在主线程中调用广告对象的创建(new Ad())和加载(load)方法

  • 创建激励视频实例:

    RewardedVideoAd mRewardedVideoAd = new RewardedVideoAd(this, "7048", new RewardedVideoAdListener() {

    /**
    * 获得奖励,在该回调中做奖励操作
    */
    @Override
    public void onRewarded() {
    Log.i("OctopusGroupDemo","enter onRewarded");
    }

    /**
    * 加载失败
    * @param i 错误码
    */
    @Override
    public void onRewardedVideoAdFailedToLoad(int i) {
    Log.i("OctopusGroupDemo","enter onRewardedVideoAdFailedToLoad errorCode = "+i);
    }

    /**
    * 广告加载成功
    */
    @Override
    public void onRewardedVideoAdLoaded() {
    Log.i("OctopusGroupDemo","enter onRewardedVideoAdLoaded");
    if (mRewardedVideoAd != null && mRewardedVideoAd.isLoaded()) {
    Log.i("OctopusGroupDemo", "ad ecpm = " + mRewardedVideoAd.getECPM());
    mRewardedVideoAd.showAd(RewardedVideoActivity.this);
    }
    }

    /**
    * 广告展示
    */
    @Override
    public void onRewardedVideoAdShown() {
    Log.i("OctopusGroupDemo","enter onRewardedVideoAdShown");
    }

    /**
    * 广告关闭
    */
    @Override
    public void onRewardedVideoAdClosed() {
    Log.i("OctopusGroupDemo","enter onRewardedVideoAdClosed");
    }

    /**
    * 广告点击
    */
    @Override
    public void onRewardedVideoClick() {
    Log.i("OctopusGroupDemo","enter onRewardedVideoClick");
    }
    },10000);//加载激励视频的超时时长,建议10秒以上,该参数单位为ms;

    mRewardedVideoAd.loadAd();
  • 在页面的 onDestroy 方法中请调用:

    @Override
    protected void onDestroy() {
    if (mRewardedVideoAd != null){
    mRewardedVideoAd.destroy();
    }
    super.onDestroy();
    }
  • PS:完整流程请参考 Demo 中的 com.octopus.demo.RewardedVideoActivity 的示例代码。

七、原生(信息流)自渲染广告

7.1、原生自渲染广告接口说明

  • /**
    * 自定义广告构造方法
    * @param context 必须传入Activity的上下文
    * @param adTypeId 聚合SDK的广告位id,由运营人员提供
    * @param adListener 原生广告监听
    * @param usableTime 广告请求超时时长,单位毫秒,建议5秒(5000)以上
    */
    public NativeUnifiedAd(Context context, String adTypeId, NativeUnifiedAdListener adListener, long usableTime)

    /**
    * 广告是否加载成功
    * @return true表示加载成功;false则失败
    */
    public boolean isLoaded()

    /**
    * 广告加载,只加载一条广告
    */
    public void loadAd()

    /**
    * 恢复广告状态
    */
    public void resume()

    /**
    * 资源释放
    */
    public void destroy()

7.2、原生自渲染广告回调说明

  • /**
    * 原生自渲染广告监听器
    */
    NativeUnifiedAdListener {
    /**
    * 广告加载失败
    * @param code
    */
    void onAdFailed(int code);

    /**
    * 广告加载成功
    * @param response 广告响应结果
    */
    void onAdLoaded(NativeUnifiedAdResponse response);

    /**
    * 广告展示
    */
    void onAdShown();

    /**
    * 广告点击
    */
    void onAdClick();
    }

7.3、原生自渲染广告响应说明

  • /**
    * 原生自渲染广告响应数据
    */
    public interface NativeUnifiedAdResponse {
    /**
    * 获取广告标题,短文字
    */
    String getTitle();

    /**
    * 获取广告描述,长文字
    */
    String getDescription();

    /**
    * 获取 Icon 图片地址
    */
    String getIconUrl();

    /**
    * 获取广告单图图片地址
    */
    String getImageUrl();

    /**
    * 获取图片的地址列表(多图广告)
    */
    List<String> getImgList();

    /**
    * 获取广告Logo链接
    */
    String getLogoUrl();

    /**
    * 获取广告文字Logo链接
    */
    String getTextLogoUrl();

    /**
    * 获取广告LogoBitmap
    */
    Bitmap getLogo(Context context);

    /**
    * 获取广告文字LogoBitmap
    */
    Bitmap getTextLogo(Context context);

    /**
    * 获取广告素材类型
    */
    int getMaterialType();

    /**
    * 获取按钮文案
    */
    String getButtonText();

    /**
    * 是否视屏类广告
    */
    boolean isVideo();

    /**
    * 获取放置广告内容的容器
    */
    ViewGroup getViewContainer();

    /**
    * 获取广告视频view
    */
    View getVideoView();

    /**
    * 注册view为可点击控件
    */
    void registerViewForInteraction(List<View> views);
    }

7.4、原生自渲染广告示例

  • 注意: 在主线程中调用广告对象的创建(new Ad())和加载(load)方法

  • 创建原生自渲染广告实例:

    private NativeUnifiedAd mNativeAd;

    private void loadAd() {
    //context 必须传入 Activity类型
    mNativeAd = new NativeUnifiedAd(NativeUnifiedAdActivity.this, "7166", new NativeUnifiedAdListener() {
    @Override
    public void onAdFailed(int code) {
    Log.i("OctopusGroupDemo", TAG + " Native ad onAdFailed " + code);
    Toast.makeText(getApplicationContext(), getResources().getString(R.string.load_ad_fail) + ",错误码 = " + code, Toast.LENGTH_LONG).show();
    }

    @Override
    public void onAdLoaded(NativeUnifiedAdResponse response) {
    Log.i("OctopusGroupDemo", TAG + " Native ad onAdLoaded");
    Log.i("OctopusGroupDemo", "ad ecpm = " + mNativeAd.getECPM());
    handleUnifiedView(response);
    Toast.makeText(getApplicationContext(), getResources().getString(R.string.load_ad_success), Toast.LENGTH_LONG).show();
    }

    @Override
    public void onAdShown() {
    Log.i("OctopusGroupDemo", TAG + " Native ad onAdShown");
    }

    @Override
    public void onAdClick() {
    Log.i("OctopusGroupDemo", TAG + " Native ad onAdClick");

    }
    }, 5000);//第四个参数是:广告请求超时时长,建议设置为5000毫秒;
    // 是否自动添加广告Logo,默认true
    mNativeAd.setIsAddLogo(true);
    // 广告加载
    mNativeAd.loadAd();
    }

    @SuppressLint("InflateParams")
    private void handleUnifiedView(NativeUnifiedAdResponse response) {
    if (response == null) return;
    View mUnifiedView = LayoutInflater.from(this).inflate(R.layout.item_native_unified_ad_view, null);
    ImageView imageIv = mUnifiedView.findViewById(R.id.ad_image);
    FrameLayout videoFl = mUnifiedView.findViewById(R.id.ad_video);
    ImageView iconIv = mUnifiedView.findViewById(R.id.ad_icon);
    TextView titleTv = mUnifiedView.findViewById(R.id.ad_title);
    TextView desTv = mUnifiedView.findViewById(R.id.ad_desc);
    Button actionBt = mUnifiedView.findViewById(R.id.ad_button);
    Log.e("OctopusGroupDemo", TAG + "response imageUrl:" + response.getImageUrl()
    + "\n;IconUrl:" + response.getIconUrl()
    + "\n;getTitle:" + response.getTitle()
    + "\n;getDescription:" + response.getDescription()
    + "\n;getButtonText:" + response.getButtonText()
    + "\n;getMaterialType:" + response.getMaterialType()
    + "\n;isVideo:" + response.isVideo()
    );
    if (!TextUtils.isEmpty(response.getImageUrl())) {
    OctopusImageUtils.with(this).load(response.getImageUrl()).into(imageIv);
    }
    if (!TextUtils.isEmpty(response.getIconUrl())) {
    iconIv.setVisibility(View.VISIBLE);
    OctopusImageUtils.with(this).load(response.getIconUrl()).into(iconIv);
    }
    if (!TextUtils.isEmpty(response.getTitle())) {
    titleTv.setText(response.getTitle());
    }
    if (!TextUtils.isEmpty(response.getDescription())) {
    desTv.setText(response.getDescription());
    }
    if (!TextUtils.isEmpty(response.getButtonText())) {
    actionBt.setText(response.getButtonText());
    }
    if (response.isVideo()) {
    imageIv.setVisibility(View.GONE);
    videoFl.setVisibility(View.VISIBLE);
    videoFl.addView(response.getVideoView(), new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 600, Gravity.CENTER));
    }
    View adContainer = response.getViewContainer();
    if (adContainer instanceof FrameLayout) {
    FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
    adContainer.setLayoutParams(params);
    ((FrameLayout) adContainer).removeAllViews();
    ((FrameLayout) adContainer).addView(mUnifiedView);
    }
    mAdContainer.removeAllViews();
    mAdContainer.addView(adContainer);
    List<View> views = new ArrayList<>();
    views.add(imageIv);
    views.add(actionBt);
    views.add(titleTv);
    views.add(iconIv);
    response.registerViewForInteraction(views);
    }
  • 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">

    <ImageView
    android:id="@+id/ad_image"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:adjustViewBounds="true"
    android:contentDescription="@null"
    android:scaleType="fitCenter" />

    <FrameLayout
    android:id="@+id/ad_video"
    android:layout_width="match_parent"
    android:layout_height="wrap_content" />

    <RelativeLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_marginTop="10dp"
    android:layout_marginBottom="20dp">

    <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>
    </LinearLayout>

  • 在页面的 onResume 和 onDestroy 方法中请调用:

    @Override
    protected void onResume() {
    super.onResume();
    // 必须要在Activity.onResume()时通知到广告数据,以便重置广告恢复状态
    if (mNativeUnifiedAd != null) {
    mNativeUnifiedAd.resume();
    }
    }

    @Override
    protected void onDestroy() {
    if (mNativeUnifiedAd != null){
    mNativeUnifiedAd.destroy();
    }
    super.onDestroy();
    }

  • PS:完整流程请参考 Demo 中的 com.octopus.demo.NativeUnifiedAdActivity 的示例代码。

八、竞胜竞败回传(媒体 RTB 时调用,提高 ECPM 出价)

  • 说明:章鱼广告平台根据媒体传回来的竞胜竞败价格,通过相应算法自动提高出价来获得广告曝光,媒体 RTB 时一定要调用,否则会导致价格出不上去。

  • 示例:

    splashAd.sendWinNotice(1000); // 价格传竞价第二高价格
    splashAd.sendLossNotice(100,ADBidEvent.PRICE_LOW_FILTER,ADBidEvent.CSJ); // 价格传竞价最高的价格

8.1 接口说明

  • IBidding 接口说明

    方法名含义
    getECPM();获取本条广告实时的 eCPM 价格,单位是分
    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 小米
    * OCTOPUS 章鱼
    * 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 平台接入章鱼聚合文档

  • Topon 自定义广告接入地址:https://docs.toponad.com/#/zh-cn/android/NetworkAccess/customnetwork/customnetwork

  • 9.1 自定义广告源 adapter 参数

    参数填写:{"app_id":"应用ID","slot_id":"广告位ID","is_unified":"是否是自渲染1:是 0 否"}

    广告类型广告类名称服务端配置参数
    开屏com.octopus.group.topon.OctopusATSplashAdapter"app_id" // 应用 ID
    "slot_id" // 广告位 ID
    插屏com.octopus.group.topon.OctopusATInterstitialAdapter"app_id" // 应用 ID
    "slot_id" // 广告位 ID
    激励视频com.octopus.group.topon.OctopusATRewardVideoAdapter"app_id" // 应用 ID
    "slot_id" // 广告位 ID
    原生com.octopus.group.topon.OctopusATNativeAdapter"app_id" // 应用 ID
    "slot_id" // 广告位 ID
    "is_unified":"0"//渲染方式-模板渲染
    "is_unified":"1"//渲染方式-自渲染
    横幅com.octopus.group.topon.OctopusATBannerAdapter"app_id" // 应用 ID
    "slot_id" // 广告位 ID
  • 9.2 添加广告平台1

  • 9.3 创建广告源2