跳到主要内容

Dirichlet 聚合SDK Android 接入文档

SDK 支持版本

  • Dirichlet SDK 和 优量汇 (Tencent Ad SDK) 最低支持 Android 5.0(API level 21)
  • 穿山甲 (Pangle) SDK 最低支持 Android 7.0(API level 24)
  • 编译环境为 Android Studio

SDK 配置

Maven 仓库配置

在 project 级别的 build.gradle 文件中添加穿山甲 (Pangle) Maven 的引用:

allprojects {
repositories {
maven {
url 'https://artifact.bytedance.com/repository/pangle'
}
}
}

依赖配置

DirichletAD_Mediation_4.2.4.3.aarDirichletAD_CSJ_Adapter_4.2.4.3.aarDirichletAD_GDT_Adapter_4.2.4.3.aar 拷贝到游戏目录下的 src/main/libs 目录中。

在项目目录下 build.gradle 文件中添加代码:

repositories {
flatDir{
dirs 'src/main/libs'
}
}
dependencies {
implementation (name: "DirichletAD_Mediation_4.2.4.3", ext: "aar") // Dirichlet 聚合SDK(包含Dirichlet广告SDK)
implementation (name: "DirichletAD_CSJ_Adapter_4.2.4.3", ext: "aar") // 穿山甲 adapter SDK
implementation (name: "DirichletAD_GDT_Adapter_4.2.4.3", ext: "aar") // 优量汇 adapter SDK

implementation('com.pangle.cn:ads-sdk-pro:7.4.2.2') { // 穿山甲广告 SDK
exclude group: 'com.android.support'
}

implementation 'com.qq.e.union:union:4.671.1541' // 优量汇广告SDK
implementation 'com.squareup.okhttp3:okhttp:3.12.1'
implementation "com.android.support:appcompat-v7:28.0.0"
implementation "com.android.support:support-annotations:28.0.0"
implementation "com.android.support:support-v4:28.0.0"
implementation "com.github.bumptech.glide:glide:4.9.0"
implementation 'com.android.support:recyclerview-v7:28.0.0'
}

权限申请 & 清单配置

配置 AndroidManifest.xml

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">

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

<!-- 为了获取更精准的推送数据,建议加上的权限 -->
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<uses-permission android:name="android.permission.QUERY_ALL_PACKAGES"/>
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES"/>
<uses-permission android:name="android.permission.BLUETOOTH"/>
<!-- targetVersion 31 及以上建议加上这个权限 -->
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT"/>

<!-- 为了获取更好的广告体验,建议加上以下权限来获取用户信息 -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>

<!-- 加上下列权限可以提高广告的转化率 -->
<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
</manifest>

Android 代码混淆

聚合 SDK 已内置 R8/ProGuard 混淆规则(consumerProguardFiles),默认情况下无需额外添加 -keep / -dontwarn 配置。 若工程使用自定义混淆策略导致类被误删/误混淆,请根据构建或运行日志按需补充规则。

资源混淆配置

如果您的工程中接入了资源混淆插件 AndResGuard,需要在 build.gradle 中新增白名单配置:

andResGuard {
// 白名单配置,请参考demo中的 `whiteList.txt`
whiteList = [
"R.integer.min_screen_width_bucket",
"R.style.DialogAnimationUp",
"R.style.DialogAnimationRight",
"R.style.DialogFullScreen",
"R.drawable.gdt_*"
...
]
}

获取广告权限

在获取 IMEI 和地理位置信息时,需要用户授予权限。建议先询问权限,再进行初始化工作。

DirichletAdManager.get().requestPermissionIfNecessary(activity);

初始化

