自渲染广告

自渲染广告

此章节将演示如何请求在原生环境下请求与展示自渲染广告

自渲染是对原有类型的优化和升级,使用自渲染的 API,您可以为您的应用打造定制式体验

请求自渲染广告

提示

2.4.18 版本起对自渲染广告接入方式进行了调整,旧的方法已移除,需要重新接入

视频广告的MediaView内部使用了TextureView,所以需要在开启硬件加速的窗口中才能使用。当 Android API>=14时,硬件加速默认是开启的

调用ZJNativeAd#loadAd方法请求广告

public class ZJNativeAd {

    /**
     * 加载广告
     * 
     * @param posId         广告位ID
     * @param num           期望请求的数量
     * @param loadListener  加载回调
     */
    public static void loadAd(@NonNull String posId, int num, @NonNull ZJNativeAdLoadListener loadListener);

    /**
     * 加载广告
     *
     * @param activity     当前Activity
     * @param posId        广告位ID
     * @param num          期望的广告数量(不大于5)
     * @param widthPX      展示区域的宽(单位PX)
     * @param heightPX     展示区域的高(单位PX)
     * @param loadListener 加载回调
     */
    public static void loadAd(Activity activity, @NonNull String posId, int num, int widthPX, int heightPX, @NonNull ZJNativeAdLoadListener loadListener);

}

加载回调说明

方法说明
onError(int code, String msg)广告加载出错
code: 错误码
msg: 错误信息
onAdLoaded(List<ZJNativeAd> adList)广告加载成功
adList: 广告列表

展示自渲染广告

在加载成功回调中获取到ZJNativeAd对象后,需要通过以下方法获取信息、配置回调、绑定视图以展示广告

获取信息

调用以下方法获取自渲染广告的详细信息并展示在自定义容器中

方法说明
setInteractionListener(ZJNativeAdInteractionListener interactionListener)配置交互回调
setDownloadListener(ZJNativeAdDownloadListener downloadListener)配置下载回调
getDislikeEvents()获取不喜欢的事件列表
dislike(ZJNativeAd.DislikeEvent event)回传不喜欢事件
boolean addShakeView(@NonNull ViewGroup shakeViewContainer, int widgetSizeDP, int textSizeSP, @Nullable ShakeViewListener shakeViewListener)添加摇一摇组件
shakeViewContainer:容器
widgetSizeDP:摇一摇控件的宽高,单位DP
textSizeSP 摇一摇文案字体大小,单位SP
shakeViewListener 组件回调
return 是否支持手动添加摇一摇组件
addSlideView(@NonNull ViewGroup shakeViewContainer, int widgetSizeDP, int textSizeSP, @Nullable ShakeViewListener shakeViewListener)添加摇一摇组件
slideViewContainer:容器
widgetSizeDP:摇一摇控件的宽高,单位DP
textSizeSP 摇一摇文案字体大小,单位SP
repeat:动画重复次数
shakeViewListener 组件回调
registerViewForInteraction(Activity activity, ZJNativeAdContainer container, List<View> clickableViews, List<View> creativeViews)绑定广告对象和视图
activity: 当前的 activity
container: 当前的广告容器,所有的自渲染组件需要在此容器内,且不可以设置点击事件,否则无法正常曝光和计费
clickableViews: 可点击的 view 列表,默认展示下载整改弹框
creativeViews: 带有下载引导文案的View,默认不会触发下载整改弹框
registerViewForInteraction(Activity activity, ZJNativeAdContainer container, List<View> clickableViews, List<View> creativeViews, FrameLayout.LayoutParams adLogoParams)绑定广告对象和视图
activity: 当前的 activity
container: 当前的广告容器,所有的自渲染组件需要在此容器内,且不可以设置点击事件,否则无法正常曝光和计费
clickableViews: 可点击的 view 列表,默认展示下载整改弹框
creativeViews: 带有下载引导文案的View,默认不会触发下载整改弹框
adLogoParms: 广告标志布局参数,(0,0)时不显示角标,部分广告有效
bindVideoView(ViewGroup videoContainer, ZJNativeAdVideoListener videoListener)绑定广告对象与视频播放器
videoContainer: 播放器的容器
videoListener: 视频播放回调
bindVideoView(ViewGroup videoContainer, ZJNativeAdVideoListener videoListener, boolean videoSoundEnable)绑定广告对象与视频播放器
videoContainer: 播放器的容器
videoListener: 视频播放回调
videoSoundEnable: 是否开启视频声音
onDestroy()在 activity#destroy 时调用,以便释放内存
getMaterialType()获取素材类型, 返回的 type 为视频时,需要通过 bindVideoView 方法绑定播放器,播放视频
getActionButtonText()按钮提示文字,可能为空字符串
getTitle()标题,下载类为App应用名,非下载类为产品名称,可能为空字符串
getDesc()描述,可能为空字符串
getIconUrl()下载类型的Icon,⾮下载可能返回为空字符串
getImageUrl()主图Url,可能为空字符串
getImageList()类型为ZJNativeAd.MaterialType.GROUP_IMG时需要调用,返回一组图片 URL
isAppAd()是否为下载类广告
getDownloadCount()获取应用下载次数文案,默认为'0次下载'
getAppScore()应用评分,0-5.0,默认为0
getVideoDuration()视频时长,默认为0,仅类型为ZJNativeAd.MaterialType.VIDEO时有效
getImageWidth()大图素材的宽度,默认为0,仅类型为ZJNativeAd.MaterialType.SINGLE_IMG时有效
getImageHeight()大图素材的高度,默认为0,仅类型为ZJNativeAd.MaterialType.SINGLE_IMG时有效
getComplianceInfo()获取下载类广告的合规信息,包含应用名称、开发者、版本、apk包大小、隐私政策、权限信息。返回值类型为com.zj.zjsdk.api.v2.nativead.ZJNativeAd.ComplianceInfo。非下载类广告会返回空对象
getSourceInfo()获取广告来源信息。返回值类型为com.zj.zjsdk.api.v2.nativead.ZJNativeAd.SourceInfo,内容可能为空,需要开发者判断并处理

