亿帆SDK-Android 快速指引

1. 开发文档修改记录

版本 修改内容 更新步骤 时间
6.0.0.0 1.调整广告源的依赖,本地变更远程maven库;
2.优化广告请求和展示策略,提升收益;
3.适配618活动,提升场景覆盖;
4.新增支持使用GroMore;
5.新增广告下载应用合规
必选:
1.更新依赖: implementation("com.yfanads.ads:sdk-core:6.0.0.0")
2024.5.8
5.3.3.8 1.自定义字段数据上报;
2.激励视频支持横版广告;
3.插屏自渲染优化弹框
必选:
1.更新依赖: implementation("com.yfanads.ads:sdk:5.3.3.8")
implementation("com.yfanads.ads:sdk-core:5.3.3.8")
implementation("com.yfanads.ads:sdk-factory:5.3.3.8")
2024.3.18
5.3.3.0 1.更新百度SDK;
2.更新快手SDK,初始化方式变成异步请求;
3.更新优量汇;
4.更新穿山甲;
5.优化广告请求下的优先展示逻辑;
6.支持流量分组自定义字段
必选:
1.更新依赖: implementation("com.yfanads.ads:sdk:5.3.3.0")
implementation("com.yfanads.ads:sdk-core:5.3.3.0")
implementation("com.yfanads.ads:sdk-factory:5.3.3.0")
implementation(name: "Baidu_MobAds_SDK-release_v9.34", ext: "aar")
implementation 'com.pangle.cn:ads-sdk-pro:5.9.1.4'
implementation(name: "kssdk-ad-33612", ext: "aar")
implementation 'com.qq.e.union:union:4.563.1433'
2024.3.15
5.3.2.6 1.优量汇、VIVO信息流上下文问题; 2.信息流模板渲染宽度媒体自定义,高度自适应 必选:
1.更新依赖:implementation("com.yfanads.ads:sdk-core:5.3.2.6")
implementation("com.yfanads.ads:sdk:5.3.2.4")
implementation("com.yfanads.ads:sdk-all:5.3.2.6")
2024.3.12
5.3.2.4 1.解决小米信息关闭在主线程中回调;2.信息流返回广告视图、广告源数据 必选:
1.更新依赖:implementation("com.yfanads.ads:sdk-core:5.3.2.4")
implementation("com.yfanads.ads:sdk:5.3.2.4")
implementation("com.yfanads.ads:sdk-all:5.3.2.4")
2024.3.5
5.3.2.2 1.优化京东展示问题;2.优化设备ID获取方式;3.拆分集成方式 必选:
1.更新依赖:implementation("com.yfanads.ads:sdk-core:5.3.2.2")
implementation("com.yfanads.ads:sdk:5.3.2.2")
2024.2.18
5.3.2.1 1.支持Draw流广告;2.支持贴片广告;优化广告请求和展示API 必选:
1.更新依赖:implementation("com.yfanads.ads:sdk-core:5.3.2.1")
2024.2.1
5.3.1.4 1.信息下亿帆广告播放器资源释放优化 必选:
1.更新依赖:implementation("com.yfanads.ads:sdk-core:5.3.1.3")
2024.1.11
5.3.1.2 1.修复摇一摇在特殊场景下生效问题 必选:
1.更新依赖:implementation("com.yfanads.ads:sdk-core:5.3.1.2")
2024.1.6
5.3.1.0 1.接入OPPO广告
2.接入华为广告
3.接入VIVO广告
4.接入小米广告
4.亿帆广告摇一摇功能优化,支持单双向
5.更新百度SDK9.332
6.更新快手SDK3.3.57
7.更新京东 SDK2.5.8
8.更新穿山甲SDK5.8.1.3
9.更新广点通SDK4.551
必选:
用户已经接入广告源,需要更新依赖:
implementation(name: "Baidu_MobAds_SDK-release_v9332", ext: "aar")
implementation(name: "open_ad_sdk_5813", ext: "aar")
implementation(name: "kssdk-ad-3357", ext: "aar")
implementation(name: "GDTSDK_4551", ext: "aar")
implementation(name: "jad_yun_sdk_jingdong_2.5.8_20231124", ext: "aar")
implementation "com.huawei.hms:ads-lite:13.4.67.300"
implementation(name: "open_ad_6.1.1.2", ext: "aar")
implementation(name: "mimo-ad-sdk", ext: "aar")
implementation(name: "open_ad_6.1.1.2", ext: "aar")
2024.1.5
5.3.0.10 1.快手只保留close事件
2.更新打点数据上报
必选:
1.更新依赖:implementation("com.yfanads.ads:sdk-core:5.3.0.10")
2023.11.30
5.3.0.9 1.调整混淆范围,保留完整包路径
2.解决播放器黑屏问题,使用最后一帧兜底
3.webview支持唤起和下载功能
4.解决亿帆广告使用播在列表播放出现黑屏问题
必选:
1.更新依赖:implementation("com.yfanads.ads:sdk-core:5.3.0.9")
2023.10.23
5.3.0.0 1.支持亿帆广告功能: 开屏、 插屏、激励视频、全屏视频
2.聚合广告的策略优化
3.本地aar依赖的方式修改成远程依赖
必选:
1.项目根目录Build.gradle新增: maven { url "https://maven.yfanads.com/repository/maven-public/" }
2.新增依赖:implementation("com.yfanads.ads:sdk-core:5.3.0.0")
2023.9.16
5.2.0.3 1.优化Banner位广告,广告容器高度自适应
2.更新穿山甲SDK至5.2.0.5
3.更新广点通版本至4.520.1390
4.更新快手版本至3.3.42
5.更新百度SDK至9.28
2023.8.25
5.2.0.0 1.修复已知问题
2.更新穿山甲SDK至5.1.0.2
3.更新广点通版本至4.512.1382
4.更新快手版本至3.3.40
2023.7.26
5.1.5.0 1.支持保底广告请求时机云控
2.调整自有广告上报打点
2023.7.7
5.1.0.0 1.自渲染广告提供获取六要素接口以及六要素View
2.更新穿山甲SDK至5.0.0.4
2.更新广点通SDK至4.500.1370
3.更新快手SDK至3.3.36
4.更新百度SDK至9.251
2023.6.21
5.0.5.0 1.兼容开屏广告容器非FrameLayout时快手开屏广告展示异常 2023.5.25
5.0.0.0 1.解决protobuf冲突问题
2.请求调度和内存优化
3.自渲染广告负反馈
优化自渲染广告展示回调问题
4.支持Bidding
2023.5.15

SDK版本说明列表