DirichletAdConfig config = new DirichletAdConfig.Builder()
.withMediaId(your_media_id) // 必选参数。为 Dirichlet ADN 注册的媒体 ID
.withMediaName(your_media_name) // 必选参数。为 Dirichlet ADN 注册的媒体名称
.withMediaKey(your_media_key) // 必选参数。媒体密钥,可以在 Dirichlet ADN 后台查看
.enableDebug(false) // 可选参数,是否打开 debug 调试信息输出:true 打开、false 关闭。默认 false 关闭
.withCustomController(new DirichletAdCustomController() {

// 是否允许 SDK 主动使用地理位置信息
@Override
public boolean isCanUseLocation() {
return enableGetLocation;
}

// 当 isCanUseLocation=false 时,可传入地理位置信息,DirichletAd 使用您传入的地理位置信息
@Override
public DirichletAdLocation getDirichletAdLocation() {
return new DirichletAdLocation(longitude, latitude, accuracy);
}

// 是否允许 SDK 主动使用手机硬件参数,如 imei
@Override
public boolean isCanUsePhoneState() {
return enableGetPhoneState;
}

// 当 isCanUsePhoneState=false 时,可传入 imei 信息,DirichletAd 使用您传入的 imei 信息
@Override
public String getDevImei() {
return imei;
}

// 是否允许 SDK 主动使用 ACCESS_WIFI_STATE 权限
@Override
public boolean isCanUseWifiState() {
return enableGetWifiState;
}

// 是否允许 SDK 主动使用 WRITE_EXTERNAL_STORAGE 权限
@Override
public boolean isCanUseWriteExternal() {
return enableWriteExternal;
}

// 开发者可以传入 oaid
// 信通院 OAID 的相关采集——如何获取 OAID:
// 1. 移动安全联盟官网 http://www.msa-alliance.cn/
// 2. 信通院统一 SDK 下载 http://msa-alliance.cn/col.jsp?id=120
@Override
public String getDevOaid() {
return oaid;
}

// 是否允许 SDK 主动获取设备上应用安装列表的采集权限
@Override
public boolean alist() {
return enableGetAppList;
}

// 是否允许 SDK 主动获取 ANDROID_ID
@Override
public boolean isCanUseAndroidId() {
return enableGetAndroidId;
}
})
.build();

// context 为 application 的上下文
DirichletSdk.init(context, config, new DirichletSdk.InitListener() {
@Override
public void onInitSuccess() {
Log.d("DirichletSdk", "初始化成功");
}

@Override
public void onInitFail(int code, String msg) {
Log.d("DirichletSdk", "初始化失败: " + code + ", " + msg);
}
});

广告通用接口

创建广告加载器

// 注意,一个 Activity 中只需要创建一个 DirichletAdNative 对象
DirichletAdNative adNative = DirichletAdManager.get().createAdNative(context);

广告请求参数

DirichletAdRequest request = new DirichletAdRequest.Builder()
.withSpaceId(spaceId) // 必填,广告位 id
.withUserId(user_id) // 选填,用户 ID(用于激励广告奖励验证)
.withExtra1(extra_info) // 选填,激励广告验证奖励时透传参数
.withRewardName(reward_name) // 选填,奖励的名称(激励广告)
.withRewardAmount(100) // 选填,奖励的数量(激励广告)
.withExpressViewAcceptedSize(width, height) // 选填,广告视图尺寸(开屏、Banner)
.withExpressImageAcceptedSize(width, height) // 选填,视频视图尺寸(信息流)
.build();

广告对象通用方法

// 所有广告对象都包含以下方法
class Dirichlet**Ad {
// 销毁广告
public void destroy();

// 广告是否有效
boolean isValid();

// 获取广告额外参数,例如广告唯一 track_id、价格等
Map<String, Object> getDirichletExtraInfo();
}

广告类型

激励视频广告

激励视频是一种全屏播放的视频广告,用户可以在观看完整的视频后获取奖励。

自动加载展示(推荐)

4.2.0.1 新增

showRewardVideoAutoAd 接口将加载和展示合并为一次调用,内部自动管理广告缓存。若有可用缓存则立即展示,否则自动加载后展示。

DirichletAdRequest request = new DirichletAdRequest.Builder()
.withSpaceId(YOUR_SPACE_ID)
.withUserId("user_123")
.withRewardName("金币")
.withRewardAmount(100)
.build();