MaterialType 说明

ZJNativeAd#getMaterialType()方法返回的素材类型

类型说明
ZJNativeAd.MaterialType.UNKNOWN0未知类型
ZJNativeAd.MaterialType.VIDEO1视频类型,需要调用bindVideoView方法绑定播放器容器与配置视频回调
ZJNativeAd.MaterialType.SINGLE_IMG2单图类型,包含主图与图标
ZJNativeAd.MaterialType.GROUP_IMAGE3三小图类型,需要调用getImageList()方法获取组图信息

添加摇一摇与滑一滑互动

注意

需要注意容器和传入的尺寸单位为DP,且不可以小于80DP

添加摇一摇组件

开发者可以根据需求,调用addShakeView方法传入容器等参数为广告添加摇一摇组件

若返回值为true,则表示广告支持添加摇一摇组件

若返回值为false,则表示广告不支持添加摇一摇组件,可以考虑添加滑一滑组件

添加滑一滑组件

开发者可以根据需求,调用addSlideView方法传入容器等参数为广告添加滑一滑组件

添加滑一滑组件方法与添加摇一摇组件不同,没有返回值,无法直接获取是否添加成功的状态

组件回调

当组件消失时,会回调ZJNativeAd.ShakeViewListener#onDismiss()方法

绑定视图

视频素材额外绑定

如果素材为视频类型(getMaterialType()方法返回ZJNativeAd.MaterialType.VIDEO),需要调用bindVideoView方法绑定播放器容器与配置视频回调

所有素材都需要绑定视图

在自定义容器内渲染广告信息后,需要调用registerViewForInteraction方法传入容器绑定视图,否则无法正常曝光和计费

注意

确保所有的自渲染组件在此容器内。同时此容器不可以设置点击事件,否则无法正常曝光和计费

交互回调说明

开发者需要调用setInteractionListener(ZJNativeAdInteractionListener)方法配置交互回调来监听广告的状态

方法说明
onNativeAdShow()⼴告展示回调 每个⼴告仅回调⼀次
onNativeAdClick()⼴告点击的回调,点击后的动作由 sdk 控制
onNativeAdRenderFailed(int code, String msg)渲染失败
code: 错误码
msg: 错误信息
onDownloadTipsDialogShow()广告展示下载合规弹窗
onDownloadTipsDialogDismiss()广告关闭下载合规弹窗