亿帆 穿山甲
(远程maven)
百度
(本地包)
优量汇
(远程maven)
快手
(本地包)
京东
(本地包)
6.0.0.0 com.pangle.cn:mediation-sdk:6.1.0.4 Baidu_MobAds_SDK-release_v9.35.aar com.qq.e.union:union:4.575.1445 kssdk-ad-3.3.63.aar jad_yun_sdk_jingdong_2.5.12.aar
5.3.3.8 com.pangle.cn:ads-sdk-pro:5.9.1.4 Baidu_MobAds_SDK-release_v9.34.aar com.qq.e.union:union:4.562.1432 kssdk-ad-33612.aar jad_yun_sdk_jingdong_2.5.10_20240130.aar
5.3.3.0 com.pangle.cn:ads-sdk-pro:5.9.1.4 Baidu_MobAds_SDK-release_v9.34.aar com.qq.e.union:union:4.562.1432 kssdk-ad-33612.aar jad_yun_sdk_jingdong_2.5.10_20240130.aar
5.3.2.6 com.pangle.cn:ads-sdk-pro:5.9.1.4 Baidu_MobAds_SDK-release_v9332.aar com.qq.e.union:union:4.562.1432 kssdk-ad-33591.aar jad_yun_sdk_jingdong_2.5.10_20240130.aar
5.3.2.1 com.pangle.cn:ads-sdk-pro:5.9.1.4 Baidu_MobAds_SDK-release_v9332.aar com.qq.e.union:union:4.562.1432 kssdk-ad-33591.aar jad_yun_sdk_jingdong_2.5.10_20240130.aar
亿帆 华为
(远程maven)
小米
(本地包)
vivo
(本地包)
oppo
(本地包)
6.0.0.0 com.huawei.hms:ads-lite:13.4.71.300 mimo-ad-sdk-531.aar open_ad_6.1.5.1.aar mobad_normal_pub_563004_2023_10_18.aar
5.3.3.8 com.huawei.hms:ads-lite:13.4.69.300 mimo-ad-sdk-530.aar open_ad_6.1.5.1.aar mobad_normal_pub_563004_2023_10_18.aar
5.3.3.0 com.huawei.hms:ads-lite:13.4.69.300 mimo-ad-sdk-530.aar open_ad_6.1.5.1.aar mobad_normal_pub_563004_2023_10_18.aar
5.3.2.6 com.huawei.hms:ads-lite:13.4.68.300 mimo-ad-sdk-530.aar open_ad_6.1.1.2.aar mobad_normal_pub_563004_2023_10_18.aar
5.3.2.1 com.huawei.hms:ads-lite:13.4.68.300 mimo-ad-sdk-530.aar open_ad_6.1.1.2.aar mobad_normal_pub_563004_2023_10_18.aar

2. 支持的SDK平台及广告位

SDK平台 开屏 激励视频 横幅 插屏(弹窗) 信息流 全屏视频 Draw流 贴片
穿山甲
优量汇
百青藤
快手
亿帆
京东
华为
小米
oppp
vivo

3. 快速接入

下面介绍亿帆SDK的快速接入方法,开发中也可以参考[Example]下的示例工程,快速了解。

开发环境

操作系统:支持 Linux/Mac/Windows 系统,具体依赖开发者选择的 IDE
开发工具:支持 Android studio
支持设备:运行了 Android 4.2.2 以及以上系统的 Android 设备(minSdkVersion 17) 

3.1 SDK包导入

3.1.1 申请应用广告位

请在亿帆平台上申请应用ID和广告位

3.1.2 导入aar和SDK依赖的jar包

3.1.2.1 添加仓库

顶级build.gradle中配置私库地址:

    maven {
        url "https://maven.yfanads.com/repository/maven-public/"
    }

3.1.2.2 添加依赖

AndroidX版本

因为亿帆SDK还没有使用AndroidX库,为了避免应用程序崩溃,请在项目的
gradle.properties中添加

   android.enableJetifier=true 
   android.useAndroidX=true

在主工程下(main)build.gradle中新增依赖

    implementation("com.yfanads.ads:sdk-core:6.0.0.0")

其中6.0.0.0版本号,查看发行版本

3.2 AndroidManifest配置

3.2.1 添加权限

    <uses-sdk tools:overrideLibrary="com.bun.miitmdid,com.easyads.supplier.ks,com.kwad.sdk,com.flayone.oaid,com.miui.zeus.mimo.sdk,com.bytedance.sdk.openadsdk" />

    <!--必须要有的权限-->
    <uses-permission android:name="android.permission.INTERNET" />

    <!--强烈推荐权限-->
    <!--强烈建议您在AndroidManifest.xml添加以下权限声明,若您的targetSDKVersion >= 23您还需要在运行时进行动态权限申请。
    注意:SDK不强制校验以下权限(即:无以下权限sdk也可正常工作),但建议您申请以下权限。
          针对单媒体的用户,允许获取权限的,投放定向广告;
          不允许获取权限的用户,投放通投广告。
          媒体可以选择是否把以下权限提供出来,并承担相应广告填充和eCPM单价下降损失的结果。-->
    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <!-- 可选,如果需要精确定位的话请加上此权限 -->
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

    <!--可选权限-->
    <!--下面权限可以优化用户的交互体验,提高eCPM。-->
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <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.SYSTEM_ALERT_WINDOW" />

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

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

3.3 混淆问题

请添加下面混淆规则到应用混淆规则中。

## ------聚合开始
-keep class com.yfanads.android.** { *; }
-keep class com.yfanads.ads.** { *; }
## ------聚合结束

# -------三方依赖开始
-keep class com.google.** { *; }
-dontwarn okio.**
-dontwarn com.ak.**
-dontwarn android.webkit.**
-dontwarn com.bytedance.sdk.**
-keep class android.** { *; }
-keep public class * implements com.bumptech.glide.module.GlideModule
-keep public enum com.bumptech.glide.load.resource.bitmap.ImageHeaderParser$** {
  **[] $VALUES;
  public *;
}
# -------三方依赖结束

3.4 添加组件

    <provider
        android:name="com.yfanads.android.adx.download.AdxFileProvider"
        android:authorities="${applicationId}.AdxFileProvider"
        android:exported="false"
        android:grantUriPermissions="true">
        <meta-data
            android:name="android.support.FILE_PROVIDER_PATHS"
            android:resource="@xml/adxfilepaths" />
    </provider>

3.5 支持微信小程序/小游戏跳转

微信小程序/小游戏广告,是指用户点击广告后,将跳转至微信打开微信小程序/小游戏,在微信内部发生后续的行为转化。

集成微信OpenSDK,可有效提升流量的填充和CPM值。整体接入流程:

  • 进入微信开放平台创建移动应用并获取到相应的微信AppID:
  • 在移动端嵌入最新版OpensDK(仅嵌入即可,无需额外开发工作),并确认版本为Android v5.3.1以上;
  • 提供AppID给亿帆运营进⾏绑定

3.6 初始化SDK

注意:需要在主线程中执行初始化方法

开发者需要在Application#onCreate()方法中调用以下代码来初始化亿帆SDK。
目前SDK已支持多进程,如果明确某个进程不会使用到广告SDK,可以只针对特定进程初始化广告SDK。

接入代码示例:参考Demo中的MyApplication类

public class MyApplication extends Application {

    @Override
    public void onCreate() {
        super.onCreate();
        

        // 一般是在主进程中初始化SDK,避免在其它不展示广告的进程中初始化SDK,浪费资源
        if (TextUtils.equals(this.getPackageName(), getProcessName(this))) {
            initSDK();
        }
    }

    private void initSDK() {
        YFAdsConfig fcAdsConfig =
                new YFAdsConfig.YFAdsConfigBuilder(GlobalConst.APP_ID)
                        // debug调试阶段的日志,正式包请注释
                        .setDebug(true)
                        // 当前有且只使用亿帆广告,需要打开,否者不用设置
//                        .setUseAdx(true)
                        .builder();
        YFAdsManager.getInstance().init(this, fcAdsConfig);
    }
    
    private boolean hasPermission(String permission) {
        return ActivityCompat.checkSelfPermission(this, permission) == PackageManager.PERMISSION_GRANTED;
    }

    private String getProcessName(Context context) {
        if (context == null) return null;
        ActivityManager manager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
        for (ActivityManager.RunningAppProcessInfo processInfo : manager.getRunningAppProcesses()) {
            if (processInfo.pid == android.os.Process.myPid()) {
                return processInfo.processName;
            }
        }
        return null;
    }
}

主要API

YFAdsManager

方法名 方法介绍
init(Application application, YFAdsConfig YFAdsConfig) 初始化SDK
YFAdsConfig getYFAdsConfig() 获取亿帆SDK的配置,详细参考YFAdsConfig类

YFAdsConfigBuilder