adNative.showRewardVideoAutoAd(request, new DirichletAdNative.RewardVideoAutoAdListener() {
@Override
public void onError(int code, String message) {
Log.e("DirichletAd", "激励视频加载/展示失败: " + code + ", " + message);
}

@Override
public void onAdShow() {
Log.d("DirichletAd", "激励视频展示");
}

@Override
public void onAdClose() {
Log.d("DirichletAd", "激励视频关闭");
}

@Override
public void onRewardVerify(boolean rewardVerify, int rewardAmount, String rewardName, int code, String msg) {
if (rewardVerify) {
Log.d("DirichletAd", "获得奖励: " + rewardAmount + " " + rewardName);
}
}

@Override
public void onAdClick() {
Log.d("DirichletAd", "激励视频点击");
}
});

手动加载展示

获取广告

// 构建广告请求
DirichletAdRequest request = new DirichletAdRequest.Builder()
.withSpaceId(YOUR_SPACE_ID) // 广告位 ID
.withUserId(user_123) // 用户 ID(用于奖励验证)
.withExtra1(extra_data) // 额外参数
.withRewardName("金币") // 奖励名称
.withRewardAmount(100) // 奖励数量
.build();

// 加载激励视频广告
adNative.loadRewardVideoAd(request, new DirichletAdNative.RewardVideoAdListener() {
@Override
public void onRewardVideoAdLoad(DirichletRewardVideoAd rewardVideoAd) {
// 广告加载成功
Log.d("DirichletAd", "激励视频广告加载成功");

// 可以展示广告
showRewardVideoAd(rewardVideoAd);
}

@Override
public void onError(int code, String message) {
// 广告加载失败
Log.e("DirichletAd", "激励视频广告加载失败: " + code + ", " + message);
}
});

播放

private void showRewardVideoAd(DirichletRewardVideoAd rewardVideoAd) {
if (rewardVideoAd != null && rewardVideoAd.isValid()) {
// 设置交互回调 listener,曝光、点击、关闭、奖励等回调事件
rewardVideoAd.setRewardAdInteractionListener(new DirichletRewardVideoAd.RewardAdInteractionListener() {
@Override
public void onAdShow() {
Log.d("DirichletAd", "激励视频广告曝光展示");
}

@Override
public void onAdClick() {
Log.d("DirichletAd", "激励视频广告点击");
}

@Override
public void onAdClose() {
Log.d("DirichletAd", "激励视频广告关闭");
}

@Override
public void onRewardVerify(boolean rewardVerify, int rewardAmount, String rewardName, int code, String msg) {
if (rewardVerify) {
Log.d("DirichletAd", "获得奖励: " + rewardAmount + ", " + rewardName);
// 发放奖励给用户
} else {
Log.d("DirichletAd", "奖励验证失败: " + code + ", " + msg);
}
}
});

// 展示激励广告
rewardVideoAd.showRewardVideoAd(activity);
}
}

Banner 广告为固定尺寸的横幅广告,可以放置在页面的顶部或底部。

自动加载展示(推荐)

4.2.2.0 新增

showBannerAutoAd 接口将加载和展示合并为一次调用,内部自动管理广告缓存与轮播。开发者只需提供广告容器,SDK 自动完成加载、展示和定时刷新。

ViewGroup bannerContainer = findViewById(R.id.banner_container);

DirichletAdRequest request = new DirichletAdRequest.Builder()
.withSpaceId(YOUR_BANNER_SPACE_ID)
.withSlideInternal(30) // 轮播间隔(秒),取值范围 30~120,默认 30
.build();

adNative.showBannerAutoAd(request, bannerContainer, new DirichletAdNative.BannerAutoAdListener() {
@Override
public void onError(int code, String message) {
Log.e("DirichletAd", "Banner 自动加载失败: " + code + ", " + message);
}

@Override
public void onAdShow() {
Log.d("DirichletAd", "Banner 展示");
}

@Override
public void onAdClick() {
Log.d("DirichletAd", "Banner 点击");
}

@Override
public void onAdClose() {
Log.d("DirichletAd", "Banner 关闭");
}
});

手动加载展示

获取广告

DirichletAdRequest request = new DirichletAdRequest.Builder()
.withSpaceId(YOUR_BANNER_SPACE_ID)
.withExpressViewAcceptedSize(width, height)
.build();

adNative.loadBannerAd(request, new DirichletAdNative.BannerAdListener() {
@Override
public void onBannerAdLoad(DirichletBannerAd bannerAd) {
// Banner 广告加载成功
Log.d("DirichletAd", "Banner 广告加载成功");
showBannerAd(bannerAd);
}

@Override
public void onError(int code, String message) {
Log.e("DirichletAd", "Banner 广告加载失败: " + code + ", " + message);
}
});