下载回调说明

开发者可以调用setDownloadListener(ZJNativeAdDownloadListener)方法配置下载回调,并在界面上显示下载进度等信息

方法说明
onIdle()下载挂起
onDownloadStarted()下载开始
onProgressUpdate(int progress)下载进度更新
progress: 当前进度(0-100)
onDownloadPaused(int progress)下载暂停
progress: 当前进度(0-100)
onDownloadFinished()下载完成
onDownloadFailed()下载失败
onInstalled()安装成功

视频回调说明

视频类素材在调用bindVideoView方法时,需要传入ZJNativeAdVideoListener对象,并在回调中处理视频播放事件

方法说明
onVideoReady()视频加载完成
onVideoStart()视频开始播放
onVideoPause()视频暂停播放
onVideoResume()视频恢复播放
onVideoComplete()视频播放完成
onVideoError(int code, String msg, String extra)视频播放出错
code: 错误码
msg: 错误信息
extra: 额外信息,可能为空

不喜欢事件回传

在用户点击关闭按钮时,可以展示调用getDislikeEvents()方法获取dislike列表,并在用户选择后调用dislike(ZJNativeAd.DislikeEvent event)方法回传给广告

Dislike 包括以下预定义事件,若用户手动输入了意见,可以调用构造方法Dislike(String name)回传DislikeEvent对象

typename
0不感兴趣
1内容质量差
2推荐重复
3低俗色情
4违法违规
5虚假欺诈
6诱导点击
7疑似抄袭
8其他

下载六要素说明

下载类广告可以调用getComplianceInfo()方法获取合规信息,包含应用名称、开发者、版本、apk包大小、隐私政策、权限信息

提示

非下载类广告会返回空对象

部分信息会返回空字符串,需要做判断和处理

应用权限URL返回为空字符串时,需要调用getAppPermissions(PermissionsCallback callback)方法异步获取权限信息,并根据结果渲染

方法说明
getAppName()应用的名称
getAppVersion()应用版本信息
getAppPackageName()应用包名
getAppDeveloperName()应用开发者名称
getAppPrivacyUrl()应用隐私政策url,需要使用WebView显示该url
getAppFunctionDescUrl()应用功能介绍url,需要使用WebView展示该url
getAppPermissionsUrl()获取应用权限URL,需要使用WebView展示该url
返回空字符串时,需要调用getAppPermissions(PermissionsCallback callback)方法异步获取权限信息
getPackageSizeBytes()应用apk包的大小,单位byte
getIcpNumber()应用备案号
getAppPermissions(PermissionsCallback callback)异步获取应用权限

异步获取应用权限回调

ZJNativeAd.ComplianceInfo.PermissionsCallback包含以下回调方法

方法说明
callback(List<Permission> permissions)返回权限信息,可能为空列表

应用权限对象说明

ZJNativeAd.ComplianceInfo.Permission类包含以下获取信息的方法

方法说明
getName()权限原始名称,如android.permission.ACCESS_NETWORK_STATE
可能为空字符串
getDesc()权限描述,如允许该应用查看网络连接的相关信息,例如存在和连接的网络
可能为空字符串
getTitle()权限标题,如查看网络连接
可能为空字符串
getLevel()权限级别

提示

返回中的namedesctitle三个值可能部分为空字符串,不会全部为空字符串,需要在渲染时做判断和处理

来源信息说明

部分广告会返回来源信息,需要调用getSourceInfo()方法获取。方法的返回值不为空,但返回对象的各个字段都有可能为空,需要开发者自行处理

ZJNativeAd.SourceInfo 说明

方法说明
String getSourceText()获取广告来源,如"广告"、"ADX"、"腾讯",可能为空字符串
String getSourceImageUrl()获取广告来源图片的地址,可能为空字符串
String getLogoUrl()获取广告来源的LOGO地址,可能为空字符串
Bitmap getLogoBitmap()广告来源的Bitmap,可能为空

渲染说明

当开发者需要在自渲染广告的模板中展示详细的来源信息时,可以通过以上方法来获取广告的来源信息,但需要处理返回为空时的情况

可以参考演示工程的NativeAdSourceView.class