方法名 方法介绍
public YFAdsConfigBuilder(String appId) 初始化的方法,appId在平台申请的AppId
public YFAdsConfig setDebug(Boolean debug) 是否是调试模式
public YFAdsConfigBuilder setCanUseLocation(boolean canUseLocation) 设置是否允许SDK主动使用地理位置信息。true可以获取,false禁止获取。默认为true
public YFAdsConfigBuilder setYFLocation(YFLocation yfLocation) 传入地理位置信息, 当canUseLocation=false时,亿帆sdk使用您传入的地理位置信息
public YFAdsConfigBuilder setCanUsePhoneState(boolean canUsePhoneState) 设置是否允许SDK主动使用手机硬件参数,如:imei。true可以使用,false禁止使用。默认为true
public YFAdsConfigBuilder setDevImei(String devImei) 可传入imei信息,当canUsePhoneState=false时,亿帆sdk使用您传入的imei信息
public YFAdsConfigBuilder setCanUseWifiState(boolean canUseWifiState) 设置是否允许SDK主动使用ACCESS_WIFI_STATE权限获取MAC信息。true可以使用,false禁止使用。默认为true
public YFAdsConfigBuilder setCanUseWriteExternal(boolean canUseWriteExternal) 设置是否允许SDK主动使用WRITE_EXTERNAL_STORAGE权限。true可以使用,false禁止使用。默认为true
public YFAdsConfigBuilder setDevOaid(String devOaid) 传入OAID,当canUseOaid=false时,亿帆sdk使用您传入的OAID
public YFAdsConfigBuilder setCanUseAppList(boolean canUseAppList) 设置是否允许SDK主动获取应用列表,判定广告对应的应用是否在用户的app上安装,避免投放错误的广告,以此提高用户的广告体验。true可以使用,false禁止使用。默认为true
public YFAdsConfigBuilder setCanUseAndroidId(boolean canUseAndroidId) 设置是否允许SDK主动使用AndroidId。true可以使用,false禁止使用。默认为true
public YFAdsConfigBuilder setLimitPersonal(boolean limitPersonal) 设置是否允许SDK设置个性化推荐。true限制个性化推荐,false不限制。默认为false
public YFAdsConfigBuilder setUseAdx(boolean isOnlyAdx) 设置只使用亿帆广告功能(废弃)
public void setCustomDefine(Map<String, Object> customDefine) 广告自定义字段:不支持中文;不能嵌套,仅支持int string float
public YFAdsConfig builder() 创建配置对象实例

3.7 隐私开关

  • 目前SDK已支持工信部隐私敏感权限要求
  • 敏感权限,用户同意则使用,若用户拒绝则不再获取
  • 申请权限界面由应用依据自身情况、用户真实选择,使用如下API更新隐私信息权限开关

    注意:目前OAID不属于个人信息保护法律范畴,建议提供获取的能力。

主要API

YFAdsConfig

方法名 方法介绍
public void setCanUseLocation(boolean canUseLocation) 设置是否允许SDK主动使用地理位置信息。true可以获取,false禁止获取。默认为true
public void setYFLocation(YFLocation yfLocation) 传入地理位置信息, 当canUseLocation=false时,亿帆sdk使用您传入的地理位置信息
public void setCanUsePhoneState(boolean canUsePhoneState) 设置是否允许SDK主动使用手机硬件参数,如:imei。true可以使用,false禁止使用。默认为true
public void setDevImei(String devImei) 可传入imei信息,当canUsePhoneState=false时,亿帆sdk使用您传入的imei信息
public void setCanUseWifiState(boolean canUseWifiState) 设置是否允许SDK主动使用ACCESS_WIFI_STATE权限获取MAC信息。true可以使用,false禁止使用。默认为true
public void setCanUseWriteExternal(boolean canUseWriteExternal) 设置是否允许SDK主动使用WRITE_EXTERNAL_STORAGE权限。true可以使用,false禁止使用。默认为true
public void setDevOaid(String devOaid) 传入OAID,当canUseOaid=false时,亿帆sdk使用您传入的OAID
public void setCanUseAppList(boolean canUseAppList) 设置是否允许SDK主动获取应用列表,判定广告对应的应用是否在用户的app上安装,避免投放错误的广告,以此提高用户的广告体验。true可以使用,false禁止使用。默认为true
public void setCanUseAndroidId(boolean canUseAndroidId) 设置是否允许SDK主动使用AndroidId。true可以使用,false禁止使用。默认为true
public void setLimitPersonal(boolean limitPersonal) 设置是否允许SDK设置个性化推荐。true限制个性化推荐,false不限制。默认为false
public void setCustomDefine(Map<String, Object> customDefine) 广告自定义字段:不支持中文;不能嵌套,仅支持int string float

3.8 合规四步走

  • 参考合规指南

  • 您需要确保App有隐私政策
    并且在用户首次启动App时就弹出隐私政策
    取得用户同意


  • 您务必告知用户,您选择亿帆SDK服务;请在隐私政策
    中增加如下参考条款:

    我们的产品集成亿帆SDK,亿帆SDK需要收集您的设备Mac地址、唯一设备识别码(
    IMEI/android ID)、SIM卡IMSI信息、地理位置信息以提供个性化推荐内容,提升用户体验。


  • 您务必确保用户同意隐私政策之后,再初始化亿帆SDK。

  • 目前SDK初始化不主动获取用户隐私相关信息。如媒体侧授权后,可以重新设置用户隐私相关配置,可使用如下代码:

  YFAdsConfig adsConfig = YFAdsManager.getInstance().getYFAdsConfig();
  adsConfig.setXXXX

其中setXXX方法参考YFAdsConfig类的API

3.9 关闭个性化

  • 为遵循《个人信息保护法》相关法规,亿帆SDK将为开发者提供个性化广告关闭能力接口,开发者可以调用接口,为开发者媒体应用的用户提供个性化广告关闭能力。

  • 开发者应遵循法律法规要求,在客户端为用户创建可便捷查找的个性化广告关闭按钮,并保证用户点击关闭按钮后调用亿帆SDK关闭能力接口,保证个性化广告关闭功能真实有效。

主要API

YFAdsConfig

方法名 方法介绍
setLimitPersonal(boolean limitPersonal) 设置限制个性化广告推荐。true 开启个性化推荐能力,false关闭个性化推荐能力,默认为true

4. 聚合三方SDK

4.1 穿山甲SDK

4.1.1 添加依赖

  • 找到工程的build.gradle文件,在dependencies节点进行远程仓库
  // 穿山甲
  maven { url 'https://artifact.bytedance.com/repository/pangle' }

  • 在app目录下添加aar远程依赖
    //穿山甲广告SDK(适配+原sdk)
    implementation("com.yfanads.ads:adapter-csj:6.1.0.4")
  • 自动引入广告源sdk,对应版本如”SDK版本说明列表“所示,如果项目有穿山甲广告源则可以使用
    //穿山甲广告SDK(适配+原sdk)
    implementation("com.yfanads.ads:adapter-csj:6.1.0.4") {
        exclude group: 'com.pangle.cn', module: 'mediation-sdk'
    }

4.1.2 添加权限

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

4.1.3 添加组件

<!-- bytedance start -->
<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/tt_provider_paths" />
</provider>
<provider
	android:name="com.bytedance.sdk.openadsdk.multipro.TTMultiProvider"
	android:authorities="${applicationId}.TTMultiProvider"
	android:exported="false" />
<!-- bytedance end -->

4.1.4 添加混淆

# csj sdk start
#3900版本及以上版本混淆规则如下:
-keep class com.bytedance.sdk.openadsdk.** { *; }
-keep class com.bytedance.frameworks.** { *; }
-keep class ms.bd.c.Pgl.**{*;}
-keep class com.bytedance.mobsec.metasec.ml.**{*;}
-keep class com.ss.android.**{*;}
-keep class com.bytedance.embedapplog.** {*;}
-keep class com.bytedance.embed_dr.** {*;}
-keep class com.bykv.vk.** {*;}
# csj sdk end