播放

private void showBannerAd(DirichletBannerAd bannerAd) {
if (bannerAd != null) {
// 获取 Banner 视图
View bannerView = bannerAd.getBannerView();
if (bannerView != null) {
// 添加到容器中
ViewGroup container = findViewById(R.id.banner_container);
container.removeAllViews();
container.addView(bannerView);

// 设置交互监听
bannerAd.setBannerInteractionListener(new DirichletBannerAd.BannerInteractionListener() {
@Override
public void onAdShow() {
Log.d("DirichletAd", "Banner 广告展示");
}

@Override
public void onAdClick() {
Log.d("DirichletAd", "Banner 广告点击");
}

@Override
public void onAdClose() {
Log.d("DirichletAd", "Banner 广告关闭");
}
});
}
}
}

开屏广告

开屏广告为用户在进入 App 时展示的全屏广告。

信息

开屏广告的展示和加载必须在同一个 Activity 中。

竖屏开屏广告 view 要求 width = 屏幕宽,height 需要 >= 75% 屏幕高,否则会影响计费。

横屏开屏广告 view 要求 width = 屏幕宽,height 需要 = 屏幕高,否则会影响计费。

自动加载展示(推荐)

4.2.2.0 新增

showSplashAutoAd 接口将加载和展示合并为一次调用,内部自动管理广告缓存。若有可用缓存则立即展示,否则自动加载后展示。

ViewGroup splashContainer = findViewById(R.id.splash_container);

DirichletAdRequest request = new DirichletAdRequest.Builder()
.withSpaceId(YOUR_SPLASH_SPACE_ID)
.withExpressViewAcceptedSize(screenWidth, screenHeight)
.build();

adNative.showSplashAutoAd(request, splashContainer, new DirichletAdNative.SplashAutoAdListener() {
@Override
public void onError(int code, String message) {
Log.e("DirichletAd", "开屏自动加载失败: " + code + ", " + message);
goToMainActivity();
}

@Override
public void onAdShow() {
Log.d("DirichletAd", "开屏展示");
}

@Override
public void onAdClick() {
Log.d("DirichletAd", "开屏点击");
}

@Override
public void onAdClose() {
Log.d("DirichletAd", "开屏关闭");
goToMainActivity();
}
});

手动加载展示

获取广告

DirichletAdRequest request = new DirichletAdRequest.Builder()
.withSpaceId(YOUR_SPLASH_SPACE_ID)
.withExpressViewAcceptedSize(screenWidth, screenHeight) // 设置开屏尺寸
.build();

adNative.loadSplashAd(request, new DirichletAdNative.SplashAdListener() {
@Override
public void onSplashAdLoad(DirichletSplashAd splashAd) {
Log.d("DirichletAd", "开屏广告加载成功");
showSplashAd(splashAd);
}

@Override
public void onError(int code, String message) {
Log.e("DirichletAd", "开屏广告加载失败: " + code + ", " + message);
// 跳转到主页面
goToMainActivity();
}
});

播放