示例代码
public void initView(ZJNativeAd.SourceInfo sourceInfo) {
    if (!TextUtils.isEmpty(sourceInfo.getLogoUrl())) {
        addImage(sourceInfo.getLogoUrl());
    } else if (sourceInfo.getLogoBitmap() != null) {
        addImage(sourceInfo.getLogoBitmap());
    } else {
        addImage(R.drawable.ad_source_logo_def);
    }
    if (!TextUtils.isEmpty(sourceInfo.getSourceText())) {
        addText(sourceInfo.getSourceText());
    } else if (!TextUtils.isEmpty(sourceInfo.getSourceImageUrl())) {
        addImage(sourceInfo.getSourceImageUrl());
    } else {
        addText("广告");
    }
}
fun init(sourceInfo: SourceInfo) {
    when {
        sourceInfo.logoUrl.isNotEmpty() -> addImage(sourceInfo.logoUrl)
        sourceInfo.logoBitmap != null -> addImage(sourceInfo.logoBitmap!!)
        else -> addImage(R.mipmap.ad_source_logo_def)
    }
    when {
        sourceInfo.sourceText.isNotEmpty() -> addText(sourceInfo.sourceText)
        sourceInfo.sourceImageUrl.isNotEmpty() -> addImage(sourceInfo.sourceImageUrl)
        else -> addText("广告")
    }
}

自渲染广告接入示例

ZJNativeAd.loadAd(广告位ID, 1, new ZJNativeAdLoadListener() {
        
    @Override
    public void onError(int code, @NonNull String msg) {
        Log.e("NativeAd", "onError..." + code + " | " + msg);
    }

    @Override
    public void onAdLoaded(@NonNull List<ZJNativeAd> adList) {
        Log.e("NativeAd", "onAdLoaded");
        if (!adList.isEmpty()) {
            ad = adList.get(0);
            getAdInfo(ad);
            // 渲染参照Demo工程的NativeAdRender.java
            render(ad);
        } else {
            Log.e("NativeAd", "onAdLoaded...ret is null");
            Toast.makeText(NativeDrawActivity.this, "onZjAdLoaded...ret is null", Toast.LENGTH_SHORT).show();
        }
    }

});

