# 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