private void showSplashAd(DirichletSplashAd splashAd) {
if (splashAd != null) {
splashAd.setSplashInteractionListener(new DirichletSplashAd.AdInteractionListener() {
@Override
public void onAdShow() {
Log.d("DirichletAd", "开屏广告展示");
}

@Override
public void onAdClick() {
Log.d("DirichletAd", "开屏广告点击");
}

@Override
public void onAdClose() {
Log.d("DirichletAd", "开屏广告关闭");
goToMainActivity();
}
});

ViewGroup splashContainer = findViewById(R.id.splash_container);
splashAd.show(splashContainer);
}
}
点击展开 Kotlin 完整示例代码
class SplashActivity: AppCompatActivity() {

private lateinit var splashModel: SplashViewModel
private lateinit var binding: ActivitySplashBinding
var isPortrait: Boolean = true

override fun onCreate(savedInstanceState: Bundle?) {
supportRequestWindowFeature(Window.FEATURE_NO_TITLE)
super.onCreate(savedInstanceState)
binding = ActivitySplashBinding.inflate(layoutInflater)
setContentView(binding.root)

splashModel = ViewModelProvider(this, ViewModelProvider.NewInstanceFactory())[SplashViewModel::class.java]
binding.splashModel = splashModel
binding.lifecycleOwner = this

binding.portraitSplashBtn.setOnClickListener {
loadAd(splashModel.portraitSplashId.value, true)
}

binding.landscapeSplashBtn.setOnClickListener {
loadAd(splashModel.landscapeSplashId.value, false)
}

binding.splashShowBtn.setOnClickListener {
splashModel.log.value = ""
ad?.let {
binding.splashContainer.visibility = View.VISIBLE
binding.splashLoadContainer.visibility = View.GONE
binding.splashContainer.layoutParams = FrameLayout.LayoutParams(width, height)
it.show(binding.splashContainer)
}
}

tapAdNative = DirichletAdManager.get().createAdNative(this)
}

var ad: DirichletSplashAd? = null
var width = LayoutParams.MATCH_PARENT
var height = LayoutParams.MATCH_PARENT

private lateinit var tapAdNative: DirichletAdNative

private fun loadAd(spaceId: String?, isPortrait: Boolean) {
width = UIUtils.getScreenWidthInPx(this)
height = UIUtils.getScreenHeightInPx(this)
if (isPortrait) {
height = width / 9 * 16
}
splashModel.log.value = ""
tapAdNative.loadSplashAd(
DirichletAdRequest.Builder()
.withSpaceId(spaceId?.toLong() ?: 0)
.withExpressViewAcceptedSize(width, height)
.build(), object: DirichletAdNative.SplashAdListener {
override fun onError(code: Int, message: String?) {
splashModel.log.postValue("加载失败,$code, $message")
}

override fun onSplashAdLoad(splashAd: DirichletSplashAd?) {
splashModel.log.postValue("加载成功")
this@SplashActivity.isPortrait = isPortrait
ad = splashAd
ad?.setSplashInteractionListener(object: DirichletSplashAd.AdInteractionListener {
override fun onAdClose() {
binding.splashContainer.removeAllViews()
binding.splashContainer.visibility = View.GONE
binding.splashLoadContainer.visibility = View.VISIBLE
}

override fun onAdClick() {
Toast.makeText(this@SplashActivity, "开屏广告点击", Toast.LENGTH_SHORT).show()
}

override fun onAdShow() {
}
})
}
})
}

/**
* 清理当前广告和相关引用
*/
private fun cleanupCurrentAd() {
ad?.destroy()
}

override fun onDestroy() {
super.onDestroy()
// 最终清理,确保所有引用都被释放
cleanupCurrentAd()
}
}

插屏广告

插屏广告支持「全屏视频广告」、「全屏图文广告」和「半屏图文广告」等形式。

提示

插屏广告分横竖屏形式,强烈建议在后台配置后正确使用横屏或竖屏广告,若用错配置的 orientation,可能会出现 UI 兼容异常问题。

自动加载展示(推荐)

4.2.2.0 新增

showInterstitialAutoAd 接口将加载和展示合并为一次调用,内部自动管理广告缓存。若有可用缓存则立即展示,否则自动加载后展示。

DirichletAdRequest request = new DirichletAdRequest.Builder()
.withSpaceId(YOUR_INTERSTITIAL_SPACE_ID)
.build();

adNative.showInterstitialAutoAd(request, activity, new DirichletAdNative.InterstitialAutoAdListener() {
@Override
public void onError(int code, String message) {
Log.e("DirichletAd", "插屏自动加载失败: " + code + ", " + message);
}

@Override
public void onAdShow() {
Log.d("DirichletAd", "插屏展示");
}

@Override
public void onAdClick() {
Log.d("DirichletAd", "插屏点击");
}

@Override
public void onAdClose() {
Log.d("DirichletAd", "插屏关闭");
}
});

手动加载展示

获取广告

DirichletAdRequest request = new DirichletAdRequest.Builder()
.withSpaceId(YOUR_INTERSTITIAL_SPACE_ID)
.build();