#gromore start
-keep class bykvm*.**
-keep class com.bytedance.msdk.adapter.**{ public *; }
-keep class com.bytedance.msdk.api.** {
 public *;
}
-keep class com.bytedance.msdk.base.TTBaseAd{*;}
-keep class com.bytedance.msdk.adapter.TTAbsAdLoaderAdapter{
    public *;
    protected <fields>;
}
#gromore end

4.2 百度SDK

4.2.1 添加依赖

  • 找到工程的build.gradle文件,在dependencies节点进行如下添加即可:
    //百度广告SDK(适配+原sdk)
    implementation("com.yfanads.ads:adapter-bd:9.35")
  • 自动引入广告源sdk,对应版本如”SDK版本说明列表“所示,如果项目有百度广告源则可以使用
    //百度广告SDK(适配+原sdk)
    implementation("com.yfanads.ads:adapter-bd:9.35") {
        exclude group: 'com.baidu.mobads', module: 'sdk'
    }

4.2.2 添加权限

4.2.3 添加组件

4.2.4 添加混淆

#baidu start
-keep class com.baidu.mobads.** { *; }
#baidu end

如果您的工程中接入了资源混淆插件AndResGuard,为了保证SDK的资源可以被正常使用,需要在build.gradle中新增白名单配置,内容如下:

andResGuard {
  // 白名单配置
  whiteList = [
               "R.integer.min_screen_width_bucket",
               "R.style.DialogAnimationUp",
               "R.style.DialogAnimationRight",
               "R.style.DialogFullScreen",
               "R.drawable.gdt_*"
               ]
}

4.3 快手SDK

4.3.1 添加依赖

  • 找到工程的build.gradle文件,在dependencies节点进行如下添加即可:
    // 快手广告SDK(适配+原sdk)
    implementation("com.yfanads.ads:adapter-ks:3.3.63")
    implementation 'androidx.localbroadcastmanager:localbroadcastmanager:1.1.0'  ...
  }
  • 自动引入广告源sdk,对应版本如”SDK版本说明列表“所示,如果项目有快手广告源则可以使用
    // 快手广告SDK(适配+原sdk)
    implementation("com.yfanads.ads:adapter-ks:3.3.63") {
        exclude group: 'com.ks.kwad', module: 'sdk'
    }

4.3.2 添加权限

4.3.3 添加组件

4.3.4 添加混淆

#kuaishou begin
-keep class org.chromium.** {*;}
-keep class org.chromium.** { *; }
-keep class aegon.chrome.** { *; }
-keep class com.kwai.**{ *; }
-dontwarn com.kwai.**
-dontwarn com.kwad.**
-dontwarn com.ksad.**
-dontwarn aegon.chrome.**
#kuaishou end

4.3.5 快手so架构问题

目前快手最新的SDK版本不支持armeabi架构,如果apk集成的so文件和apk安装的OS仅匹配到armeabi目录下的so,会导致快手广告无法填充。

解决方案:将快手aar后缀改为zip,解压之后进入jni/armeabi-v7a目录,将其中所有的so文件拷贝到工程的app/libs/armeabi中,然后打包apk即可

4.4 优量汇SDK

4.4.1 添加依赖

  • 找到工程的build.gradle文件,在dependencies节点进行如下添加即可:
    // 优量汇广告SDK(适配+原sdk)
    implementation("com.yfanads.ads:adapter-ylh:4.575.1445") 
  ...
  }
  • 自动引入广告源sdk,对应版本如”SDK版本说明列表“所示,如果项目有优量汇广告源则可以使用
    // 优量汇广告SDK(适配+原sdk)
    implementation("com.yfanads.ads:adapter-ylh:4.575.1445") {
        exclude group: 'com.qq.e.union', module: 'union'
    }

4.4.2 添加权限

4.4.3 添加组件

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

4.4.4 添加混淆

# GDT sdk start
-dontwarn com.qq.e.**
-keep class com.qq.e.** {*;}
-dontpreverify
# GDT sdk end

4.5 京东SDK

4.5.1 添加依赖

  • 找到工程的build.gradle文件,在dependencies节点进行如下添加即可:
    // 京东广告SDK(适配+原sdk)
    implementation("com.yfanads.ads:adapter-jd:2.5.12") 
    // androidX项目需要导入
    implementation 'androidx.localbroadcastmanager:localbroadcastmanager:1.1.0'
  ...
  }
  • 自动引入广告源sdk,对应版本如”SDK版本说明列表“所示,如果项目有京东广告源则可以使用
    // 京东广告SDK(适配+原sdk)
    implementation("com.yfanads.ads:adapter-jd:2.5.12") {
        exclude group: 'com.github.JAD-FE-TEAM.JADYunAndroid', module: 'jad_yun_sdk'
    }

4.5.2 添加权限

4.5.3 添加组件

4.5.4 添加混淆

# JD sdk start
-keep class com.jd.ad.sdk.** { *; }
# JD sdk end

4.6 华为SDK

4.6.1 添加依赖

  • 在build.gradle添加远程依赖库
  // 配置华为鲸鸿动能SDK的Maven仓地址
  maven { url 'https://developer.huawei.com/repo/' }
  • 找到工程的build.gradle文件,在dependencies节点进行如下添加即可:
    //华为广告SDK(适配+原sdk)
    implementation("com.yfanads.ads:adapter-hw:13.4.71.300")
  • 自动引入广告源sdk,对应版本如”SDK版本说明列表“所示,如果项目有华为广告源则可以使用
    //华为广告SDK(适配+原sdk)
    implementation("com.yfanads.ads:adapter-hw:13.4.71.300") {
        exclude group: 'com.huawei.hms', module: 'ads-lite'
    }

4.6.2 添加权限

4.6.3 添加组件

4.6.4 添加混淆

# HuaWei SDK
-keep class com.huawei.openalliance.ad.** { *; }
-keep class com.huawei.hms.ads.** { *; }

4.7 小米SDK

4.7.1 添加依赖

  • 找到工程的build.gradle文件,在dependencies节点进行如下添加即可:
    //小米广告SDK(适配+原sdk)
    implementation("com.yfanads.ads:adapter-xm:531")
  • 自动引入广告源sdk,对应版本如”SDK版本说明列表“所示,如果项目有小米广告源则可以使用
    //小米广告SDK(适配+原sdk)
    implementation("com.yfanads.ads:adapter-xm:531") {
        exclude group: 'com.xiaomi.ads', module: 'sdk'
    }

4.7.2 添加权限

4.7.3 添加组件

    <!-- 小米 -->
    <provider
      android:name="androidx.core.content.FileProvider"
      android:authorities="${applicationId}.fileprovider"
      android:exported="false"
      android:grantUriPermissions="true">
      <meta-data
          android:name="android.support.FILE_PROVIDER_PATHS"
          android:resource="@xml/xm_file_paths" />
    </provider>

4.7.4 添加混淆

# Xm SDK
-keep class com.miui.zeus.** { *; }

4.8 OPPO SDK

4.8.1 添加依赖

  • 找到工程的build.gradle文件,在dependencies节点进行如下添加即可:
    //oppo广告SDK(适配+原sdk)
    implementation("com.yfanads.ads:adapter-oppo:580004")
  • 自动引入广告源sdk,对应版本如”SDK版本说明列表“所示,如果项目有OPPO广告源则可以使用
    //oppo广告SDK(适配+原sdk)
    implementation("com.yfanads.ads:adapter-oppo:580004") {
        exclude group: 'com.oppo.ads', module: 'sdk'
    }

4.8.2 添加权限

4.8.3 添加组件

4.8.4 添加混淆

# Oppo SDK
-keep class com.opos.** { *;}
-keep class com.heytap.msp.mobad.** { *;}
-keep class com.heytap.openid.** {*;}

-keep class okio.**{ *; }

-keeppackagenames com.heytap.nearx.tapplugin