private void getAdInfo(ZJNativeAd ad) {
    // 素材类型见ZJNativeAd.MaterialType
    Log.e("NativeAd", "素材类型: " + ad.getMaterialType());
    // 按钮提示文字,可能为空字符串
    Log.e("NativeAd", "按钮提示文字: " + ad.getActionButtonText());
    // 标题,可能为空字符串;下载类为App应用名,非下载类为产品名称
    Log.e("NativeAd", "标题: " + ad.getTitle());
    // 描述,可能为空字符串
    Log.e("NativeAd", "描述: " + ad.getDesc());
    // 下载类型的AppIcon,⾮下载返回为空字符串
    Log.e("NativeAd", "下载类型的AppIcon: " + ad.getIconUrl());
    // 主图Url,可能为空字符串
    Log.e("NativeAd", "主图Url: " + ad.getImageUrl());
    // {@link #getMaterialType()} 返回 {@link MaterialType#GROUP_IMG} 时需要调用;返回一组图片 URL
    Log.e("NativeAd", "getImageList: " + ad.getImageList().size());
    // 是否为下载类广告
    Log.e("NativeAd", "是否为下载类广告: " + ad.isAppAd());
    // 获取应用下载次数文案,默认为0; eg: 1000W次下载
    Log.e("NativeAd", "应用下载次数文案: " + ad.getDownloadCount());
    // 应用评分,0-5.0,默认为0
    Log.e("NativeAd", "应用评分: " + ad.getAppScore());
    // 视频时长,默认为0
    Log.e("NativeAd", "视频时长: " + ad.getVideoDuration());
    // 大图素材的宽度,默认为0
    Log.e("NativeAd", "大图素材的宽度: " + ad.getImageWidth());
    // 大图素材的高度,默认为0
    Log.e("NativeAd", "大图素材的高度: " + ad.getImageHeight());
    // 获取下载六要素,可能为空
    ZJNativeAd.ComplianceInfo complianceInfo = ad.getComplianceInfo();
    if (complianceInfo != null) {
        // 下载类型因平台不通,可能出现部分字段为空的情况
        Log.e("NativeAd", "下载类应用名称: " + complianceInfo.getAppName());
        Log.e("NativeAd", "下载类应用版本信息: " + complianceInfo.getAppVersion());
        Log.e("NativeAd", "下载类应用包名: " + complianceInfo.getAppPackageName());
        Log.e("NativeAd", "下载类应用开发者名称: " + complianceInfo.getAppDeveloperName());
        // 应用隐私政策url,需要使用WebView显示该url
        Log.e("NativeAd", "下载类应用隐私政策url: " + complianceInfo.getAppPrivacyUrl());
        // 应用功能介绍url,需要使用WebView展示该url
        Log.e("NativeAd", "下载类应用功能介绍url: " + complianceInfo.getAppFunctionDescUrl());
        // 应用apk包的大小,单位byte
        Log.e("NativeAd", "下载类应用apk包的大小: " + complianceInfo.getPackageSizeBytes());
        Log.e("NativeAd", "下载类应用备案号: " + complianceInfo.getIcpNumber());
        // 获取应用权限URL因平台原因,可能为空字符串,需要做判断和处理
        String appPermissionsUrl = complianceInfo.getAppPermissionsUrl();
        if (!TextUtils.isEmpty(appPermissionsUrl)) {
            // 获取应用权限URL,需要使用WebView显示该url
            Log.e("NativeAd", "下载类获取应用权限URL: " + appPermissionsUrl);
        } else {
            // 权限URL为空时,需要使用异步接口获取权限信息并进行自渲染
            complianceInfo.getAppPermissions(new ZJNativeAd.ComplianceInfo.PermissionsCallback() {
                @Override
                public void callback(@Nullable List<ZJNativeAd.ComplianceInfo.Permission> permissions) {
                    if (permissions == null || permissions.isEmpty()) {
                        // 部分平台会返回空列表
                        Log.e("NativeAd", "下载类获取应用权限获取失败");
                        return;
                    }
                    for (ZJNativeAd.ComplianceInfo.Permission permission : permissions) {
                        // 权限信息不是全部字段都有,title或name一定不为空字符串
                        // eg:
                        // {
                        //  "name" : "android.permission.GET_TASKS",
                        //  "desc" : "允许应用程序获取当前的信息或最近运行的任务。",
                        //  "level" : 1,
                        //  "title" : "检索正在运行的应用。"
                        // }, {
                        //  "name" : "com.asus.msa.SupplementaryDID.ACCESS",
                        //  "desc" : "",
                        //  "level" : 0,
                        //  "title" : "",
                        // }, {
                        //  "name" : "",
                        //  "desc" : "",
                        //  "level" : 0,
                        //  "title" : "修改或删除您的USB存储设备中的内容",
                        // }
                        Log.e("NativeAd", "下载类获取应用权限: " + permission.getName() + " | " + permission.getTitle() + " | " + permission.getDesc() + " | " + permission.getLevel());
                    }
                }
            });
        }
    }
}
ZJNativeAd.loadAd(广告位ID, 1, object : ZJNativeAdLoadListener {

    override fun onError(code: Int, msg: String) {
        Log.e("NativeAd", "onError...$code | $msg")
    }

    override fun onAdLoaded(adList: List<ZJNativeAd?>) {
        Log.e("NativeAd", "onAdLoaded")
        if (!adList.isEmpty()) {
            ad = adList[0]
            getAdInfo(ad)
            // 渲染参照Demo工程的NativeAdRender.java
            render(ad)
        } else {
            Log.e("NativeAd", "onAdLoaded...ret is null")
            Toast.makeText(
                this@NativeDrawActivity,
                "onZjAdLoaded...ret is null",
                Toast.LENGTH_SHORT
            ).show()
        }
    }
    
})