adNative.loadInterstitialAd(request, new DirichletAdNative.InterstitialAdListener() {
@Override
public void onInterstitialAdLoad(DirichletInterstitialAd interstitialAd) {
Log.d("DirichletAd", "插屏广告加载成功");
showInterstitialAd(interstitialAd);
}

@Override
public void onError(int code, String message) {
Log.e("DirichletAd", "插屏广告加载失败: " + code + ", " + message);
}
});

播放

private void showInterstitialAd(DirichletInterstitialAd interstitialAd) {
if (interstitialAd != null && interstitialAd.isValid()) {
// 设置交互 listener
interstitialAd.setInteractionListener(new DirichletInterstitialAd.InterstitialAdInteractionListener() {
@Override
public void onAdShow() {
Log.d("DirichletAd", "插屏广告展示");
}

@Override
public void onAdClick() {
Log.d("DirichletAd", "插屏广告点击");
}

@Override
public void onAdClose() {
Log.d("DirichletAd", "插屏广告关闭");
}
});
interstitialAd.show(activity);
}
}

自渲染信息流广告

自渲染信息流广告为可自定义布局的信息流广告,包含大图和视频两种基本样式类型。

信息

支持的广告尺寸:

  • 大图(宽高比:1.78 的图片)
  • 视频(宽高比:1.78 的视频)

获取广告

DirichletAdRequest request = new DirichletAdRequest.Builder()
.withSpaceId(YOUR_FEED_SPACE_ID)
.withExpressViewAcceptedSize(widthPx, heightPx) // 输入期待的父 view 的宽高
.withExpressImageAcceptedSize(widthPx, heightPx) // 输入期待的视频 view 的宽高
.build();

adNative.loadNativeFeedAd(request, new DirichletAdNative.NativeFeedAdListener() {
@Override
public void onNativeFeedAdLoad(List<DirichletNativeFeedAd> ads) {
Log.d("DirichletAd", "信息流广告加载成功,数量: " + ads.size());
for (DirichletNativeFeedAd ad : ads) {
bindNativeView(ad);
}
}

@Override
public void onError(int code, String message) {
Log.e("DirichletAd", "信息流广告加载失败: " + code + ", " + message);
}
});

广告行为监听 & 展示

信息

AdInteractionListener 涉及到广告计费,必须正确调用,container 必须使用 DirichletAdNativeContainer

private void bindNativeView(final DirichletNativeFeedAd ad) {
// 加载广告图标
Glide.with(binding.imgLogo).load(ad.getIconUrl()).into(binding.imgLogo);

// 设置广告标题和描述
binding.textTitle.setText(ad.getTitle());
binding.textDesc.setText(ad.getDescription());

// 添加视频 view
binding.videoContainer.removeAllViews();
View videoView = ad.getAdView();
ViewParent parent = videoView != null ? videoView.getParent() : null;
if (parent instanceof ViewGroup) {
((ViewGroup) parent).removeView(videoView);
}
binding.videoContainer.addView(ad.getAdView());

// 加载广告图片
Glide.with(binding.imgPoster)
.load(ad.getImageInfoList().get(0).getImageUrl())
.into(binding.imgPoster);

// 注册可点击的 View,click/show 会在内部完成
// container: 渲染广告最外层的 DirichletAdNativeContainer
// clickViews: 可点击的视图
// creativeViews: 可点击的创意视图(广告下载的按钮)
ad.registerViewForInteraction(
activity,
binding.nativeAdContainer,
Arrays.asList(binding.customContainer),
Arrays.asList(binding.btnDownload),
new DirichletNativeFeedAd.AdInteractionListener() {
@Override
public void onAdClick(View view, DirichletNativeFeedAd ad) {
Log.d("DirichletAd", "自渲染信息流点击");
}

@Override
public void onAdShow(DirichletNativeFeedAd ad) {
Log.d("DirichletAd", "自渲染信息流展示");
}
}
);

// 设置下载监听器
ad.setDownloadListener(new DirichletAppDownloadListener() {
@Override
public void onDownloadStart() {
Log.d("DirichletAd", "开始下载");
}

@Override
public void onDownloadComplete() {
Log.d("DirichletAd", "下载完成");
}

@Override
public void onUpdateDownloadProgress(int percent) {
Log.d("DirichletAd", "下载进度: " + percent);
}

@Override
public void onDownloadError() {
Log.d("DirichletAd", "下载错误");
}

@Override
public void onInstalled() {
Log.d("DirichletAd", "安装完成");
}
});

// 设置视频广告监听器
ad.setVideoAdListener(new DirichletNativeFeedAd.VideoAdListener() {
@Override
public void onVideoPrepared(DirichletNativeFeedAd ad) {
Log.d("DirichletAd", "视频准备完成");
}

@Override
public void onVideoStart(DirichletNativeFeedAd ad) {
Log.d("DirichletAd", "视频开始播放");
}

@Override
public void onVideoPause(DirichletNativeFeedAd ad) {
Log.d("DirichletAd", "视频停止播放");
}

@Override
public void onVideoError(DirichletNativeFeedAd ad, int errorCode, String message) {
Log.d("DirichletAd", "视频播放错误: " + errorCode + ", " + message);
}
});
}

