本文档旨在帮助 Android 应用开发者在程序中快速植入青云广告服务平台提供的广告。作为应用开发者,您只需要进行可以在您的应用中显示定制的广告。关于 SDK 的具体使用方法,请仔细阅读下面的文档。
支持以下几种广告类型,您可以根据开发需要选择合适的广告:
| 广告类型 | 简介 | 适用场景 |
|---|---|---|
| 开屏广告 | 开屏广告以App启动作为曝光时机,提供5s的可感知广告展示。用户可以点击广告跳转到目标页面;或者点击右上角的“跳过”按钮,跳转到app内容首页。 | APP启动时 |
| 激励广告 | 指将短视频融入到app场景当中,成为app“任务”之一,用户观看短视频广告后可以得到一些应用内奖励。 | 常见于游戏内的广告样式,多出现在游戏的复活、登录等位置,或者网服类app的一些增值服务场景。建议开发者在分析媒体属性和功能的基础上,判断是否嵌入。 |
| 插屏广告 | 插屏半屏是移动广告的一种常见形式,在应用流程中弹出,当应用展示插页式广告时,用户可以选择点按广告,访问其目标网址,也可以将其关闭,返回应用。 插屏全屏广告:是移动广告的一种常见形式,在应用自然流畅结束时全屏弹出,当应用展示插页式广告时,用户可以选择点按广告,访问其目标网址,也可以将其关闭,返回应用。 | 在应用执行流程的自然停顿点,适合投放这类广告 |
| Banner广告 | Banner广告(横幅广告)位于app顶部、中部、底部任意一处,横向贯穿整个app页面;当用户与app互动时,Banner广告会停留在屏幕上,并可在一段时间后自动刷新。 | 常见的展现场景为:文章页末尾,详情页面底部,信息流顶部等。 |
| 原生自渲染 | 您可自行定义广告布局样式和展示场景。 | APP信息流中、任何您希望展示广告的地方、APP中视频内容的框内插入 |
| 信息流模板 | 各类贴合内容场景的广告类型。 | 适用于App 推荐列表(信息流)里、App 详情页内随内容呈现插入、在视频片头、片尾或暂停等位置。 |
SDK接⼊推荐使⽤aar的⽅式进⾏接⼊,具体说明如下:
请在工程文件根目录下创建一个名为 libs 的子目录,并将QY SDK 的 aar包拷贝到 libs 目录下
请在工程build.gradle中添加如下配置:
x
repositories { //本地⽂件仓库依赖 flatDir { dirs 'libs' }}
compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8}
dependencies { // supprot库依赖,SDK内部依赖如下support,请确保添加 compile 'com.android.support:appcompat-v7:28.0.0' compile "com.android.support:support-v4:28.0.0" // qy sdk compile (name:'qy_sdk_3.2.1', ext:'aar') //如果支持广点通sdk,根据对接详情处理 //compile (name: "GDTSDK.unionNormal.${支持的版本}", ext: 'aar') //如果支持快手sdk,根据对接详情处理 //compile (name: "ks_ad_sdk_${支持的版本}", ext: 'aar') //其他平台sdk,根据对接详情处理 //compile (name: "xxx_sdk_${支持的版本}", ext: 'aar') // 如果需要微信生态链路预算-微信小程序广告,再添加 api 'com.tencent.mm.opensdk:wechat-sdk-android:+' // AndroidX依赖 如果您的⼯程使⽤的是AndroidX的环境,请参考官⽹升级AndroidX,在 gradle.properties ⽂件中新增如下配置。 ## Android 插件会使⽤对应的 AndroidX 库⽽⾮⽀持库。 android.useAndroidX=true ## Android 插件会通过重写现有第三⽅库的⼆进制⽂件,⾃动将这些库迁移为使⽤ AndroidX。 android.enableJetifier=true}
注:'qy_sdk_3.2.1'仅为举例,接入时以当前接入aar的文件为准
xxxxxxxxxx<uses-permission android:name="android.permission.INTERNET" /><uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /><uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /><uses-permission android:name="android.permission.READ_PHONE_STATE" /><uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /><uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" /><uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /><uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /><uses-permission android:name="android.permission.GET_TASKS"/><uses-permission android:name="android.permission.WAKE_LOCK" />
如果您打包 App 时的 targetSdkVersion >= 23:请动态获取到 SDK 要求的所有权限,然后再调用 SDK 的广告接口。
请确保您的应⽤打包混淆时,请在混淆配置⽂件添加如下配置:
x
# QY SDK ProGuard -dontwarn com.qy.sdk.** -keep class com.qy.sdk.** { *; }
为了让 SDK 能够正常下载、安装 App 类广告,必须按照下面的步骤做兼容性处理。
在AndroidManifest.xml 中的 Application 标签中添加 provider 标签
x
<provider android:name="com.qy.sdk.fp.QYFileProvider" android:authorities="${applicationId}.QYFileProvider" android:exported="false" android:grantUriPermissions="true"> <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/qy_paths" /></provider>
在res/xml目录下,新建一个xml文件qy_paths,在该文件中添加如下代码:
x
<?xml version="1.0" encoding="utf-8"?><paths> <external-path name="qy_download_file" path="com_qy_dl" /> <external-cache-path name="qy_download_file1" path="com_qy_dl" /> <external-files-path name="qy_download_file2" path="com_qy_dl" /> <cache-path name="qy_download_file3" path="com_qy_dl" /></paths>
xxxxxxxxxx ndk { abiFilters "arm64-v8a", "armeabi-v7a"//根据自己app jni支持的架构实际需要选择填写 }
sourceSets { main { jniLibs.srcDirs = ['libs'] } }
请在您的的 Application 类的 onCreate() 回调中调用如下方法初始化 SDK。
x
/** * sdk初始化⼊⼝ * * @param context applicationContext, 必填 * @param QYSdkConfig config 初始化配置,必填 */ QYAdSdk.init(applicationContext, config);
/** * 初始化配置参数说明 */ QYSdkConfig config = new QYSdkConfig(); config.setAppId("请填入您的AppId"); // 必填参数,应⽤申请的AppId config.setMultiProcess(false); // 是否支持多进程 config.printLog(true); // 可选参数,是否开启⽇志,log tag "QY_SDK" config.complianceController(new QYComplianceController() {...});// 推荐:隐私信息控制 config.setWXAppId("微信开放平台的AppID");// 可选参数,填写微信开放平台移动应用(App)的 AppId,非小程序的 AppID config.setLogoUrl("https://......");// 可选参数,设置广告角标Logo,支持http、https。停用广告角标Logo,设置为 "" 空字符串即可。 config.disableSafeMode();// 可选参数,关闭sdk保护模式;在保护模式下,可以避免大部分常见的错误引起的崩溃,建议正式上线不要关闭保护模式,测试阶段可以关闭
| 方法名 | 参数 | 返回值 | 备注 |
|---|---|---|---|
| init |
1、Context:applicationContext, 2、QYSdkConfig:配置类 |
void | static方法,Application 类的 onCreate() 回调中调用 |
| checkPermission | Activity:Activity实例 | void | static方法,需要时调用 |
| setOAID | 1、Context:上下文 2、String:oaid字符串 |
void | static方法,android10及以上手机需要设置 |
| setPersonalizedState | int:state 0、所有非1的值 : 不屏蔽,1:屏蔽 | void | static方法,个性化推荐⼴告开关 |
| setProgrammaticState | int:state 0、所有非1的值 : 不屏蔽,1:屏蔽 | void | static方法,程序化⼴告推荐开关 |
| 方法名 | 参数 | 返回值 | 备注 |
|---|---|---|---|
| setAppId | String:appid字符串 | QYSdkConfig | 应⽤申请的AppId |
| setMultiProcess | boolean:isMultiProcess | QYSdkConfig | 是否支持多进程 |
| printLog | boolean:enable | QYSdkConfig | 是否开启⽇志,log tag "QY_SDK";默认false |
| complianceController | QYComplianceController:controller | QYSdkConfig | 隐私信息合规控制 |
| disableSafeMode | QYSdkConfig | 关闭sdk保护模式;在保护模式下,可以避免大部分常见的错误引起的崩溃,建议正式上线不要关闭保护模式,测试阶段可以关闭 | |
| setWXAppId | String:wx appid字符串 | QYSdkConfig | 微信开放平台的AppID,非小程序的AppID |
| setLogoUrl | String:url字符串 | QYSdkConfig | 设置广告角标Logo,支持http、https。停用广告角标Logo。设置为 "" 空字符串即可。 |
x
示例:QYSdkConfig config = new QYSdkConfig(); config.setAppId("请填入您的AppId"); config.setWXAppId("微信开放平台的AppID"); config.setMultiProcess(false); config.complianceController(new QYComplianceController() { // 隐私信息控制 public boolean canUsePhoneState() { return true; } });QYAdSdk.init(applicationContext, config);
x
/*注意隐私数据传⼊时,请传入原始值,不需要加密,sdk整体信息加密传输已满⾜合规需求*/public abstract class QYComplianceController {
/** * 是否允许SDK主动使用地理位置信息 * * @return true可以获取,false禁止获取。默认为true */ public boolean canUseLocation() { return true; }
/** * 当isCanUseLocation=false时,可传入地理位置信息,sdk使用您传入的地理位置信息 * * @return 地理位置参数 */ public Location getLocation() { return null; }
/** * 是否允许SDK主动使⽤⼿机硬件参数,如:imei, android_id, meid, imsi, mac * * @return true可以使⽤,false禁⽌使⽤。默认为true */ public boolean canUsePhoneState() { return true; }
/** * 当canUsePhoneState=false时,可传⼊原始的imei信息,sdk使⽤您传⼊的原始imei信息。 * 注意:请传⼊原始imei值,⽆需使⽤md5加密,sdk整体信息加密传输已满⾜合规需要 */ public String getDevImei() { return ""; }
/** * 当canUsePhoneState=false时,可传⼊原始的imsi信息,sdk使⽤您传⼊的原始imsi信息。 * 注意:请传⼊原始imsi值,⽆需使⽤md5加密,sdk整体信息加密传输已满⾜合规需要 */ public String getImsi() { return ""; }
/** * 当canUsePhoneState=false时,可传⼊android_id信息,sdk使⽤您传⼊的android_id */ public String getAndroidId() { return ""; }
/** * 当canUsePhoneState=false时,可传⼊mac信息,sdk使⽤您传⼊的mac */ public String getMacAddress() { return ""; }
/** * 可以传入oaid * 信通院OAID的相关采集——如何获取OAID: * 1. 移动安全联盟官网http://www.msa-alliance.cn/ * 2. 信通院统一SDK下载http://msa-alliance.cn/col.jsp?id=120 * * @return true可以使⽤,false禁⽌使⽤。默认为true */ public boolean canUseOaid() { return true; }
/** * 当canUseOaid=false时,可传⼊oaid信息,sdk使⽤您传⼊的oaid信息 * 注意:请传⼊原始oaid,⽆需使⽤md5加密,sdk整体信息加密传输已满⾜合规需要 */ public String getDevOaid() { return ""; }
/** * 是否允许SDK主动获取设备上应用安装列表的采集权限 * * @return true可以使用,false禁止使用。默认为true */ public boolean canUseInstalledPackages() { return true; }
/** * 新增 * 当canUseInstalledPackages=false时,可传⼊package list信息,sdk使⽤您传⼊的package list */ public List<String> getInstalledPackages() { return null; } /** * 是否允许SDK主动获取安卓系统启动标识 * * @return true可以使用,false禁止使用。默认为true */ public boolean canUseBootId() { return true; }
/** * * 当canUseBootId=false时,可传⼊boot_id信息,sdk使⽤您传⼊的boot_id * 为了保证获取更多的广告预算,建议传入boot_id * 文档末尾见boot_id获取示例 */ public String getBootId() { return ""; } /** * 运营商代码 * MCC(3位数字,移动国家码)+MNC(2位数字,移动网络码) 如:46002 * 建议设置此参数,否则会影响广告填充以及收益 */ public String getMCCMNC() { return ""; }}
x
// 在SDK初始化前设置,否则可能不生效// 应用后台禁用安装监听开关Map<String, Object> params = new HashMap<>();params.put(QYAdConst.KEY.GDT_HIEIB, false);QYAdSdk.setConvOptInfo(params);
| 方法名 | 方法说明 |
|---|---|
| QYSplash(Activity context, String posId, QYSplashEventListener listener) |
构造方法,配合 fetchOnly() 使用,广告相关状态会通过 listener回调。 参数说明:activity(上下文 )、posId(广告位 ID)、listener(广告状态监听器)。 |
| QYSplash(Activity context, String posId, ViewGroup container, QYSplashEventListener listener) |
构造方法,配合 fetchAndShow() 使用,广告相关状态会通过 listener回调。 参数说明:activity(上下文 )、posId(广告位 ID)、ViewGroup(开屏容器)、listener(广告状态监听器)。 |
| fetchAndShow() | 拉取并展示广告,广告内容被填充到 container,container返回值类型ViewGroup,建议请求统计在调用此方法之后进行埋点 |
| fetchOnly() | 拉取广告,配合 showAd() 使用,实现和 fetchAndShow() 相同的功能。建议请求统计在调用此方法之后进行埋点 |
| showAd(ViewGroup container) | 展示广告,配合 fetchOnly() 使用,实现和 fetchAndShow() 相同的功能。 |
| isValid() | 广告是否有效,无效广告将无法展示 |
| getECPM() | 获取本条广告实时的eCPM价格,单位是分 |
| setBidFloor(int bidFloor) | 设置底价价格,单位是分 |
| destroy() | Activity生命周期结束时调用销毁 |
| setDownloadConfirmListener(QYApkDownloadConfirmListener listener) | 设置下载回传接口,在 fetch() 动作之前调用(只适用于集成广点通4.333及以上版本,没有集成则不会生效) |
| fetchApkDownloadInfo(QYApkInfoCallBack callback) | 获取下载信息回传接口,在 QYApkInfoCallBack 回调动作触发后调用(只适用于集成广点通4.333及以上版本,没有集成则不会生效) |
| 方法名 | 方法说明 |
|---|---|
| onADLoaded() | 广告加载成功的回调 |
| onADPresent() | 广告展示时回调,此时一般进行填充统计 |
| onADExposed() | 广告曝光时调用,此时一般进行曝光统计 |
| onADClicked() | 广告被点击时调用 |
| onDismissed() | 广告关闭时调用,可能是用户关闭或者展示时间到。此时需要跳过开屏的 Activity,进入应用内容页面 |
| onADTick(long t) | 倒计时回调,返回广告还将被展示的剩余时间,单位是 ms |
| onADFailed(QYError error) | 广告加载失败,error 对象包含了错误码和错误信息 |
x
// fetchAndShow private void initSplash(final Activity context) { isClicked = false; mSplash = new QYSplash(this, posId, mAdContainer, new QYSplashEventListener() {
public void onADLoaded() { Log.e("QY.DEMO", "onAdLoaded() >>"); }
public void onADPresent() { Log.e("QY.DEMO", "onPresented() >>"+mSplash.getECPM()); }
public void onADExposed() { Log.e("QY.DEMO", "onExposed() >>"); }
public void onADFailed(QYError error) { Log.e("QY.DEMO", "onFailed() >> with: error = [" + error.getErrorCode() + " ,"+error.getErrorMsg() + "]"); }
public void onDismissed() { Log.e("QY.DEMO", "onDismiss() >>"); context.finish(); }
public void onADClicked() { isClicked = true; Log.e("QY.DEMO", "onClicked() >>"); }
public void onADTick(long l) { Log.e("QY.DEMO", "onTick() >> with: timeLeft = [" + l + "]"); } });//开屏测试 mSplash.setDownloadConfirmListener(new QYApkDownloadConfirmListener() { public void onDownloadConfirm(Context activity, QYDownloadConfirmCallBack callBack) { mSplash.fetchApkDownloadInfo(new QYApkInfoCallBack() { public void onApkInfo(QYApkInfo s) { Log.e("QY.DEMO", "onApkInfo() >> with: info = [" + s + "]"); try { final AlertDialog.Builder normalDialog; normalDialog = new AlertDialog.Builder(activity, android.R.style.Theme_DeviceDefault_Light_Dialog); normalDialog.setIcon(null); normalDialog.setTitle("下载确认信息:" + s); normalDialog.setMessage("点击确定"); normalDialog.setPositiveButton("确定", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { callBack.onConfirm();//确认下载 } }); normalDialog.setNegativeButton("取消", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { callBack.onCancel();//取消下载 } }); // 显示 normalDialog.show(); } catch (Exception | Error e) { } } }); } }); mSplash.fetchAndShow(); }
| 方法名 | 方法说明 |
|---|---|
| QYNativeRender(Context context, String posId, QYNativeLoadListener listener) | 构造方法, 参数说明:activity(上下文 )、posId(广告位 ID)、listener(广告数据获取回调)。 |
| loadFeedAD() | 加载广告,count默认为1 |
| loadFeedAD(int count) | 加载广告,count 指定期望加载的广告数量,根据广告填充情况不同,返回不大于 count 数量的广告 |
| setDownloadConfirmStatus(int status) | 指定下载二次确认状态,配合 QYDownloadConfirmPolicy 的 DEFAULT(wifi 不展示,非 wifi 展示)或 NO_CONFIRM(所有情况不展示,直接下载)使用,加载前调用;在显示工信部弹窗时,该设置无效,工信部弹窗会替换二次确认的弹窗 |
| setVideoPlayStatus(int status) | 指定视频广告自动播放状态,配合 QYAutoPlayPolicy 的 WIFI(只在WiFi下自动播放); ALWAYS(始终自动播放,不区分网络); NEVER(始终都不自动播放,不区分网络)使用,加载前调用 |
| setBidFloor(int bidFloor) | 设置底价价格,单位是分 |
| destroy() | Activity生命周期结束时调用销毁 |
| 方法名 | 方法说明 |
|---|---|
| getInteractionType() | 原生数据交互类型: QYInteractionType.NORMAL QYInteractionType.DOWNLOAD |
| getTitle() | 获取标题 |
| getDescription() | 获取描述 |
| getIconUrl() | 获取图标链接 |
| getSource() | 获取广告平台图标地址 |
| getImgList() | 获取多图地址,返回值为List< String >数据类型 |
| getImgUrl() | 获取大图地址 |
| getECPM() | 获取本条广告实时的eCPM价格,单位是分 |
| getAppStatus() | 获取应用下载状态 |
| getProcess() | 获取app类广告的apk文件下载进度 |
| getMaterialType() | 获取大图素材的类型 |
| getVideoDuration() | 获取广告的视频时长,广告加载成功即可获取,单位ms |
| getImageWidth() | 获取大图素材的宽度 |
| getImageHeight() | 获取大图素材的高度 |
| setVideoMute(boolean mute) | 视频广告播放过程中,设置其是否静音,mute为true时表示静音 |
| getVideoCurrentPosition() | 获取视频广告当前已播放时长,单位ms |
| pauseDownload() | 暂停下载正在下载中的应用 |
| resumeDownload() | 继续下载被暂停下载的应用 |
| bindAdToView(ViewGroup container, List creatives) |
绑定广告视图,把返回的视图动态add到layout布局上面准备好的父容器中,返回值为View数据类型 参数说明:container(放置所有原生广告渲染的视图的容器,注意不要给这个View setOnClickListener,否则会影响点击响应) 、creatives(广告接收点击的View列表,注意不要给这个View setOnClickListener,否则会影响点击响应) |
| bindAdToView(ViewGroup container, List creatives, FrameLayout.LayoutParams layoutParams) |
绑定广告视图,把返回的视图动态add到layout布局上面准备好的父容器中,返回值为View数据类型 参数说明:container(放置所有原生广告渲染的视图的容器,注意不要给这个View setOnClickListener,否则会影响点击响应) 、creatives(广告接收点击的View列表,注意不要给这个View setOnClickListener,否则会影响点击响应)、layoutParams(logo位置设置) |
| getMediaView(Context context) | 获取视频渲染视图;返回值为View数据类型,当getMaterialType等于QYPatternType.NATIVE_HORIZONTAL_VIDEO和QYPatternType.NATIVE_HORIZONTAL_VIDEO时 参数说明:context(上下文) |
| getMediaView(Context context, boolean muted) | 获取视频渲染视图;返回值为View数据类型,当getMaterialType等于QYPatternType.NATIVE_HORIZONTAL_VIDEO和QYPatternType.NATIVE_HORIZONTAL_VIDEO时 参数说明:context(上下文);muted(muted为true时表示静音) SDK>=3.2.18支持 |
| onResume() | 当宿主Activity onResume时调用,恢复广告状态,如果不调用会导致广告状态错乱 |
| getNativeAppInfo() | 获取app类广告的app信息,包含应用名称,开发者,版本,apk包大小,隐私政策,权限信息,返回值为QYNativeAppInfo数据类型,对于非app类广告返回值为null |
| setNativeEventListener(QYNativeEventListener listener) | 设置广告点击曝光等事件监听 |
| setNativeMediaListener(QYNativeMediaListener listener) | 视频播放回调 |
| destroy() | 销毁广告,释放View等相关的资源,且广告失效,不能再次使用 |
| startVideo() | 播放视频广告;该接口只对视频广告有效 |
| resumeVideo() | 继续播放被暂停的视频广告;该接口只对视频广告有效 |
| pauseVideo() | 继续播放被暂停的视频广告;该接口只对视频广告有效 |
| stopVideo() | 停止视频广告播放;该接口只对视频广告有效 |
| setDownloadConfirmListener(QYApkDownloadConfirmListener listener) | 设置下载回传接口,在loadFeedAD()动作之前调用(只适用于集成广点通4.333版本之后,没有集成则不会生效) |
| fetchApkDownloadInfo(QYApkInfoCallBack callback) | 获取下载信息回传接口,在QYApkInfoCallBack 回调动作触发后调用(只适用于集成广点通4.333版本之后,没有集成则不会生效) |
| 方法名 | 方法说明 |
|---|---|
| getAppName() | 应用名称 |
| getAppDescription() | 【新增】应用介绍 |
| getAppSize() | 应用apk包的大小 |
| getAuthorName() | 应用开发者 |
| getVersionName() | 应用版本信息 |
| getPermissionsUrl2() | 【新增】权限信息url |
| getPermissionsUrl() | 权限信息,json数据 |
| getPrivacyAgreementUrl() | 应用隐私政策url |
| getDescriptionUrl() | 【新增】功能介绍url |
| 方法名 | 方法说明 |
|---|---|
| onADLoaded(List ads) | 数据获取成功时回调 |
| onFailed(QYError error) | 数据获取失败时回调 |
| 方法名 | 备注 |
|---|---|
| onADExposed() | 曝光回调 |
| onADClicked() | 点击回调 |
| onStatusChanged() | apk数据更新状态时的回调 |
| onError(QYError error) | 错误回调 |
| 方法名 | 备注 |
|---|---|
| onVideoStart() | 开始播放 |
| onVideoResume() | 继续播放 |
| onVideoPause() | 暂停播放 |
| onVideoComplete() | 播放完成 |
| onVideoError(QYError error) | 视频播放报错 |
获取自渲染广告
x
private void loadNativeAd(final Activity activity, String PosId) { QYNativeRender manager = new QYNativeRender(activity, PosId, new QYNativeLoadListener() { public void onADLoaded(List<QYNativeRenderData> list) { if (list != null && list.size() > 0) { Log.e("QY.DEMO", "onADLoaded() >> with: list = [" + list.size() + "]"); for (int i = 0; i < list.size(); i++) { final QYNativeRenderData data = list.get(i); mInfos.add(data); data.setDownloadConfirmListener(new QYApkDownloadConfirmListener() { public void onDownloadConfirm(Context context, QYDownloadConfirmCallBack callBack) { data.fetchApkDownloadInfo(new QYApkInfoCallBack() { public void onApkInfo(QYApkInfo s) { Log.e("QY.DEMO", "onApkInfo() >> with: apk info = [" + s + "]"); try { final AlertDialog.Builder normalDialog; normalDialog = new AlertDialog.Builder(activity, android.R.style.Theme_DeviceDefault_Light_Dialog); normalDialog.setIcon(null); normalDialog.setTitle("下载确认信息:" + s); normalDialog.setMessage("点击确定"); normalDialog.setPositiveButton("确定", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { callBack.onConfirm();//确认下载 } }); normalDialog.setNegativeButton("取消", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { callBack.onCancel();//取消下载 } }); // 显示 normalDialog.show(); } catch (Exception | Error e) { } } }); } }); Log.e("QY.DEMO", "onADLoaded() >> with: render native material type = [" + data.getMaterialType() + " title--->" + data.getTitle() + ", info type--->" + data.getInteractionType()+", vd:"+data.getVideoDuration() +", ecpm:"+data.getECPM() + "]");
QYNativeAppInfo appInfo = data.getNativeAppInfo(); if (appInfo!= null) { try { JSONArray array = new JSONArray(appInfo.getPermissionsUrl()); for (int j = 0; j < array.length(); j++) { Log.e("QY.DEMO", "onADLoaded() >> with: permission = [" + array.get(j) + "]"); } } catch (JSONException e) { e.printStackTrace(); } Log.e("QY.DEMO", "onADLoaded() >> with: app info = [" + appInfo.getAppName() + "\n" + appInfo.getAuthorName() + "\n" + appInfo.getVersionName() + "\n" + appInfo.getAppSize() + "\n" + appInfo.getPrivacyAgreementUrl() + "\n" + appInfo.getPermissionsUrl() + "]"); } View adView = new NativeContainer(activity).renderNativeAd(activity, data); if (adView != null) mAdContainer.addView(adView); break; } } else { Toast.makeText(NativeActivity.this, "native ad failed", Toast.LENGTH_SHORT).show(); } }
public void onFailed(QYError error) { Log.e("QY.DEMO", "onFailed() >> with: error = [" + error.getErrorCode() +" ,"+error.getErrorMsg() + "]"); } }); manager.setDownloadConfirmStatus(QYDownloadConfirmPolicy.DEFAULT); manager.loadFeedAD();}
展示自渲染广告
xxxxxxxxxxpublic class NativeContainer {
ViewGroup mContainer;
public NativeContainer(Context c){ mContainer = new FrameLayout(c); mContainer.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)); }
public View renderNativeAd(final Context c, final QYNativeRenderData data){ data.setNativeEventListener(new QYNativeEventListener() {
public void onADExposed() { Log.e("QY.DEMO", "onADExposed() >>"); }
public void onADClicked() { Log.e("QY.DEMO", "onADClicked() >>"); }
public void onError(QYError error) { Log.e("QY.DEMO", "onError() >> with: error = [" + error.getErrorCode()+" ,"+error.getErrorMsg() + "]"); }
public void onStatusChanged() { Log.e("QY.DEMO", "onStatusChanged() >>" + data.getAppStatus() + " process->" + data.getProgress()); } }); data.setNativeMediaListener(new QYNativeMediaListener() { public void onVideoStart() { Log.e("QY.DEMO", "onVideoStart() >>"); }
public void onVideoPause() { Log.e("QY.DEMO", "onVideoPause() >>"); }
public void onVideoResume() { Log.e("QY.DEMO", "onVideoResume() >>"); }
public void onVideoComplete() { Log.e("QY.DEMO", "onVideoComplete() >>"); }
public void onVideoError(QYError error) { Log.e("QY.DEMO", "onVideoError() >> with: error = [" + error.getErrorCode()+" ,"+error.getErrorMsg() + "]"); } });
//创建广告视图 ViewGroup mAdRoot = (ViewGroup) LayoutInflater.from(c).inflate(R.layout.native_ad_container, null); // !!!此控件非必须使用QYImageView,您也可以使用glide加载!!! QYImageView mAdPoster = mAdRoot.findViewById(R.id.ad_preview); ViewGroup mVideoContainer = mAdRoot.findViewById(R.id.video_container);
//选择需要绑定点击事件的视图 List<View> mCreaters = new ArrayList<>(); mCreaters.add(mAdPoster); mCreaters.add(mAdRoot); mCreaters.add(mVideoContainer);
//渲染 mAdPoster.setImageUrl(data.getImgUrl());
//设置广告容器的LayoutParam ViewGroup.LayoutParams lp = mContainer.getLayoutParams(); float density = c.getResources().getDisplayMetrics().density; lp.height = (int)(200*density); mContainer.setLayoutParams(lp); mContainer.requestLayout();
//设置logo的LayoutParam FrameLayout.LayoutParams mLayoutParam = null; if(mLayoutParam == null) { float dens = c.getResources().getDisplayMetrics().density; mLayoutParam = new FrameLayout.LayoutParams(0, 0); mLayoutParam.gravity = Gravity.RIGHT | Gravity.BOTTOM; }
//绑定视图 View content = data.bindAdToView(mAdRoot, mCreaters, mLayoutParam);
//把视图添加到页面 if(content.getParent() != mContainer){ mContainer.removeAllViews(); if(content.getParent() != null) ((ViewGroup) content.getParent()).removeAllViews(); mContainer.addView(content); }
//设置视频类型的视图 if (data.getMaterialType() == QYPatternType.NATIVE_HORIZONTAL_VIDEO || data.getMaterialType() == QYPatternType.NATIVE_VERTICAL_VIDEO) { View media = data.getMediaView(c); if(media.getParent() != mVideoContainer){ mVideoContainer.removeAllViews(); if(media.getParent() != null) ((ViewGroup)media.getParent()).removeAllViews(); mVideoContainer.addView(media); } if(mVideoContainer.getVisibility() == View.GONE) mVideoContainer.setVisibility(View.VISIBLE); }else{ mVideoContainer.setVisibility(View.GONE); } mContainer.setVisibility(View.VISIBLE); return mContainer; }}
| 方法名 | 方法说明 |
|---|---|
| QYRewardVideo(Activity context, String posId, QYRewardVideoEventListener listener) | 构造方法 参数说明:activity(上下文)、posId(广告位id)、listener(指定广告状态回调接口) |
| loadAD() | 加载激励视频广告,加载成功则调用回调onADLoaded(),加载失败则会调用onADFailed(QYError error) |
| showAD() | 显示激励视频广告,onAdLoaded回调之后才能调用 |
| destroy() | Activity生命周期结束时调用销毁 |
| getECPM() | 获取本条广告实时的eCPM价格,单位是分 |
| setBidFloor(int bidFloor) | 设置底价价格,单位是分 |
| setDownloadConfirmListener(QYApkDownloadConfirmListener listener) | 设置下载回传接口,在 loadAD() 动作之前调用(只适用于集成广点通4.333版本之后,没有集成则不会生效) |
| fetchApkDownloadInfo(QYApkInfoCallBack callback) | 获取下载信息回传接口,在 QYApkInfoCallBack 回调动作触发后调用(只适用于集成广点通4.333版本之后,没有集成则不会生效) |
| 方法名 | 方法说明 |
|---|---|
| onADLoaded() | 激励视频加载成功 |
| onADFailed(QYError error) | 激励视频加载失败 |
| onADExposed() | 激励视频曝光 |
| onADClicked() | 激励视频被点击 |
| onADClosed() | 激励视频广告被关闭 |
| onRewards() | 激励视频广告激励发放 |
| onVideoComplete() | 激励视频素材播放完毕 |
| onADError(QYError error) | 激励视频广告出错 |
xxxxxxxxxx QYRewardVideo rewardVideo;
public void loadRewardVideo() { rewardVideo = new QYRewardVideo(this, posId, new QYRewardVideoEventListener() { public void onADLoaded() { Log.e("QY.DEMO", "onAdLoaded() >>"); }
public void onADFailed(QYError error) { Log.e("QY.DEMO", "onAdFailed() >> with: error = [" + error.getErrorCode() + " ,"+error.getErrorMsg() + "]"); }
public void onADExposed() { Log.e("QY.DEMO", "onADExposed() >>"); }
public void onADClicked() { Log.e("QY.DEMO", "onADClicked() >>"); }
public void onADClosed() { Log.e("QY.DEMO", "onAdClosed() >>"); }
public void onRewards() { Log.e("QY.DEMO", "onRewards() >>"); }
public void onVideoComplete() { Log.e("QY.DEMO", "onVideoComplete() >>"); Toast.makeText(RewardVideoActivity.this, "reward ad complete", Toast.LENGTH_SHORT).show(); }
public void onADError(QYError error) { Log.e("QY.DEMO", "onAdError() >> with: error = [" + error.getErrorCode() + " ,"+error.getErrorMsg() + "]"); } }); rewardVideo.setDownloadConfirmListener(new QYApkDownloadConfirmListener() { public void onDownloadConfirm(Context activity, QYDownloadConfirmCallBack callBack) { rewardVideo.fetchApkDownloadInfo(new QYApkInfoCallBack() { public void onApkInfo(QYApkInfo s) { Log.e("QY.DEMO", "onApkInfo() >> with: s = [" + s + "]"); try { final AlertDialog.Builder normalDialog; normalDialog = new AlertDialog.Builder(activity, android.R.style.Theme_DeviceDefault_Light_Dialog); normalDialog.setIcon(null); normalDialog.setTitle("下载确认信息:" + s); normalDialog.setMessage("点击确定"); normalDialog.setPositiveButton("确定", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { callBack.onConfirm();//确认下载 } }); normalDialog.setNegativeButton("取消", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { callBack.onCancel();//取消下载 } }); // 显示 normalDialog.show(); } catch (Exception | Error e) { } } }); } }); }
public void showAd(View v) { if (rewardVideo != null) rewardVideo.showAD(); }
public void loadAd(View v) { if (rewardVideo != null) rewardVideo.loadAD(); }
protected void onDestroy() { super.onDestroy(); if (rewardVideo != null) rewardVideo.destroy(); }
| 方法名 | 方法说明 |
|---|---|
| QYBanner(Activity context, String posId, ViewGroup container, QYBannerEventListener listener) |
构造方法 second 默认为30s, 自动轮播刷新 参数说明:activity(上下文)、posId(广告位id)、listener(指定广告状态回调接口) |
| QYBanner(Activity context, String posId, int second, ViewGroup container, QYBannerEventListener listener) | 构造方法 参数说明:activity(上下文)、posId(广告位id)、second(设置刷新频率,为0或30~120之间的数字,单位为 s, 0标识不自动轮播)、listener(指定广告状态回调接口) |
| setDownloadConfirmStatus(int status) | 指定下载二次确认状态,配合 QYDownloadConfirmPolicy 的 DEFAULT(wifi 不展示,非 wifi 展示)或 NO_CONFIRM(所有情况不展示,直接下载)使用,加载前调用; 在显示工信部弹窗时,该设置无效,工信部弹窗会替换二次确认的弹窗 |
| loadAD() | 加载广告 |
| getECPM() | 获取本条广告实时的eCPM价格,单位是分 |
| setBidFloor(int bidFloor) | 设置底价价格,单位是分 |
| destroy() | Activity生命周期结束时调用销毁 |
| setDownloadConfirmListener(QYApkDownloadConfirmListener listener) | 设置下载回传接口,在 loadAD() 动作之前调用(只适用于集成广点通4.333版本之后,没有集成则不会生效) |
| fetchApkDownloadInfo(QYApkInfoCallBack callback) | 获取下载信息回传接口,在 QYApkInfoCallBack 回调动作触发后调用(只适用于集成广点通4.333版本之后,没有集成则不会生效) |
| 方法名 | 方法说明 |
|---|---|
| onADReceive() | 广告填充 |
| onADExposed() | 广告曝光 |
| onADFailed(QYError error) | 广告加载失败 |
| onADClicked() | 广告点击 |
| onClosed() | 广告关闭;3.2.16版本及以上 |
xxxxxxxxxx QYBanner mBanner; private void initBannerAd(ViewGroup mContainer, final Activity activity) { if (mBanner == null) { mBanner = new QYBanner(activity, mEditText.getText().toString(), 0, mContainer, new QYBannerEventListener() { public void onADReceive() { Log.e("QY.DEMO", "onADReceive() >>"); }
public void onADFailed(QYError error) { Log.e("QY.DEMO", "onADFailed() >> with: error = [" + error.getErrorCode() +" ,"+error.getErrorMsg() + "]"); }
public void onClosed() { Log.e("QY.DEMO", "onClosed() >>"); }
public void onADExposed() { Log.e("QY.DEMO", "onADExposed() >>"); }
public void onADClicked() { Log.e("QY.DEMO", "onADClicked() >>"); } }); } mBanner.setDownloadConfirmListener(new QYApkDownloadConfirmListener() { public void onDownloadConfirm(Context context, QYDownloadConfirmCallBack callBack) { mBanner.fetchApkDownloadInfo(new QYApkInfoCallBack() { public void onApkInfo(QYApkInfo s) { Log.e("QY.DEMO", "onApkInfo() >> with: apk info = [" + s + "]"); try { final AlertDialog.Builder normalDialog; normalDialog = new AlertDialog.Builder(activity, android.R.style.Theme_DeviceDefault_Light_Dialog); normalDialog.setIcon(null); normalDialog.setTitle("下载确认信息:" + s); normalDialog.setMessage("点击确定"); normalDialog.setPositiveButton("确定", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { callBack.onConfirm();//确认下载 } }); normalDialog.setNegativeButton("取消", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { callBack.onCancel();//取消下载 } }); // 显示 normalDialog.show(); } catch (Exception | Error e) { } } }); } }); mBanner.loadAD(); } protected void onDestroy() { super.onDestroy(); if (mBanner != null) mBanner.destroy(); }
| 方法名 | 方法说明 |
|---|---|
| QYInterstitial(Activity context, String posId, QYInterstitialEventListener listener) | 构造方法 参数说明:activity(上下文)、posId(广告位id)、listener(指定广告状态回调接口) |
| loadAD() | 加载插屏广告 |
| showAD() | 展示插屏广告,(展示使用loadAD()加载的广告) |
| showAD(Activity activity) | 展示插屏广告,(展示使用loadAD()加载的广告) |
| close() | 插屏半屏广告关闭 |
| getECPM() | 获取本条广告实时的eCPM价格,单位是分 |
| setBidFloor(int bidFloor) | 设置底价价格,单位是分 |
| setMediaListener(QYInterstitialMediaListener listener) | 设置视频广告的状态监听 |
| destroy | Activity生命周期结束时调用销毁 |
| setDownloadConfirmListener(QYApkDownloadConfirmListener listener) | 设置下载回传接口,在 loadAD() 动作之前调用(只适用于集成广点通4.333版本之后,没有集成则不会生效) |
| fetchApkDownloadInfo(QYApkInfoCallBack callback) | 获取下载信息回传接口,在 QYApkInfoCallBack 回调动作触发后调用(只适用于集成广点通4.333版本之后,没有集成则不会生效) |
| 方法名 | 方法说明 |
|---|---|
| onReceive() | 广告加载完毕 |
| onADExposed() | 广告曝光时回调 |
| onADClicked() | 广告点击时回调 |
| onClosed() | 广告关闭时回调 |
| onError(QYError error) | 广告加载失败,error 对象包含了错误码和错误信息 |
| 方法名 | 方法说明 |
|---|---|
| onVideoReady(long duration) | 视频加载成功,准备好可以播放了,duration 是视频素材的时间长度,单位为 ms |
| onVideoStart() | 视频开始播放 |
| onVideoPause() | 视频暂停 |
| onVideoComplete() | 视频播放结束,自然播放到达最后一帧时都会触发 |
| onVideoError(QYError error) | 视频播放时出现错误,error 对象包含了错误码和错误信息 |
注意:您需要处理好 Activity 的运行时变更,由于视频广告可以跟随手机屏幕的方向旋转和全屏播放,请处理好 Activity 的运行时变更(最简单的方式就是在 AndroidManifest 文件中给您的 Activity 加上 android:configChanges="keyboard|keyboardHidden|orientation|screenSize" 属性),不要让播放视频广告的 Activity 被销毁重建。
xxxxxxxxxxpublic class InterstitialActivity extends AppCompatActivity implements QYInterstitialEventListener, QYInterstitialMediaListener {
QYInterstitial interstitial;
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_test_intetstitial); mEditText = (EditText) findViewById(R.id.placeid); mEditText.setText(MyApplication.getInterstitialId()); }
public void loadInter(View v) { interstitial = new QYInterstitial(this, posId, this); interstitial.setDownloadConfirmListener(new QYApkDownloadConfirmListener() { public void onDownloadConfirm(Context context, QYDownloadConfirmCallBack callBack) { interstitial.fetchApkDownloadInfo(new QYApkInfoCallBack() { public void onApkInfo(QYApkInfo s) { Log.e("QY.DEMO", "onApkInfo() >> with: apk info = [" + s + "]"); try { final AlertDialog.Builder normalDialog; normalDialog = new AlertDialog.Builder(context, android.R.style.Theme_DeviceDefault_Light_Dialog); normalDialog.setIcon(null); normalDialog.setTitle("下载确认信息:" + s); normalDialog.setMessage("点击确定"); normalDialog.setPositiveButton("确定", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { callBack.onConfirm();//确认下载 } }); normalDialog.setNegativeButton("取消", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { callBack.onCancel();//取消下载 } }); // 显示 normalDialog.show(); } catch (Exception | Error e) { } } }); } }); if (interstitial == null) return; interstitial.loadAD(); }
public void showInter(View v) { if (interstitial == null) { return; } interstitial.showAD(); }
public void closeInter(View v) { if (interstitial == null) { return; } interstitial.close(); }
protected void onDestroy() { super.onDestroy(); if (interstitial != null) interstitial.destroy(); }
public void onReceive() { Log.e("QY.DEMO", "onReceive() >>"); if (interstitial == null) { return; } interstitial.setMediaListener(this); }
public void onADExposed() { Log.e("QY.DEMO", "onADExposed() >>"); }
public void onADClicked() { Log.e("QY.DEMO", "onADClicked() >>"); }
public void onClosed() { Log.e("QY.DEMO", "onClosed() >>"); }
public void onError(QYError error) { Log.e("QY.DEMO", "onError() >> with: error = [" + error.getErrorCode() +" ,"+error.getErrorMsg() + "]"); }
public void onVideoReady(long l) { Log.e("QY.DEMO", "onVideoReady() >> with: l = [" + l + "]"); }
public void onVideoStart() { Log.e("QY.DEMO", "onVideoStart() >>"); }
public void onVideoPause() { Log.e("QY.DEMO", "onVideoPause() >>"); }
public void onVideoComplete() { Log.e("QY.DEMO", "onVideoComplete() >>"); }
public void onVideoError(QYError error) { Log.e("QY.DEMO", "onVideoError() >> with: error = [" + error.getErrorCode() +" ,"+error.getErrorMsg() + "]"); }}
| 方法名 | 方法说明 |
|---|---|
| QYNativeExpress(Activity context, String posId, QYNativeExpressLoadListener listener) | 构造方法, 参数说明:activity(上下文 )、posId(广告位 ID)、listener(广告数据获取回调)。 |
| loadExpressAD() | 加载广告,count默认为1 |
| loadExpressAD(int count) | 加载广告,count 指定期望加载的广告数量,根据广告填充情况不同,返回不大于 count 数量的广告 |
| setExpressViewSize(int width, int height) | 设置请求模板广告的预期宽高,单位为 dp 1.如果需要自己设置值,那么宽度、高度都必须是大于0的整数, 2.如果将高度设为 0 , 可以不需要自己调整广告的高度,此时只需要设定广告的宽度,SDK 会自动判断出广告在这个宽度下的最佳高度,并将 ExpressView 的高度设置为最佳高度。高度方面,我们建议尽量使用 0,保证广告的展示效果; 3. 如果将广告的宽度设为 0,ExpressView 会最大程度的使用其父控件给予的宽度,此时可以自己设置高度或者选用 0。 |
| setDownloadConfirmStatus(int status) | 指定下载二次确认状态,配合 QYDownloadConfirmPolicy 的 DEFAULT(wifi 不展示,非 wifi 展示)或 NO_CONFIRM(所有情况不展示,直接下载)使用,加载前调用;在显示工信部弹窗时,该设置无效,工信部弹窗会替换二次确认的弹窗 |
| setVideoPlayStatus(int status) | 指定视频广告自动播放状态,配合 QYAutoPlayPolicy 的 WIFI(只在WiFi下自动播放); ALWAYS(始终自动播放,不区分网络); NEVER(始终都不自动播放,不区分网络)使用,加载前调用 |
| setBidFloor(int bidFloor) | 设置底价价格,单位是分 |
| destroy() | Activity生命周期结束时调用销毁 |
| 方法名 | 方法说明 |
|---|---|
| getExpressView() | 绑定广告视图,把返回的视图动态add到layout布局上面准备好的父容器中,返回值为View数据类型 |
| getECPM() | 获取本条广告实时的eCPM价格,单位是分 |
| setNativeExpressEventListener(QYNativeExpressEventListener listener) | 设置模板广告点击曝光等事件监听 |
| setNativeExpressMediaListener(QYNativeExpressMediaListener listener) | 设置模板视频广告播放状态等事件监听 |
| setDownloadConfirmListener(QYApkDownloadConfirmListener listener) | 设置下载回传接口,在loadExpressAD()动作之前调用(只适用于集成广点通4.333版本之后,没有集成则不会生效) |
| fetchApkDownloadInfo(QYApkInfoCallBack callback) | 获取下载信息回传接口,在QYApkInfoCallBack 回调动作触发后调用(只适用于集成广点通4.333版本之后,没有集成则不会生效) |
| destroy() | 销毁广告,释放View等相关的资源,且广告失效,不能再次使用 |
| 方法名 | 方法说明 |
|---|---|
| onADLoaded(List ad) | 数据获取成功时回调 |
| onFailed(QYError error) | 数据获取失败时回调 |
| 方法名 | 备注 |
|---|---|
| onRenderSuccess() | 渲染广告成功 |
| onRenderFail(QYError error) | 渲染广告失败 |
| onADExposed() | 曝光回调 |
| onADClicked() | 点击回调 |
| onClosed() | apk数据更新状态时的回调 |
| onError(QYError error) | 错误回调 |
| 方法名 | 备注 |
|---|---|
| onVideoStart() | 开始播放 |
| onVideoResume() | 继续播放 |
| onVideoPause() | 暂停播放 |
| onVideoComplete() | 播放完成 |
| onVideoError(QYError error) | 视频播放报错 |
xxxxxxxxxxpublic class NativeExpressActivity extends Activity implements QYNativeExpressEventListener, QYNativeExpressMediaListener {
ViewGroup mAdContainer;
List<QYNativeExpressData> mInfos = new ArrayList<>();
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_test_native_express); getWindow().setFlags(WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED, WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED); mEditText = (EditText) findViewById(R.id.placeid); mEditText.setText(MyApplication.getNativeExpressId()); mAdContainer = (ViewGroup) findViewById(R.id.ad_container);
}
public void loadExpressAd(View v) { mInfos.clear(); mAdContainer.removeAllViews(); loadNativeAd(NativeExpressActivity.this, posId); }
private void loadNativeAd(final Activity activity, String posId) { QYNativeExpress mFactory = new QYNativeExpress(activity, posId, new QYNativeExpressLoadListener() { public void onADLoaded(List<QYNativeExpressData> list) { if (list != null && list.size() > 0) { for (int i = 0; i < list.size(); i++) { final QYNativeExpressData data = list.get(i); mInfos.add(data); Log.e("QY.DEMO", "render native poster type->" ); if (mAdContainer.getVisibility() != View.VISIBLE) { mAdContainer.setVisibility(View.VISIBLE); } View adView = data.getExpressView();
if (mAdContainer.getChildCount() > 0) { mAdContainer.removeAllViews(); }
mAdContainer.addView(adView); data.setNativeExpressEventListener(NativeExpressActivity.this); data.setNativeExpressMediaListener(NativeExpressActivity.this); data.setDownloadConfirmListener(new QYApkDownloadConfirmListener() { public void onDownloadConfirm(Context context, QYDownloadConfirmCallBack callBack) { data.fetchApkDownloadInfo(new QYApkInfoCallBack() { public void onApkInfo(QYApkInfo s) { Log.e("QY.DEMO", "onApkInfo() >> with: APK INFO = [" + s + "]"); try { final AlertDialog.Builder normalDialog; normalDialog = new AlertDialog.Builder(activity, android.R.style.Theme_DeviceDefault_Light_Dialog); normalDialog.setIcon(null); normalDialog.setTitle("下载确认信息:" + s); normalDialog.setMessage("点击确定"); normalDialog.setPositiveButton("确定", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { callBack.onConfirm();//确认下载 } }); normalDialog.setNegativeButton("取消", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { callBack.onCancel();//取消下载 } }); // 显示 normalDialog.show(); } catch (Exception | Error e) { } } }); } }); break; } } else { Log.e("QY.DEMO", "onADLoaded() >> native express ad failed data is null"); } }
public void onFailed(QYError error) { Log.e("QY.DEMO", "onFailed() >> with: error = [" + error.getErrorCode() + " ,"+error.getErrorMsg() + "]"); } }); mFactory.loadExpressAD(); }
protected void onResume() { Log.e("QY.DEMO", "onResume() >>"); super.onResume(); }
protected void onPause() { Log.e("QY.DEMO", "onPause() >>"); super.onPause();
}
protected void onDestroy() { super.onDestroy(); for (QYNativeExpressData info : mInfos) info.destroy(); }
public void onADExposed() { Log.e("QY.DEMO", "onADExposed() >>"); }
public void onADClicked() { Log.e("QY.DEMO", "onADClicked() >>"); }
public void onRenderSuccess() { Log.e("QY.DEMO", "onRenderSuccess() >>"); }
public void onRenderFail(QYError error) { Log.e("QY.DEMO", "onRenderFail() >> with: error = [" + error.getErrorCode()+" ,"+error.getErrorMsg() + "]"); }
public void onClosed() { Log.e("QY.DEMO", "onClosed() >>"); }
public void onError(QYError error) { Log.e("QY.DEMO", "onError() >> with: error = [" + error.getErrorCode()+" ,"+error.getErrorMsg() + "]"); }
public void onVideoStart() { Log.e("QY.DEMO", "onVideoStart() >>"); }
public void onVideoPause() { Log.e("QY.DEMO", "onVideoPause() >>"); }
public void onVideoResume() { Log.e("QY.DEMO", "onVideoResume() >>"); }
public void onVideoComplete() { Log.e("QY.DEMO", "onVideoComplete() >>"); }
public void onVideoError(QYError error) { Log.e("QY.DEMO", "onVideoError() >> with: error = [" + error.getErrorCode()+" ,"+error.getErrorMsg() + "]"); }}
| 方法名 | 方法说明 |
|---|---|
| onDownloadConfirm(Context context, QYDownloadConfirmCallBack callBack) | 下载确认回调 参数说明: 1.Activity:下载行为承载活动页 2.QYDownloadConfirmCallback:下载确认回调接口 |
| 方法名 | 方法说明 |
|---|---|
| onConfirm() | 确认下载 |
| onCancel() | 取消下载 |
| 方法名 | 方法说明 |
|---|---|
| onApkInfo(QYApkInfo info) | app信息加载成功 QYApkInfo : info 信息6要素 |
适用于广点通
| 方法名 | 方法说明 |
|---|---|
| iconUrl | App Icon |
| appName | App 名称 |
| versionName | 版本号 |
| descriptionUrl | 【新增】应用介绍url |
| authorName | 开发者 |
| permissions | 权限列表(具体权限信息,非URL) |
| privacyAgreement | 隐私政策(URL) |
| apkPublishTime | 版本更新时间 |
| fileSize | apk文件大小,bytes |
xxxxxxxxxxpublic class DownloadHelper {
public QYApkDownloadConfirmListener DL_LISTENER = new QYApkDownloadConfirmListener() {
public void onDownloadConfirm(Activity activity, final QYDownloadConfirmCallback confirmCallback) { data.fetchApkDownloadInfo(new QYApkInfoCallBack() {//在onDownloadConfirm回调以后 获取应用信息 6 要素 public void onApkInfo(QYApkInfo s) { Log.e("QY.DEMO", "onApkInfo() >> with: apk info = [" + s + "]"); } }); QYApkInfo info = getApkInfoFromJson(s); showApkInfoDialog(info, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { if(confirmCallback != null){ confirmCallback.confirm();//确认下载 } } }, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { if(confirmCallback != null){ confirmCallback.cancel();//取消下载 } } }); } }; }
| 常量名 | 返回值类型 | 常量说明 |
|---|---|---|
| NORMAL | int | 一般类型 |
| DOWNLOAD | int | 下载类型 |
| SCENES_NATIVE | int | 下载回调原生场景 |
| SCENES_H5 | int | 下载回调h5场景 |
| 常量名 | 返回值类型 | 常量说明 |
|---|---|---|
| NATIVE_UNKNOWN | int | 未知 |
| NATIVE_MULTI_IMAGE | int | 样式多 |
| NATIVE_VERTICAL_IMAGE | int | 竖图 |
| NATIVE_HORIZONTAL_IMAGE | int | 横图 |
| NATIVE_VERTICAL_VIDEO | int | 竖版视频 |
| NATIVE_HORIZONTAL_VIDEO | int | 横版视频 |
| 常量名 | 返回值类型 | 常量说明 |
|---|---|---|
| APP_STATUS_UNKNOWN | int | 尚未下载 |
| APP_STATUS_INSTALLED | int | 已经安装 |
| APP_STATUS_DOWNLOADING | int | 正在下载 |
| APP_STATUS_DOWNLOAD_FINISHED | int | 已经下载完成 |
| APP_STATUS_DOWNLOAD_FAILED | int | 下载失败 |
| APP_STATUS_DOWNLOAD_PAUSED | int | 下载暂停 |
| 常量名 | 返回值类型 | 常量说明 |
|---|---|---|
| DEFAULT | int | 下载再确认状态:wifi 不展示,非 wifi 展示 |
| NO_CONFIRM | int | 下载再确认状态:所有情况不展示,直接下载 |
| 常量名 | 返回值类型 | 常量说明 |
|---|---|---|
| WIFI | int | wifi自动播放,非wifi手动播放 |
| ALWAYS | int | 始终自动播放,不区分网络 |
| NEVER | int | 始终都不自动播放,不区分网络 |
微信生态链路广告,是指用户点击广告后,将跳转至微信打开微信小程序/小游戏/公众号/企业微信等场景,在微信内部发生后续的行为转化的广告类型。
按下文流程接入微信生态链路广告后,能有效提高广告填充率和eCPM。
① 进入微信开放平台创建移动应用并获取到相应的微信开放平台AppID;
② 在移动应用中嵌入微信最新版OpenSDK(仅嵌入即可,无需额外开发工作),并确认版本为Android v5.3.1 以上;
③ 将微信开放平台 App ID与当前应用进行关联。
① 在微信开放平台进行注册,并创建主体账号、应用(如历史已创建可忽略);
② 在微信开放平台管理中心,获取应用所对应的微信开放平台AppID。
需确认OpenSDK版本为Android 5.3.1及以上。
xxxxxxxxxx// 直接引用最新版本api 'com.tencent.mm.opensdk:wechat-sdk-android:+'// 或者指定版本// api 'com.tencent.mm.opensdk:wechat-sdk-android:6.8.30'
嵌入OpenSDK的详细方法及资源可参考Android接入指南|微信开放文档
在开发者平台的【流量合作 | 我的媒体】中,找到需要关联App ID的应用,点击【微信渠道信息】,即可将微信开放平台的AppID与指定应用进行绑定。具体操作如下图所示:

在初始化时,通过调用SDK的API设置微信微信开放平台的AppID:
xxxxxxxxxx示例:QYSdkConfig config = new QYSdkConfig(); ... config.setWXAppId("微信开放平台的AppID");QYAdSdk.init(applicationContext, config);
| 错误码 | 错误信息 |
|---|---|
| 2005 | 加载错误;详见错误message |
| 3001 | 网络错误 |
| 3002 | 请求广告超时 |
| 3003 | 手机无网络 |
| 4001 | 初始化错误, 包括PosId为空、AppId为空、ViewController为空 |
| 4003 | 广告位错误 |
| 4006 | 广告未曝光 |
| 4007 | 设备不支持 |
| 4021 | AppId错误,请登录平台确认 |
| 5001 | 后台数据错误; 详见错误message |
| 5003 | 视频素材错误;广告视频加载出错 |
| 5005 | 广告请求量或者消耗等超过日限额 |
| 5006 | 广告请求量或者消耗等超过小时限额 |
| 5007 | 当前页面不可见 |
| 5008 | 包名校验非法 |
private static String getBootId() { BufferedReader input = null; try { Process p = Runtime.getRuntime().exec("cat /proc/sys/kernel/random/boot_id"); input = new BufferedReader(new InputStreamReader(p.getInputStream()), 1024); String ret = input.readLine(); if (ret != null) { return ret; } } catch (Throwable throwable) { throwable.printStackTrace(); } finally { if (input != null) { try { input.close(); } catch (Throwable throwable) { throwable.printStackTrace(); } } } return "";}