4.9 VIVO SDK

4.9.1 添加依赖

  • 找到工程的build.gradle文件,在dependencies节点进行如下添加即可:
    //vivo广告SDK(适配+原sdk)
    implementation("com.yfanads.ads:adapter-vivo:6.1.5.1")
  • 自动引入广告源sdk,对应版本如”SDK版本说明列表“所示,如果项目有VIVO广告源则可以使用
    //vivo广告SDK(适配+原sdk)
    implementation("com.yfanads.ads:adapter-vivo:6.1.5.1") {
        exclude group: 'com.vivo.ads', module: 'sdk'
    }

4.9.2 添加权限

4.9.3 添加组件

4.9.4 添加混淆

# Vivo SDK
-dontwarn okhttp3.**
-dontwarn android.support.v4.**
-dontwarn com.squareup.okhttp.**
-keep class com.vivo.*.** { *; }
-dontwarn com.bytedance.article.common.nativecrash.NativeCrashInit
-keep class com.bytedance.sdk.openadsdk.** {*;}
-keep public interface com.bytedance.sdk.openadsdk.downloadnew.** {*;}
-keep class com.pgl.sys.ces.* {*;}
-keep class com.qq.e.** {
    public protected *;
}
-keep class android.support.v4.**{
    public *;
}
-dontwarn com.vivo.secboxsdk.**
-keep class com.vivo.secboxsdk.SecBoxCipherException { *; }
-keep class com.vivo.secboxsdk.jni.SecBoxNative { *; }
-keep class com.vivo.secboxsdk.BuildConfig { *; }

-keep class android.support.v7.widget.** {*;}

5. 加载广告

目前亿帆SDK支持以下物理广告位类型:Banner位插屏激励视频开屏信息流全屏视频Draw流贴片

请根据自身广告位类型进行对接。

注意
目前API对context没有做强制限制,推荐传递当前activity,否者优量汇(Banner、插屏、全屏视频)、OPPO(Banner、插屏、全屏视频)、VIVO(Banner、插屏、全屏视频、开屏、信息流)广告无法展示。

主要API

BaseAdListener

方法名 方法介绍
void onAdSuccess(); 加载广告成功
void onAdExposure(); 广告曝光成功
void onAdClicked(); 广告点击
void onAdClosed(); 广告关闭
void onAdFailed(YFAdError yfAdError); 广告加载失败

YFAdError

状态码 (code) 说明
99 加载广告成功
1001 网络返回失败
1004 请求广告超过策略时长
1005 广告策略超时
1006 广告策略数据为空
9901 广告返回的数据为空
9902 广告加载异常
9903 广告展示失败
9904 广告渲染失败
9905 未配置SDK渠道
9906 执行SDK渠道选择是发生异常
9907 没有策略
9908 联盟SDK启动失败
9909 穿山甲SDK加载超时,不再加载后续SDK渠道
9910 穿山甲SDK加载超时
9911 百度SDK加载失败
9912 快手SDK加载失败,广告位id类型转换异常
9913 当前activity已被销毁,不再请求广告
9914 快手SDK初始化失败
99141 无快手类型
99142 无百度类型
9915 广告渲染失败
9916 穿山甲SDK初始化失败
9917 没有集成sdk
9920 自渲染失败
9921 优量汇广告请求上下文非activity
9922 oppo广告请求上下文非activity
9923 vivo广告请求上下文非activity
9924 穿山甲GroMore广告请求上下文非activity

5.1 Banner位

具体可参见demo中BannerActivity

请求Banner位广告时,需要设置广告View的宽度(单位:dp),会根据设置的宽度计算出最优高度。

当选择竖版样式时,接入方可以设置广告View的高度,SDK会自动等比例缩放广告图片,如果不设置高度,会根据设置的宽度计算出最优高度。

接入代码示例

    private void startBanner() {
        showADBanner = new YFAdBanner(this, new YFBannerListener() {
            @Override
            public void onAdSuccess() {
                logAndToast("广告加载成功");
                showAds();
            }

            @Override
            public void onAdExposure() {
                logAndToast("广告展现");
            }

            @Override
            public void onAdClicked() {
                logAndToast("广告点击");
            }

            @Override
            public void onAdClosed() {
                logAndToast("广告关闭");
            }

            @Override
            public void onAdFailed(YFAdError yfAdError) {
                logAndToast("广告加载失败 code=" + yfAdError.code + " msg=" + yfAdError.msg);
            }
        });
        logAndToast("广告请求中");

        // 这个是实例的广告,实际客户自己定义,单位是dp
        int width = ScreenUtil.px2dip(getApplicationContext(),
                (float) (ScreenUtil.getScreenWidth(getApplicationContext())));
        //如果高度传入0代表自适应高度
        showADBanner.setViewAcceptedSize(width, 0);
        Log.d("TEST", "开始加载");
        showADBanner.loadOnly(potId);
    }

    private void showAds() {
        if (showADBanner != null) {
            showADBanner.showAds(this, adView);
        }
    }
    
    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (showADBanner != null) {
            showADBanner.destroy();
            showADBanner = null;
        }
    }

主要API

YFADBanner

方法名 方法介绍
public YFAdBanner(Context context, YFBannerListener listener) Banner位广告位构造方法: 其中Context推荐为当前activity,否者优量汇、OPPO、VIVO广告无法展示
public void setViewAcceptedSize(int expressViewWidth, int expressViewHeight) 期望模板广告view的size,单位dp
public void loadOnly(String posId) 请求广告(与showAds一一对应)
public void showAds(Activity activity, ViewGroup adView) 展示广告(与loadOnly一一对应)
public void destroy() 广告不使用后,及时释放资源

YFBannerListener

5.2 插屏

具体可参见demo中InterstitialActivity

接入代码示例

    private void startInterstitial(String adId) {
         if (isShowAd) {
            // 当前正在展示
            return;
        }
        //前面一个插屏资源释放
        if (easyInterstitial != null) {
            easyInterstitial.destroy();
            easyInterstitial = null;
        }
        //初始化
        easyInterstitial = new YFAdInterstitialAds(this, new YFInterstitialListener() {

            @Override
            public void onAdSuccess() {
                logAndToast("广告就绪");
                showAds();
            }

            @Override
            public void onAdExposure() {
                logAndToast("广告展示");
            }

            @Override
            public void onAdClicked() {
                logAndToast("广告点击");
            }

            @Override
            public void onAdClosed() {
                logAndToast("广告关闭");
                isShowAd = false;
            }

            @Override
            public void onAdFailed(YFAdError yfAdError) {
                logAndToast("广告加载失败 code=" + yfAdError.code + " msg=" + yfAdError.msg);
                isShowAd = false;
            }
        });
   
        //必须:设置策略信息
        easyInterstitial.loadOnly(adId);
    }
    
    private void showAds() {
        if (easyInterstitial != null) {
            easyInterstitial.showAds(this);
        }
    }
    
    @Override
    protected void onDestroy() {
        super.onDestroy();
        // 资源释放
        if (easyInterstitial != null) {
            easyInterstitial.destroy();
            easyInterstitial = null;
        }
    } 

在同一页面中,插屏广告原则上只能展示一个,如果当前已经展示了,则不用再次请求,可以通过isShowAd判断是否展示,如果展示,则不请求。

主要API

YFAdInterstitialAds

方法名 方法介绍
public YFAdInterstitialAds(Context context, YFBannerListener listener) 插屏广告位构造方法,其中Context推荐为当前activity,否者优量汇、OPPO、VIVO广告无法展示
public void loadOnly(String jsonString) 请求广告(与showAds一一对应)
public void showAds(Activity activity) 展示广告(与loadOnly一一对应)
public void destroy() 广告不使用后,及时释放资源

YFInterstitialListener

5.3 激励视频

