请向相关人员申请appKey、appID,SDK_Setting_xxx.json、defaultConfig文件、demo文件。
SDK只支持 Android API Level 26+
工程必须使用AndroidX
工程targetSdkVersion建议低于31
关于资源混淆白名单,广告版暂不支持
sdk广告就绪条件需要一定的时间(一般5秒以内),才可正常使用sdk。 建议开发者在适当时机给到sdk去获取准备就绪条件,避免首次在界面上出现较长的等待时间。例如demo启动界面的处理
xxxxxxxxxx/** * sdk广告/内容准备条件是否就绪 */public static boolean isZbAdReady() { boolean isZbAdReady = ZbSdk.isInitReady() && ZbSdk.getLoadManager() != null && ZbSdk.getLoadManager().isBindReady(); return isZbAdReady;}
调用sdk涉及到的activity需要继承ZbBaseActivity/ZbBaseAppCompatActivity。 建议app端基类activity配置,可参考demo中的com.zbsdk.demo.activity.BaseActivity
app生命周期内,必须要保证有userid。 这个跟服务端发奖有关系,这个userid可以晚但不能没有。初始化的时候如果没有拿到就不要传,后续拿到了可以通过refreshConfig给,refreshConfig不可频繁触发,最好做到在出sdk的界面之前完成触发。
maven配置:
xxxxxxxxxxmaven { url 'https://developer.huawei.com/repo' }maven { url 'https://developer.hihonor.com/repo' }maven {url 'https://maven.aliyun.com/repository/public'}maven {url 'https://artifact.bytedance.com/repository/Volcengine/'}maven {url "https://artifact.bytedance.com/repository/pangle"}maven { credentials { username '6753c35494903881f05bbb1a' password '_T1drLxVa_bo' } url 'https://packages.aliyun.com/5f2d183edb0493ecef90c444/maven/2021838-release-viinmt'}maven { url 'http://sdk.mentamob.com/repository/vlion/' allowInsecureProtocol = true}
maven { credentials { username '67ffa5c0fee9c49c80c56e44' password '0yu(wtW)B-(w' } url 'https://packages.aliyun.com/6753a63e20a07de19c7c0641/maven/2507677-release-gse8dd'}
maven { url "https://jfrog.takuad.com/artifactory/china_sdk"}推荐配置minSdkVersion=26,如果媒体工程必须低于26,可以在AndroidManifest.xml中添加以下配置
xxxxxxxxxx<uses-sdk tools:overrideLibrary="com.zb.sdk,com.ydun.risk"/>xxxxxxxxxximplementation('com.zb.sdk:zbsdk:2.0.9.7') { exclude group: 'com.google.protobuf'}implementation 'com.hz.ydun:sdk:5.1.1'implementation ('io.grpc:grpc-protobuf-lite:1.54.0') { exclude group: 'com.google.protobuf'}sdk清单中内置了以下权限,无需特别声明 ,关于读写权限,sdk强依赖所有文件的读写,开发者需要自行处理适配,关于位置权限,需要给到精确位置授权
xxxxxxxxxx<!--网络权限,必要,如果没有配置该权限,会导致无法获取到网络数据--><uses-permission android:name="android.permission.INTERNET"/><!--apk调起安装,必要,如果没有该权限会导致应用内无法调起安装--><uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES"/><!--文件读写,用于图片存储及上传、文件下载存储、个人设置信息缓存读写、系统及日志文件创建--><uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /><uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /><!--精确位置权限,用于提升ecpm--><uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />sdk内部自带了混淆配置,无需额外处理
当前暂未提供
注意:appKey、appID必须在初始化时传入,建议在初始化时传入配置参数,如果配置数据取不到,可以调用刷新配置的接口方法,具体参考配置刷新栏描述(刷新配置方法传入appID、appKey无效,以初始化的配置为准)。
该方法完全合规,可以在协议弹窗的同意之前调用。如果需要内置闪屏功能,必须在application的onCreate方法中调用。
xxxxxxxxxxZbSdk.preInit(context, zbConfig, new InitCallback() { public void success () {//预初始化成功
}
public void fail ( int code, String msg){//预初始化失败
}});
/** * 预初始化,越早越好,此方法合规,可以在用户同意协议之前调用 * * @param context application context * @param config 初始配置 * @param callBack 回调(非必填) */void preInit(Context context, ZbConfig config, Callback callBack);xxxxxxxxxx
ZbSdk.init(context,zbConfig,new Callback() { public void success () {//初始化成功
}
public void fail ( int code, String msg){//初始化失败
}});
/** * 初始化 * * @param context 上下文 * @param config 初始配置 * @param callBack 回调(非必填) */
void init(Context context, ZbConfig config, InitCallback callBack);
xxxxxxxxxxZbApiNative zbApiNative = new ZbApiNative();zbApiNative.load(new ZbNativeLoader.NativeInfoListener() { public void onLoaded (String json){
}
public void onError(int code, String msg){ }});注意:该代码需要在对象需要销毁时使用,一般建议在Activity的OnDestroy时调用
xxxxxxxxxxzbApiNative.destroy();xxxxxxxxxx[ { "id": "pglOBecXZYgHck8aVHMoWg==", "itemType": 0, "status": 3, "icon": "https://zb.fhks.cn/zb/msg/images/image/pro/17417705237766379.png", "displayAmount": "5.0", "packageName": "com.innovate.gear", "appDisplayTags": "奖励翻倍", "appDisplayIntro": "听歌猜歌名,大奖拿到手", "displayTitle": "猜歌夺金", "btnText": "下载" }, { "id": "LfYdwjKEKb3jSXKzMHo7Wg==", "itemType": 0, "status": 3, "icon": "https://zb.fhks.cn/zb/msg/images/image/pro/17417704840568948.png", "displayAmount": "8.0", "packageName": "com.sciencelab.quantum", "appDisplayTags": "惊喜不断", "appDisplayIntro": "猜歌得惊喜,大波福利来袭!", "displayTitle": "熊猫猜歌", "btnText": "下载" }, { "id": "9sC6UWpoblmQ/TvmQ9YkmA==", "itemType": 0, "status": 3, "icon": "https://zb.fhks.cn/zb/msg/images/image/pro/17417704972513226.png", "displayAmount": "7.0", "packageName": "com.innovation.stream", "appDisplayTags": "奖池扩容", "appDisplayIntro": "听歌猜曲,大奖轻松领", "displayTitle": "乐享猜歌", "btnText": "下载" }, { "id": "94iXoY5BDYxa7Uwhf10MEA==", "itemType": 0, "status": 3, "icon": "https://zb.fhks.cn/zb/msg/images/image/pro/17417705095083120.png", "displayAmount": "6.0", "packageName": "com.techspark.matrix", "appDisplayTags": "新曲热歌", "appDisplayIntro": "猜对就炸福利,手慢无!", "displayTitle": "猜歌趣玩", "btnText": "下载" }, { "id": "r9Qux7IcUy1OHBoYwDtMhw==", "itemType": 0, "status": 3, "icon": "https://zb.fhks.cn/zb/msg/images/image/pro/17401074130644254.png", "displayAmount": "9.99", "packageName": "com.innovate.gear", "appDisplayTags": "热门产品", "appDisplayIntro": "音乐时光机,猜歌赢不停!", "displayTitle": "演示产品", "btnText": "下载" }, { "itemType": 1, "totalAmount": "11.88" }, { "itemType": 2, "completeNum": "0", "taskNum": "2", "totalAmount": "1.0" }, { "itemType": 3, "giveGoldCount": "0" }, { "itemType": 4, "giveGoldCount": "0" }, { "itemType": 5 }]在demo中 com.zbsdk.demo.activity.NativeContentActivity参考相关实现。
xxxxxxxxxx//id从内容列表条目获取ZbDownloadNative zbDownloadNative = new ZbDownloadNative(id);zbDownloadNative.load(new ZbDownloadNative.NativeInfoListener() { public void onLoaded (String json){ }
public void onError ( int code, String msg){ }});注意:该代码需要在对象需要销毁时使用,一般建议在Activity的OnDestroy时调用
xxxxxxxxxxzbDownloadNative.destroy();xxxxxxxxxx{ "displayAmount": 5, "displayTitle": "猜歌夺金", "appDisplayIntro": "玩法一样没什么变化,但这个产品的奖励多多了!", "appDisplayTags": "奖励翻倍", "appDisplayTitle": "猜对歌名, 奖励就能领到", "icon": "https://zb.fhks.cn/zb/msg/images/image/pro/17417705237766379.png", "appDownloadUrl": "https://sdk.gskw.cn/apiFile/sdk/3jqlbBNdOL/137", "id": "pglOBecXZYgHck8aVHMoWg==", "packageName": "com.innovate.gear"}在demo中 com.zbsdk.demo.activity.NativeContentDetailActivity 参考相关实现。
xxxxxxxxxx//itemType从内容列表条目获取ZbNativeContentNative zbNativeContentLoader = new ZbNativeContentNative(itemType);zbNativeContentLoader.load(new ZbNativeContentLoader.NativeContentCallback() { public void refreshList() { // 回调完成,需要调用拉取内容列表(ZbApiNative),更新数据 }
public void onError(int code, String msg) {
}});销毁 注意:该代码需要在对象需要销毁时使用,一般建议在Activity的OnDestroy时调用
xxxxxxxxxxzbNativeContentLoader.destroy();插件app
| 字段 | 备注 |
|---|---|
| id | 条目内容id,app唯一标识 |
| itemType | 条目内容类型,0-插件app,1-签到活动,2-广告必得活动,3 - 阅读赚,4-搜索赚,5-语音红包 |
| status | app状态,1-打开, 2-更新,3-下载,4-打开 |
| btnText | 按钮根据不同的status的值,按钮展示不同的文案 |
| displayTitle | 条目展示标题 |
| appDisplayIntro | 条目展示简介 |
| appDisplayTags | 条目内容展示标签 |
| displayAmount | 展示赚取金额 |
| packageName | app包名 |
| appDownloadUrl | app下载地址 |
签到活动:
| 字段 | 备注 |
|---|---|
| itemType | 值为1 |
| totalAmount | 完成7天签到活动可获得的总金额 |
广告必得活动:
| 字段 | 备注 |
|---|---|
| itemType | 值为2 |
| completeNum | 完成的广告数量 |
| taskNum | 总的广告数量 |
| totalAmount | 完成一轮任务可获得的总金额 |
阅读赚:
| 字段 | 备注 |
|---|---|
| itemType | 值为3 |
| giveGoldCount | 完成所有任务可获得的总金额 |
搜索赚:
| 字段 | 备注 |
|---|---|
| itemType | 值为4 |
| giveGoldCount | 完成所有任务可获得的总金额 |
语音红包:
| 字段 | 备注 |
|---|---|
| itemType | 值为5 |
以下方法的styleType强依赖expressContentStyle,如果配置的styleType与expressContentStyle不匹配,则配置无效,出全样式。
xxxxxxxxxx/** * @param context 上下文 * @param expressContentStyle 模版样式 * @param styleType 模版样式组装类型 * /ZbSdk.getLoadManager().loadExpressContentPage(Context context, int expressContentStyle, List<Integer> styleType);xxxxxxxxxx/** * 获取模版view * @param context 上下文 * @param expressContentStyle 模版样式 * @param styleType 模版样式组装类型 * @return * /ZbSdk.getLoadManager().getZbFragment(style,List<Integer> styleType).getFragment();参考demo中com.zbsdk.demo.tab.TabDemo2Activity的使用
xxxxxxxxxx/** * 获取模版view * @param context 上下文 * @param expressContentStyle 模版样式 * @param styleType 模版样式组装类型 * @return * /ZbSdk.getLoadManager().getExpressView(Context context, int expressContentStyle, List<Integer> styleType);xxxxxxxxxxpublic interface ExpressContentStyle { /** * 默认样式 */ int Default = 0;
/** * 福利中心-样式一 */ int WELFARE_CENTER_1 = 10;
/** * 红包群 */ int RED_PACKET_GROUP = 20;
/** * 福利中心-样式二 */ int WELFARE_CENTER_2 = 30;
/** * 猜歌 */ int GUESS_MUSIC = 40; /** * 短剧 */ int DJX = 50; /** * 短视频 */ int SHORT_VIDEO = 60; /** * 福利中心一的组装类型 */ interface WelfareCenterType { /** * 所有组合 */ int All = 1;
/** * app下载 */ int DownloadApp = 4; /** * 只隐藏头部我的收益 */ int OnlyHideHeader1 = 6; }}
广告的使用之前,必须保证sdk广告就绪条件ok。
xxxxxxxxxxZbSplashAd zbSplashAd = new ZbSplashAd(new OnSplashCallback() {
public void onAdShow() { //开屏广告展示成功 DemoLog.d(TAG, "onAdShow"); }
public void onAdShowFail() { //开屏广告展示失败 DemoLog.d(TAG, "onAdShowFail"); }
public void onAdClose() { //开屏广告关闭 DemoLog.d(TAG, "onAdClose"); closeAd(); }});//展示广告,activity:上下文,frameAdContainer:viewgroup容器,建议使用FrameLayoutzbSplashAd.showAd(Activity activity,FrameLayout frameAdContainer); 推荐在activity的onDestroy中调用,防止内存泄漏。
xxxxxxxxxxif (zbSplashAd != null) { zbSplashAd.destroy();}开屏基本代码调用参考
xxxxxxxxxxcom.zbsdk.demo.activity.ad.SplashAdActivity启动页开屏参考
xxxxxxxxxxcom.zbsdk.demo.launcher.LauncherActivity自1.0.9版本之后,sdk支持内置闪屏。
需要集成广告相关sdk
需要在初始化配置内置参数,可参考demo
必须保证preInit在application的onCreate方法中调用
相关代码示例:
xxxxxxxxxx/** * @param canSplash 指定路径的activity可以展示闪屏 * @param limitSplash 指定路径的activity不可展示闪屏 */public Builder splashConfig(List<String> canSplash,List<String> limitSplash);xxxxxxxxxxZbBannerAd zbBannerAd = new ZbBannerAd(new OnBannerCallback() { public void onAdShowFail() { // banner广告展示失败 DemoLog.d(TAG, "onAdShowFail"); }
public void onAdShow() { // banner广告展示成功 DemoLog.d(TAG, "onAdShowFail"); }
public void onAdClose() { // banner广告的关闭 DemoLog.d(TAG, "onAdClose"); }});//展示广告,activity:上下文,frameAdContainer:viewgroup容器,建议使用FrameLayout,scene:广告展示位置,// 支持:BannerScene.Dialog(弹窗)、BannerScene.Bottom(底部)zbBannerAd.showAd(Activity activity,FrameLayout frameAdContainer, BannerScene scene);推荐在activity的onDestroy中调用,防止内存泄漏。
xxxxxxxxxxif (zbBannerAd != null) { zbBannerAd.destroy();}xxxxxxxxxxcom.zbsdk.demo.activity.ad.BannerAdActivityxxxxxxxxxx ZbFeedAd zbFeedAd = new ZbFeedAd(new OnFeedCallback() { public void onAdShow() { // 信息流广告展示成功 DemoLog.d(TAG, "onAdShow"); }
public void onAdShowFail() { // 信息流广告展示失败 DemoLog.d(TAG, "onAdShowFail"); }
public void onAdClose() { DemoLog.d(TAG, "onAdClose"); }});//展示信息流广告,activity:上下文,frameAdContainer:viewgroup容器,建议使用FrameLayout,scene:广告展示位置,// 支持:FeedScene.Dialog(弹窗信息流)、FeedScene.Large(界面大信息流)、FeedScene.Large(界面小信息流)zbFeedAd.showAd(Activity activity,FrameLayout frameAdContainer, FeedScene.Dialog scene);
推荐在activity的onDestroy中调用,防止内存泄漏。
xxxxxxxxxxif (zbFeedAd != null) { zbFeedAd.destroy();}xxxxxxxxxxcom.zbsdk.demo.activity.ad.FeedAdActivity关闭回调onAdClose、onAdComplete二选一
xxxxxxxxxxZbRewardAd zbRewardAd = new ZbRewardAd(new OnRewardCallback() { public void onRewardAdLoadFail() { showToast("激励广告填充失败"); }
public void onAdShow() { DemoLog.d(TAG, "激励广告展示成功"); }
public void onAdShowFail() { DemoLog.d(TAG, "激励广告展示失败"); }
public void onRewardVideo() { DemoLog.d(TAG, "激励广告激励成功"); }
public void onAdClose() { DemoLog.d(TAG, "激励广告关闭"); } public void onAdComplete(Map<String, Object> map) { DemoLog.d(TAG, "激励广告关闭"); String ecpm = "0"; if (map.containsKey("ecpm")) { ecpm = (String) map.get("ecpm"); } boolean isReward = false; if (map.containsKey("rewardStatus")) { isReward = (boolean) map.get("rewardStatus"); } if (TextUtils.isEmpty(ecpm)) { ecpm = "0"; } showToast("激励广告激励关闭,ecpm:" + ecpm + ",激励状态:" + isReward); }});zbRewardAd.showAd(Activity activity);xxxxxxxxxxif (zbRewardAd != null) { zbRewardAd.destroy();}xxxxxxxxxxcom.zbsdk.demo.activity.ad.RewardAdActivityxxxxxxxxxxZbInterstitialAd zbInterstitialAd = new ZbInterstitialAd( new OnInterstitialCallback() { public void onAdShow() { // 插屏广告展示成功 DemoLog.d(TAG, "onAdShow"); }
public void onAdShowFail() { // 插屏广告展示失败 DemoLog.d(TAG, "onAdShowFail"); }
public void onAdClose() { // 插屏广告的关闭 DemoLog.d(TAG, "onAdClose"); }});zbInterstitialAd.showAd(Activity activity);xxxxxxxxxxif (zbInterstitialAd != null) { zbInterstitialAd.destroy();}xxxxxxxxxxcom.zbsdk.demo.activity.ad.InterstitialAdActivityxxxxxxxxxx/** * 预初始化,越早越好,此方法合规,可以在用户同意协议之前调用(推荐开发者调用此方法) * * @param context 上下文 * @param config 初始配置 * @param callBack 回调(非必填) */void preInit(Context context, ZbConfig config, Callback callBack);
/** * 初始化 * * @param context 上下文 * @param config 初始配置 * @param callBack 回调(非必填) */void init(Context context, ZbConfig config, Callback callBack);
/** * 刷新配置,如果涉及配置数据需要刷新是,可以调用此方法,该方法不会更新AppKey。 * @param config */void refreshConfig(ZbConfig config, Callback callBack);
/** * 创建加载器管理 */ZbTaskLoader getLoadManager();
/** * 获取SDK版本号 */int getSdkVersion();xxxxxxxxxx public static class Builder { //初始化必传 appKey(String appKey); //初始化必传 appID(String appID);
//设置媒体用户ID,必要参数,如果初始化如果没有带入,后续进入sdk界面之前,一定要入参 userId(String mediaAppUserId);
//apk链接,可选 mediaPackageDownloadUrl(String downloadUrl);
//sdk全局弹窗,允许展示的activity集合,默认全局可弹出,如果需要指定弹窗activity,可传入,推荐弹主界面的activity dialogShow(String...dialogShowActivity);
//自定义参数 extra(Map<String, Object> extra);}
ZbTaskLoader
xxxxxxxxxxpublic interface ZbTaskLoader { /** * 获取 Sdk fragnent,一般作用于tab界面 */ ZbFragment getFragmentLoader();
/** * 跳转到sdk主界面 * @param context */ void loadTaskContentPage(Context context);
/** * 初始化是否准备好 * v1.0.7之后开始支持 */ boolean isInitReady();}AndroidManifest中配置以下代码
xxxxxxxxxx<!--压缩so文件,减少资源大小-->android:extractNativeLibs="true" cpu架构 建议只保留arm64-v8a,顶多再加一个armeabi-v7a, 开发者可以根据产品的用户画像,统计其他cpu架构占比添加,支持的架构越多,包体越大
图片资源压缩 建议图片png转webp格式,开发者自行选择压缩比,建议不要低于90%,单个图片大小尽量最大控制在100kb以内
删除无用资源,慎用三方库,提高代码的复用能力
sdk会持续性的做包体压缩
群里咨询即可
回调地址 post请求
加密方式:aes: 加密参数key两边对接;解密代码提供参考
xxxxxxxxxxprivate static final String ALGORITHM = "AES";private static final String TRANSFORMATION = "AES/ECB/PKCS5Padding";
public static String KyyDecrypt(String ciphertext, String key) throws Exception { SecretKeySpec secretKey = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), ALGORITHM); Cipher cipher = Cipher.getInstance(TRANSFORMATION); cipher.init(Cipher.DECRYPT_MODE, secretKey); byte[] decryptedBytes = cipher.doFinal(java.util.Base64.getDecoder().decode(ciphertext)); return new String(decryptedBytes, StandardCharsets.UTF_8);}BASIC
Path: /media/award/cbk/xxx 开发者提供;接口会进行三次重试,均失败后走人工处理
Method: POST
REQUEST
Headers:
| name | value | required | desc |
|---|---|---|---|
| Content-Type | application/json | YES |
Request Body:
加密参数:aes加密,密钥串key和iv根据媒体随机生成
Request Body:
| 参数名 | 类型 | 是否必须 | 备注 |
|---|---|---|---|
| orderId | string | yes | 媒体发奖订单ID |
| mediaAppUserId | string | yes | 媒体产品用户ID |
| media | string | yes | 媒体 |
| customParameters | string | no | 媒体推送的自定义参数,json |
| appName | string | no | 产品名称 |
| userRewardType | int | yes | 用户奖励类型 1-任务奖励 5-人工补贴 6-短剧红包 7-内嵌红包活动 |
| userRewardAmount | string | yes | 用户奖励金额(发放金额-现金);保留4位小数 |
| awardDiscountAmount | string | yes | 用户奖励发放折扣(发放金额-现金);保留4位小数 |
| awardShareAmount | string | yes | 分成金额(发放金额-现金);保留4位小数 |
| userRewardTime | Long | yes | 用户领奖时间(时间戳) |
xxxxxxxxxx加密参数解密后:{orderId:""媒体发奖订单IDmediaAppUserId:""媒体产品用户IDmedia:""媒体customParameters:""媒体推送的自定义参数,jsonappName:""产品名称userRewardType:""用户奖励类型 1-任务奖励 5-人工补贴 6-短剧红包 7-内嵌红包活动userRewardAmount: ""用户奖励金额(发放金额)awardDiscountAmount:""用户奖励发放折扣(发放金额)awardShareAmount: ""分成金额(发放金额-现金);保留4位小数userRewardTime : "" 用户奖励时间(时间戳)}
RESPONSE
Headers:
| name | value | required | desc |
|---|---|---|---|
| content-type | application/json;charset=UTF-8 | NO |
Body:
| name | type | desc |
|---|---|---|
| code | integer | 响应码:200-正常 |
| msg | string | 响应信息 |
Response :
xxxxxxxxxx{ "code": 200, // 200正常 "msg": ""}