private fun getAdInfo(ad: ZJNativeAd) {
    // 素材类型见ZJNativeAd.MaterialType
    Log.e("NativeAd", "素材类型: " + ad.materialType)
    // 按钮提示文字,可能为空字符串
    Log.e("NativeAd", "按钮提示文字: " + ad.actionButtonText)
    // 标题,可能为空字符串;下载类为App应用名,非下载类为产品名称
    Log.e("NativeAd", "标题: " + ad.title)
    // 描述,可能为空字符串
    Log.e("NativeAd", "描述: " + ad.desc)
    // 下载类型的AppIcon,⾮下载返回为空字符串
    Log.e("NativeAd", "下载类型的AppIcon: " + ad.iconUrl)
    // 主图Url,可能为空字符串
    Log.e("NativeAd", "主图Url: " + ad.imageUrl)
    // {@link #getMaterialType()} 返回 {@link MaterialType#GROUP_IMG} 时需要调用;返回一组图片 URL
    Log.e("NativeAd", "getImageList: " + ad.imageList.size)
    // 是否为下载类广告
    Log.e("NativeAd", "是否为下载类广告: " + ad.isAppAd)
    // 获取应用下载次数文案,默认为0; eg: 1000W次下载
    Log.e("NativeAd", "应用下载次数文案: " + ad.downloadCount)
    // 应用评分,0-5.0,默认为0
    Log.e("NativeAd", "应用评分: " + ad.appScore)
    // 视频时长,默认为0
    Log.e("NativeAd", "视频时长: " + ad.videoDuration)
    // 大图素材的宽度,默认为0
    Log.e("NativeAd", "大图素材的宽度: " + ad.imageWidth)
    // 大图素材的高度,默认为0
    Log.e("NativeAd", "大图素材的高度: " + ad.imageHeight)
    // 获取下载六要素,可能为空
    val complianceInfo = ad.complianceInfo
    if (complianceInfo != null) {
        // 下载类型因平台不通,可能出现部分字段为空的情况
        Log.e("NativeAd", "下载类应用名称: " + complianceInfo.getAppName())
        Log.e("NativeAd", "下载类应用版本信息: " + complianceInfo.getAppVersion())
        Log.e("NativeAd", "下载类应用包名: " + complianceInfo.getAppPackageName())
        Log.e("NativeAd", "下载类应用开发者名称: " + complianceInfo.getAppDeveloperName())
        // 应用隐私政策url,需要使用WebView显示该url
        Log.e("NativeAd", "下载类应用隐私政策url: " + complianceInfo.getAppPrivacyUrl())
        // 应用功能介绍url,需要使用WebView展示该url
        Log.e("NativeAd", "下载类应用功能介绍url: " + complianceInfo.getAppFunctionDescUrl())
        // 应用apk包的大小,单位byte
        Log.e("NativeAd", "下载类应用apk包的大小: " + complianceInfo.getPackageSizeBytes())
        Log.e("NativeAd", "下载类应用备案号: " + complianceInfo.getIcpNumber())
        // 获取应用权限URL因平台原因,可能为空字符串,需要做判断和处理
        val appPermissionsUrl = complianceInfo.getAppPermissionsUrl()
        if (!TextUtils.isEmpty(appPermissionsUrl)) {
            // 获取应用权限URL,需要使用WebView显示该url
            Log.e("NativeAd", "下载类获取应用权限URL: $appPermissionsUrl")
        } else {
            // 权限URL为空时,需要使用异步接口获取权限信息并进行自渲染
            complianceInfo.getAppPermissions(PermissionsCallback { permissions ->
                if (permissions == null || permissions.isEmpty()) {
                    // 部分平台会返回空列表
                    Log.e("NativeAd", "下载类获取应用权限获取失败")
                    return@PermissionsCallback
                }
                for (permission in permissions) {
                    // 权限信息不是全部字段都有,title或name一定不为空字符串
                    // eg:
                    // {
                    //  "name" : "android.permission.GET_TASKS",
                    //  "desc" : "允许应用程序获取当前的信息或最近运行的任务。",
                    //  "level" : 1,
                    //  "title" : "检索正在运行的应用。"
                    // }, {
                    //  "name" : "com.asus.msa.SupplementaryDID.ACCESS",
                    //  "desc" : "",
                    //  "level" : 0,
                    //  "title" : "",
                    // }, {
                    //  "name" : "",
                    //  "desc" : "",
                    //  "level" : 0,
                    //  "title" : "修改或删除您的USB存储设备中的内容",
                    // }
                    Log.e(
                        "NativeAd",
                        "下载类获取应用权限: " + permission.getName() + " | " + permission.getTitle() + " | " + permission.getDesc() + " | " + permission.getLevel()
                    )
                }
            })
        }
    }
}