具体可参见demo中RewardVideoActivity(竖版)、RewardVideoLandActivity(横版):其中小米、华为、穿山甲、oppo需要联系运营同学申请创建单独广告位。

接入代码示例

    private void startReward(String adId) {
        //必须:核心事件监听回调
        //初始化,注意需要时再初始化,不要复用。
        easyRewardVideo = new YFAdRewardAds(this,  new YFRewardVideoListener() {

            @Override
            public void onAdSuccess() {
                logAndToast("广告加载成功");
                showAds();
            }

            @Override
            public void onAdExposure() {
                logAndToast("广告展示");
            }

            @Override
            public void onAdClicked() {
                logAndToast("广告点击");
            }

            @Override
            public void onAdClosed() {
                logAndToast("广告关闭");
                RewardVideoActivity.this.finish();
            }

            @Override
            public void onAdFailed(YFAdError yfAdError) {
                logAndToast("广告加载失败 code=" + yfAdError.code + " msg=" + yfAdError.msg);
                RewardVideoActivity.this.finish();
            }


            @Override
            public void onVideoCached() {
                logAndToast("广告缓存成功");
            }

            @Override
            public void onVideoComplete() {
                logAndToast("视频播放完毕");
            }

            @Override
            public void onVideoSkip() {
                logAndToast("跳过视频");
            }

            @Override
            public void onRewardServerInf(YFRewardServerCallBackInf inf) {
                logAndToast("奖励发放成功");
                if (inf != null) {
                    onRewardServer(inf.rewardInf);
                }
            }
        }, "123456");
        // 自由业务拓展的字段
        easyRewardVideo.setAppExtra("packageName", "com.fc.example");
        easyRewardVideo.loadOnly(adId);
    }
    
    private void showAds() {
        if (easyRewardVideo != null) {
            easyRewardVideo.showAds(RewardVideoActivity.this);
        }
    }
    
    // 返回不同激励视频得回调
    private void onRewardServer(YFRewardServerCallBackInf.RewardInf rewardInf) {

        Log.d("reward", "type = " + rewardInf.type + " , " + rewardInf.appExtra);

        if (rewardInf instanceof YFRewardServerCallBackInf.BDRewardInf) {
            Log.d("reward", "type = BDRewardInf ");
        } else if (rewardInf instanceof YFRewardServerCallBackInf.YlhRewardInf) {
            Log.d("reward", "type = YlhRewardInf");
        } else if (rewardInf instanceof YFRewardServerCallBackInf.KsRewardInf) {
            Log.d("reward", "type = KsRewardInf");
        } else if (rewardInf instanceof YFRewardServerCallBackInf.CsjRewardInf) {
            Log.d("reward", "type = CsjRewardInf");
        } else {
            Log.d("reward", "type = Other");
        }
    }
    
    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (easyRewardVideo != null) {
            easyRewardVideo.destroy();
            easyRewardVideo = null;
        }
    }
}

主要API

YFAdRewardAds

方法名 方法介绍
public YFAdRewardAds(Context context, YFRewardVideoListener baseAdListener, String userId) 激励视频广告位构造方法, userId:媒体侧用户ID
public void loadOnly(String posId) 请求广告(与showAds一一对应)
public void showAds(Activity activity) 展示广告(与loadOnly一一对应)
public void setOrientation(int orientation) 显示横版还是竖版,参数是:YFAdsConst.HORIZONTAL或YFAdsConst.VERTICAL
public void destroy() 广告不使用后,及时释放资源

YFRewardVideoListener

方法名 方法介绍
void onVideoCached(); 广告缓存成功
void onVideoComplete(); 视频播放完毕
void onVideoSkip(); 跳过视频
void onAdReward(); 激励发放
void onRewardServerInf(YFRewardServerCallBackInf inf); 激励视频返回的服务器回调信息,穿山甲一直支持,优量汇自v4.330.1200 开始支持,百度9.13开始支持

YFRewardVideoListener

变量 变量介绍
RewardInf rewardInf 回调类型

RewardInf

变量 变量介绍
Type type 类型
Map<String, String> appExtra App传递的值

Type

变量 变量介绍
KS 快手
YLH 优量汇
ADX 亿帆
BD 百度
CSJ 穿山甲
XM 小米
OPPO oppo
HW 华为
VIVO vivo

BDRewardInf

变量 变量介绍
boolean bdRewardVerify 百度是否需要验证

YlhRewardInf

变量 变量介绍
String ylhTransId 优量汇交易ID

KsRewardInf

变量 变量介绍

CsjRewardInf

变量 变量介绍
boolean rewardVerify 是否有效
int rewardType 奖励类型,0:基础奖励 >0:进阶奖励
int rewardAmount 发放数量
String rewardName 奖励名称
float rewardPropose 建议奖励百分比
int code 状态码
String message 信息

5.4 开屏

具体可参见demo中SplashActivity

注意:

1. 展示开屏广告的容器状态必须为可见,否则不返回广告。

2. 开屏广告容器高度必须大于等于屏幕高度的75%,否则广告会出现一闪而过现象。

重要1:开屏页请设置为全屏样式,并隐藏虚拟按键和状态栏,防止跳过按钮和广告标识被遮挡

重要2: 开屏对物理返回键屏蔽,影响曝光数据

重要3: 如果开屏接入OPPO并需要全屏显示(Theme是fullscreen)(不展示底部LOGO),请联系商务经理。
如果展示底部自定义LOGO,则需要设置setBottomView()方法并在onAdSuccess回调方法中设置其可见。

重要4: 开屏点击广告后,1.跳转到落地页或者拉起其它应用,当广告展示时间完毕后回调onAdClosed,此时应该忽略,当从落地页返回到开屏广告页面时,要跳转到应用主界面;2. 进入下载操作,界面还是停留在开屏广告界面直到展示完毕回调onAdClosed。

@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
    if (keyCode == KeyEvent.KEYCODE_BACK || keyCode == KeyEvent.KEYCODE_HOME) {
        return true;
    }
    return super.onKeyDown(keyCode, event);
}