自渲染信息流广告接口说明

public interface DirichletNativeFeedAd {
/**
* 获取广告应用图标 url
*/
String getIconUrl();

/**
* 设置 logo 在广告容器中的位置
*/
void setLogoLayoutParams(FrameLayout.LayoutParams params);

/**
* 获取图片 ImageInfo list(宽、高、以及 url 地址)
*/
List<ImageInfo> getImageInfoList();

/**
* 广告标题
*/
String getTitle();

/**
* 广告描述
*/
String getDescription();

/**
* 获取下载类广告的下载应用大小
*/
String getApkSize();

/**
* @return 0: unknown
* 1: 下载类广告
* 2, 3: 跳转类广告
* 4: 小程序跳转类广告
*/
int getInteractionType();

/**
* @return 1: 大图
* 2: 视频
*/
int getImageMode();

/**
* 获取广告合规信息(六要素)
*/
ComplianceInfo getComplianceInfo();

/**
* 注册可点击的 view,click/show 会在内部完成
*
* @param activity
* @param container 广告容器(DirichletAdNativeContainer)
* @param clickViews 点击区域
* @param creativeViews 创意点击区域(下载按钮等)
* @param listener 广告交互监听回调
*/
void registerViewForInteraction(Activity activity, DirichletAdNativeContainer container,
List<View> clickViews, List<View> creativeViews, AdInteractionListener listener);

/**
* 获取广告视频的视频 view
* 注意:必须在 registerViewForInteraction 前调用
*/
View getAdView();

/**
* 设置下载监听器
*/
void setDownloadListener(DirichletAppDownloadListener listener);

/**
* 设置视频广告监听器
*/
void setVideoAdListener(VideoAdListener listener);
}

资源管理与最佳实践

广告加载时机

  • 激励视频:在用户可能需要奖励的场景前预加载
  • 插屏广告:在关卡结束、页面切换等自然停顿点展示
  • Banner 广告:在页面稳定后加载,避免影响用户体验
  • 开屏广告:在应用启动时立即加载

内存管理

onDestroy 方法中释放广告资源:

@Override
protected void onDestroy() {
super.onDestroy();

// 释放广告对象
if (rewardVideoAd != null) {
rewardVideoAd.destroy();
rewardVideoAd = null;
}
}

常见问题

错误码说明

错误码说明
200001广告位无填充,参考详细msg返回
200002广告数据无填充,参考详细msg返回
200010广告渲染失败,参考详细msg返回
200011视频播放失败,参考详细msg返回
200012广告下载失败,参考详细msg返回

广告不展示

  • 检查广告位 ID 是否正确
  • 确认网络连接正常
  • 验证媒体配置信息(Media ID、Media Name、Media Key)
  • 查看日志中的错误信息
  • 确认是否正确初始化 SDK

第三方广告平台配置问题

  • 检查 AndroidManifest.xml 中是否包含穿山甲和优量汇的必要配置
  • 确认 @xml/gdt_file_path@xml/csj_file_paths 文件存在
  • 检查资源混淆配置是否正确

广告加载失败

  • 查看错误码和错误信息
  • 确认广告位是否配置正确
  • 检查是否有可用的广告填充
  • 验证用户权限是否已授予(IMEI、位置信息等)