接入代码示例


    // 标记广告是否被点击
    // 广告点击后会有两种情况:
    // 1. 跳转到落地页或者拉起其它应用,当广告展示时间完毕后回调onAdClosed,此时应该忽略,
    //    当从落地页返回到开屏广告页面时,要跳转到应用主界面
    // 2. 进入下载操作,界面还是停留在开屏广告界面直到展示完毕回调onAdClosed
    private boolean isClicked = false;
    // 标记从跳转到落地页或拉起其它应用,当isLeftActivity为true时,忽略onSplashAdDismiss回调
    private boolean isLeftActivity = false;
    // 标记广告是否已关闭
    // 当开屏页在后台时,回调onSplashAdDismiss不跳转到主界面;
    // 等开屏页到前台后,跳转到主界面
    private boolean isAdDismiss = false;

    @Override
    public void initView(Bundle savedInstanceState) {
      type = getIntent().getIntExtra("type", GlobalConst.ERROR_NUM);
      String potId = getIntent().getStringExtra("potId");
    
      adContainer = findViewById(R.id.splash_container);
      adLogoLly = findViewById(R.id.ll_logo);
    
      if (!TextUtils.isEmpty(potId)) {
          loadSplash(adContainer, potId);
        }
      }

    private void loadSplash(ViewGroup adContainer, String adId) {
        fcAdSplash = new YFAdSplashAds(this, new YFSplashListener() {
            @Override
            public void onAdSuccess() {
                logAndToast("广告加载成功 ");
                if (adLogoLly.getVisibility() == View.GONE) {
                    adLogoLly.setVisibility(View.VISIBLE);
                }
                showAds(adContainer);
            }

            @Override
            public void onAdExposure() {
                //设置开屏父布局背景色为白色
                logAndToast("广告展示成功");
            }

            @Override
            public void onAdClicked() {
                logAndToast("广告点击");
                isClicked = true;
            }

            @Override
            public void onAdClosed() {
                Log.i("test", "onAdClosed ");
                isAdDismiss = true;
                if (/*isClicked && */isLeftActivity) {
                    logAndToast("onAdClosed. 广告被点击跳转到其它界面或按HOME键压入后台时,忽略此回调");
                    return;
                }
                // 场景:1.倒计时结束并且广告未点击;2.类似广点通广告点击跳过按钮
                goToMainActivity();
            }

            @Override
            public void onAdFailed(YFAdError yfAdError) {
                logAndToast("广告加载失败 code=" + yfAdError.code + " msg=" + yfAdError.msg);
                goToMainActivity();
            }

        });
        // 实际展示的高度,但不低于屏幕高度的75% (屏幕高度-LOGO高度-底部状态栏区域)
        int expressViewHeight = AppUtils.px2dip(this, AppUtils.getScreenHeight(this));
        // 如果底部需要展示logo,此为logo的大小,单位是dp
        expressViewHeight -= 63;
        // 设置实际请求的高度
        fcAdSplash.setHeight(expressViewHeight);
        // 设置底部LOGO的View的区域
        fcAdSplash.setBottomView(adLogoLly);
        fcAdSplash.loadOnly(adId);
        logAndToast("广告请求中");
    }
     
    private void showAds(ViewGroup adContainer) {
        if (fcAdSplash != null) {
            fcAdSplash.showAds(SplashActivity.this, adContainer);
        }
    }
    
    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (fcAdSplash != null) {
            fcAdSplash.destroy();
            fcAdSplash = null;
        }
    }
    
    @Override
    protected void onResume() {
        super.onResume();
        if (isClicked || isAdDismiss) {
            logAndToast("广告关闭");
            goToMainActivity();
        }
        isLeftActivity = false;
    }

    @Override
    protected void onPause() {
        super.onPause();
        isLeftActivity = true;
    }

主要API

YFAdSplashAds

方法名 方法介绍
public YFAdSplashAds(Context context, YFSplashListener baseAdListener) 开屏广告位构造方法:其中Context推荐为当前activity,否者VIVO无法展示
public void loadOnly(String posId) 请求广告(与showAds一一对应)
public void showAds(Activity activity, ViewGroup adContainer) 展示广告(与loadOnly一一对应)
public void setBottomView(View bottom) 设置底部Logo区域
public void destroy() 广告不使用后,及时释放资源

YFSplashListenerBaseAdListener回调监听

5.5 信息流

具体可参见demo中NativeExpressRecyclerViewActivity,其中期望realAdNumber的广告数量一次不能超过5条,实际返回广告数量为0-5条

接入代码示例

    /**
       * 加载并展示原生模板信息流广告.
       *
       * @param adId        adId
       * @param adContainer adContainer
       * @author JamesQian
       * @date 2023/9/9 17:29
       **/
      private void loadNativeExpress(String adId, ViewGroup adContainer, RycItem rycItem, final int pos) {
          // 需要计算当前的index
          if (rycItem.isReq) {
              // 正在发请求
              Log.d("TEST", "ad is req " + pos);
              return;
          }
          if (rycItem.expView == null) {
              startRequestAds(adId, pos);
          } else {
              ExpView expView = rycItem.expView;
              if (expView.getView() != null) {
                  if (expView.getView().getParent() != null) {
                      Log.d("TEST", "ad has add " + pos);
                      return;
                  }
                  adContainer.removeAllViews();
                  adContainer.addView(expView.getView());
              } else {
                  expView.render(adContainer);
              }
          }
      }

      private void startRequestAds(String adId, final int pos) {
          Log.d("TEST", "ads start req - " + pos);
          YFAdNativeExpressAds easyNativeExpress =
                  new YFAdNativeExpressAds(mActivity.get(), new YFNativeExpressListener() {
                      @Override
                      public void onAdRenderFailed() {
                          reBackData(pos);
                      }

                      @Override
                      public void onAdRenderSuccess(List<ExpView> list) {
                          Log.d("TEST", "onAdRenderSuccess:" + list.size() + " pos = " + list.get(0));
                          updateData(list);
                      }

                      @Override
                      public void onAdSuccess() {
                          startShowAd(pos);
                      }

                      @Override
                      public void onAdFailed(YFAdError yfAdError) {
                          Log.i("TEST", "onAdFailed " + yfAdError + " , pos = " + pos);
                          reBackData(pos);
                      }

                      @Override
                      public void onAdExposure(ExpView expView) {
                          Log.i("TEST", "onAdExposure " + expView + " , index = " + findIndex(expView));
                      }

                      @Override
                      public void onAdClicked(ExpView expView) {
                          Log.i("TEST", "onAdClicked " + expView + " , index = " + findIndex(expView));
                      }

                      @Override
                      public void onAdClosed(ExpView expView) {
                          int index = findIndex(expView);
                          Log.i("TEST", "onAdClosed " + expView + " , index = " + index);
                          if (index >= 0 && index < mData.size()) {
                              mData.remove(index);
                              notifyItemRemoved(index);
                          }

                      }
                  });
          easyNativeExpress.loadOnly(adId);
          adViewTemp.put(pos, easyNativeExpress);
          mData.get(pos).setReq(true);
      }

      private void reBackData(int pos) {
          RycItem rycItem = mData.get(pos);
          if (rycItem.isReq) {
              rycItem.isReq = false;
          }
      }

      private int findIndex(ExpView expView) {
          for (RycItem item: mData) {
              if (item.expView != null && item.expView.hashCode() == expView.hashCode()) {
                  return mData.indexOf(item);
              }
          }
          return -1;
      }

      protected void updateData(List<ExpView> viewList) {
          if (YFListUtils.isEmpty(viewList)) {
              return;
          }
          int index = 0;
          for (RycItem rycItem : mData) {
              if (isAdType(rycItem) && index < viewList.size()) {
                  rycItem.expView = viewList.get(index);
                  rycItem.isReq = false;
                  index++;
              }
          }
          notifyDataSetChanged();
      }

      protected void onAdClose(int pos) {
          if (pos < mData.size()) {
              mData.remove(pos);
              notifyItemChanged(pos);
          }
      }

主要API

YFAdNativeExpressAds

方法名 方法介绍
public YFAdNativeExpressAds(Context context, YFNativeExpressListener listener) 广告位构造方法: 其中Context推荐为当前activity,否者VIVO广告无法展示
public void setViewAcceptedSize(int expressViewWidth, int expressViewHeight) 期望模板广告view的size,单位dp,如果expressViewHeight是0,则高度自适应
public void loadOnly(String posId) 请求广告(与showAds一一对应)
public void showAds(Activity activity) 展示广告(与loadOnly一一对应)
public void setAdsNumbers(int realAdNumber) 设置期望的广告的数量,一次请求不能超过5条,返回0-5条数据。
public void destroy() 资源释放

YFNativeExpressListener

方法名 方法介绍
void onAdRenderFailed() 渲染失败
void onAdRenderSuccess(List view) 渲染成功
void onAdSuccess() 广告请求成功
void onAdFailed(YFAdError yfAdError) 广告请求失败
void onAdExposure(ExpView expView) 广告曝光
void void onAdClicked(ExpView expView) 广告点击
void void onAdClosed(ExpView expView) 广告关闭

ExpView

方法名 方法介绍
int getAdSourceType(); 获取广告源(具体参考YFAdsConst.CHANEL_XXX)
view getView() 获取视图(可为空,则使用render方法)
void render(ViewGroup viewGroup) 渲染视图(如果view为空,则调用次方法)

5.6 全屏视频

具体可参见demo中FullScreenVideoActivity

接入代码示例

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

    private void startFullVideo(String adId) {

        //推荐:核心事件监听回调
        //初始化
        easyFullScreenVideo = new YFAdFullScreenVideoAds(this, new YFFullScreenVideoListener() {

            @Override
            public void onVideoComplete() {
                logAndToast("视频播放结束");
            }

            @Override
            public void onVideoSkipped() {
                logAndToast("跳过视频");
            }

            @Override
            public void onVideoCached() {
                //广告缓存成功,可以在此记录状态,但要注意:不一定所有的广告会返回该回调
                logAndToast("广告缓存成功");
            }

            @Override
            public void onAdSuccess() {
                logAndToast("广告加载成功");
                showAds();
            }

            @Override
            public void onAdExposure() {
                logAndToast("广告展示");
            }


            @Override
            public void onAdClicked() {
                logAndToast("广告点击");
            }

            @Override
            public void onAdClosed() {
                logAndToast("广告关闭");
                FullScreenVideoActivity.this.finish();
            }

            @Override
            public void onAdFailed(YFAdError yfAdError) {
                logAndToast("广告加载失败 code=" + yfAdError.code + " msg=" + yfAdError.msg);
                FullScreenVideoActivity.this.finish();
            }
        });
        easyFullScreenVideo.loadOnly(adId);
    }
    
    private void showAds() {
        if (easyFullScreenVideo != null) {
            easyFullScreenVideo.showAds(FullScreenVideoActivity.this);
        }
    }
}

主要API

YFAdFullScreenVideoAds

方法名 方法介绍
public YFAdFullScreenVideoAds(Context context, YFFullScreenVideoListener baseAdListener) 广告位构造方法: 其中Context推荐为当前activity,否者VIVO广告无法展示
public void loadOnly(String posId) 请求广告(与showAds一一对应)
public void showAds(Activity activity) 展示广告(与loadOnly一一对应)
public void destroy() 广告不使用后,及时释放资源

YFFullScreenVideoListener

方法名 方法介绍
void onVideoCached(); 广告缓存成功
void onVideoComplete(); 视频播放完毕
void onVideoSkip(); 跳过视频

5.7 Draw流

具体可参见demo中DrawActivity

接入代码示例

  
    private void loadDraw(String adId, ViewGroup adContainer) {

      SoftReference<ViewGroup> parentView = new SoftReference<>(adContainer);
      easyAdDraw = new YFAdDrawAds(getContext(), new YFDrawListener() {

          @Override
          public void onAdSuccess() {
              logAndToast("广告加载成功");
              showAds(parentView);
          }

          @Override
          public void onAdExposure() {
              logAndToast("广告展示");

          }

          @Override
          public void onAdClicked() {
              logAndToast("广告点击");

          }

          @Override
          public void onAdClosed() {
              logAndToast("广告关闭");
          }

          @Override
          public void onAdFailed(YFAdError fcAdError) {
              logAndToast("广告加载失败 code=" + fcAdError.code + " msg=" + fcAdError.msg);
          }


      });
      logAndToast("广告请求中");
      //必须:设置策略信息
      easyAdDraw.loadOnly(adId);
    }
  
    private void showAds(SoftReference<ViewGroup> viewGroup) {
        if (easyAdDraw != null && mContext != null && viewGroup != null) {
            easyAdDraw.showAds(mContext.get(), viewGroup.get());
        }
    }
    
    public void onDestroy() {
        if (easyAdDraw != null) {
            easyAdDraw.destroy();
        }
    }

主要API

YFAdDrawAds

方法名 方法介绍
public YFAdDrawAds(Context context, YFDrawListener baseAdListener) 广告位构造方法
public void loadOnly(String posId) 请求广告(与showAds一一对应)
public void showAds(Activity activity, ViewGroup viewGroup) 展示广告(与loadOnly一一对应)
public void destroy() 广告不使用后,及时释放资源

YFDrawListenerBaseAdListener的使用示例同上

5.8 贴片

具体可参见demo中RollAdsActivity

接入代码示例

  
    private void startBanner() {
      rollAds = new YFRollAds(this, new YFRollAdsListener() {

          @Override
          public void onAdRenderSuccess(List<View> viewList) {
              logAndToast("广告渲染成功 " + viewList.size());
              Log.e("ad", viewList.size() + " load Roll ");
              addViewList = viewList;
              addView();
          }

          @Override
          public void onAdSuccess() {
              logAndToast("广告加载成功 ");
              showAds();
          }

          @Override
          public void onAdExposure() {
              logAndToast("广告展示");
          }

          @Override
          public void onAdRenderFailed() {
              logAndToast("广告渲染失败");
          }

          @Override
          public void onAdClicked() {
              logAndToast("广告点击");
          }

          @Override
          public void onAdClosed() {
              logAndToast("广告关闭");
          }

          @Override
          public void onAdFailed(YFAdError fcAdError) {
              logAndToast("广告加载失败 code=" + fcAdError.code + " msg=" + fcAdError.msg);
          }
      });
      logAndToast("广告请求中");

      // 这里示例使用的广告位宽高比为640:100。
      int width = ScreenUtil.px2dip(getApplicationContext(),
              (float) (ScreenUtil.getScreenWidth(getApplicationContext())));
      // 52是底部高
      int height = width * 9 / 20 - 52;
      Log.d("TEST", "width = " + width + " , screen width =" + height);
      //如果高度传入0代表自适应高度
      rollAds.setViewAcceptedSize(width, height);
      Log.d("TEST", "开始加载");
      rollAds.loadOnly(potId);
    }
    
    private void showAds() {
      if (rollAds != null) {
          rollAds.showAds(this, adView);
      }
    }
    
    private void addView() {
      if (addViewList != null && addViewList.size() > 0) {
          adView.removeAllViews();
          adView.addView(addViewList.get(0));
      }
    }
    
    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (rollAds != null) {
            rollAds.destroy();
            rollAds = null;
        }
        if (addViewList != null) {
            addViewList.clear();
        }
    }

主要API

YFAdDrawAds

方法名 方法介绍
public YFRollAds(Context context, YFRollAdsListener baseAdListener) 广告位构造方法
public void loadOnly(String posId) 请求广告(与showAds一一对应)
public void showAds(Activity activity, ViewGroup viewGroup) 展示广告(与loadOnly一一对应)
public void destroy() 广告不使用后,及时释放资源

YFRollAdsListener

方法名 方法介绍
void onAdRenderFailed() 渲染失败
void onAdRenderSuccess(List view) 渲染成功

5. 使用注意事项

5.1 常见问题

    Q: 广告的请求的API的context传入application context会有啥影响?
    A:目前API对context没有做强制限制,推荐传递当前activity,否者优量汇(Banner、插屏、全屏视频)、
     OPPO(Banner、插屏、全屏视频)、VIVO(Banner、插屏、全屏视频、开屏、信息流)广告无法展示。
    Q:对接和测试中出现问题了怎么办?
    A:首先查看常见问题中是否有相关问题;如果没有找到请设置下面属性打开亿帆日志开关抓取日志反馈给开发人员。
    代码中设置YFAdsConfigBuilder setDebug(true) {
    // 抓取日志(过滤应用级别日志即可)
    adb logcat -v time > d:\log.txt
    Q:接入开屏广告需要注意什么?
    A:1. 开屏广告不支持预加载;
    2. 请求开屏的超时时间最好为5秒,时间太短会影响广告展示量;
    Q:接入Banner位广告需要注意什么?
    A:1. 请求Banner位广告时,需要设置广告View的宽度(单位:dp),如果没有设置广告宽度,默认广告宽度为屏幕宽度;
    2. 广告View没有留白,如有留白需求,应用自己处理;
    Q:接入插屏广告需要注意什么?
    A:1. 展示插屏广告时需要确保依赖的Activity不能为停止和销毁状态,否则广告无法展示;
    2. 请求下一次广告前,需要把前面一个广告销销毁,否者出现异常情况;