试玩任务

试玩任务

接入准备

配置 Kotlin 环境

注意

不管是否使用kotlin编写代码,都需要这个步骤

在根目录下的build.gradle下加入如下代码

buildscript {
    ext.kotlin_version = '1.3.41'
    dependencies {
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
    }
}

app modulebuild.gradle加入如下代码

plugins {
    //...
    id 'kotlin-android'
}

dependencies {
    implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
}

添加依赖项

将 SDK 压缩包内的zj_xzzq_ywsdk_x.y.z.aar复制到application module/libs文件夹(没有的话须手动创建), 并增加依赖

depedencies {
    // 试玩任务相关支持包
    implementation files('./libs/ywsdk_x.y.z.aar')
    implementation 'com.liulishuo.filedownloader:library:1.7.7'
    implementation "org.greenrobot:eventbus:3.1.0-RC"
    implementation 'com.google.code.gson:gson:2.8.5'
    implementation 'com.zhy:okhttputils:2.6.2'
}

配置 AndroidManifest

若您的 targetSDKVersion>=23 ,您还需要在运行时进行动态权限申请

<!-- 必要的权限声明 -->
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
<uses-permission android:name="android.permission.PACKAGE_USAGE_STATS" />

提示

您项目中的targetSdkVersion大于等于30时需要在AndroidManifest加入下面配置

<queries>
    <intent>
        <action android:name="android.intent.action.MAIN" />
    </intent>
    <!-- google -->
    <package android:name="com.google.android.gms" />
    <package android:name="com.android.vending" />
    <!-- freeme -->
    <package android:name="com.android.creator" />
    <!-- zte -->
    <package android:name="com.mdid.msa" />
    <!-- samsung -->
    <package android:name="com.samsung.android.deviceidservice" />
    <!-- coolpad -->
    <package android:name="com.coolpad.deviceidsupport" />
    <!-- oppo -->
    <package android:name="com.heytap.openid" />
    <!-- huawei -->
    <package android:name="com.huawei.hwid" />
    <package android:name="com.huawei.hwid.tv" />
    <package android:name="com.huawei.hms" />
    <!-- asus -->
    <package android:name="com.asus.msa.SupplementaryDID" />
    <!-- lenovo -->
    <package android:name="com.zui.deviceidservice" />
</queries>

展示方式说明

试玩任务分为SDK渲染任务列表自渲染两种调用方式,其中:

  • SDK 渲染会直接弹出任务列表页面
  • 任务列表自渲染会根据传入的 page 返回任务信息列表,应用自渲染任务列表后调用onClick(Activty activity)方法进入任务详情页

SDK 渲染调用

调用ZJYWAd#loadAd的重载方法请求广告,并在ZJVoiceAdLoadListener中获取广告对象与处理错误信息

public class ZJYWAd {

    /**
     * 加载广告
     *
     * @param activity     当前Activity
     * @param posId        广告位ID
     * @param userId       用户ID
     * @param loadListener 加载回调
     */
    public static void loadAd(Activity activity, String posId, String userId, ZJYWAdLoadListener loadListener);

}

加载回调说明

方法说明
onError(int code, String msg)广告加载失败
code: 错误码
msg: 错误信息
onAdLoaded(List<ZJYWAd> adList)广告加载成功
adList: 任务列表,SDK 渲染时为空

SDK 渲染示例

注意

onAdLoaded回调中的List<ZJYWAd>是空的List

需要传入正确的 userId 来设置用户账号

ZJYWAd.loadAd(this, posId, userId, new ZJYWAdLoadListener() {

    @Override
    public void onError(int code, @NonNull String msg) {
        Log.e("ZJYWAd", "试玩任务加载出错" + code + "-" + msg);             
    }

    @Override
    public void onAdLoaded(@NonNull List<ZJYWAd> list) {
        // 自渲染的广告信息列表,以Activity展示时返回空列表
    }

})
ZJYWAd.loadAd(this, posId, userId, object : ZJYWAdLoadListener {
        
    override fun onError(code: Int, msg: String) {
        Log.e("ZJYWAd", "试玩任务加载出错" + code + "-" + msg);    
    }

    override fun onAdLoaded(list: List<ZJYWAd>) {
        // 自渲染的广告信息列表,以Activity展示时返回空列表
    }

})

任务列表自渲染调用

调用ZJYWAd#loadAd的重载方法传入页码来请求广告,并在ZJVoiceAdLoadListener中处理错误信息与渲染任务列表:

public class ZJYWAd {

    /**
     * 加载广告
     *
     * @param activity     当前Activity
     * @param posId        广告位ID
     * @param userId       用户ID
     * @param page         自渲染时的任务页码
     * @param loadListener 加载回调
     */
    public static void loadAd(Activity activity, String posId, String userId, int page, ZJYWAdLoadListener loadListener);

}

注意

onAdLoaded回调中的List<ZJYWAd>可能是空的List

需要传入正确的 userId 来设置用户账号

传入的 Activity 对象需要为当前前台的 Activity

加载回调说明

方法说明
onError(int code, String msg)广告加载失败
code: 错误码
msg: 错误信息
onAdLoaded(List<ZJYWAd> adList)广告加载成功
adList: 任务列表,见ZJYWAd

任务信息说明

提示

任务列表自渲染会根据传入的 page 返回任务信息列表,应用自渲染任务列表后调用ZJYWAd#onClick(Activty activity)方法进入任务详情页

ZJYWAd.class

方法说明
onClick(Activity activity)点击事件,进入任务详情页
getAppIcon()获取图标的URL
getAdName()获取广告名称 (app名称)
getSubtitle()获取广告标题 (广告描述)
getRemainDay()获取可以持续的天数
getTaskId()获取任务id
appId()获取广告的应用id,一个广告可能有多个任务
getUserCurrency()获取用户可以获取的奖励(单位:媒体币)
getTotalReward()获取可以获取到的总奖励(单位:媒体币)
getCurrencyName()获取媒体币的名称
getTaskDescription()任务描述
isPlaying()获取是否正在玩

自渲染接入示例

请求数据

ZJYWAd.loadAd(this, posId, userId, 1, new ZJYWAdLoadListener() {

    @Override
    public void onError(int code, @NonNull String msg) {
        Log.e("ZJYWAd", "试玩任务加载出错" + code + "-" + msg);   
    }

    @Override
    public void onAdLoaded(@NonNull List<ZJYWAd> list) {
        // 自渲染的广告信息列表,以Activity展示时返回空列表
        RecyclerView recycler = findViewById(R.id.recycler);
        recycler.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false));
        AdAdapter adapter = new AdAdapter(this, adList);
        recycler.setAdapter(adapter);
    }

})
ZJYWAd.loadAd(this, posId, userId, 1, object : ZJYWAdLoadListener {

    override fun onError(code: Int, msg: String) {
        Log.e("ZJYWAd", "试玩任务加载出错" + code + "-" + msg);   
    }

    override fun onAdLoaded(list: List<ZJYWAd>) {
        // 自渲染的广告信息列表,以Activity展示时返回空列表
        val recycler: RecyclerView = findViewById(R.id.recycler)
        recycler.layoutManager = LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false)
        val adapter = AdAdapter(this, adList)
        recycler.adapter = adapter
    }

})

渲染列表

public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
    ZJYWAd ad = adList.get(position);
    // 广告图标
    Glide.with(activity).load(ad.getAppIcon()).into(holder.icon);
    // 广告名称 (app名称)
    holder.adName.setText(ad.getAdName());
    // 用户可以获取的奖励(单位:媒体币)
    if (StringUtil.isEmpty(ad.getCurrencyName())) {
        holder.userCurrency.setVisibility(View.GONE);
    } else {
        holder.userCurrency.setVisibility(View.VISIBLE);
        // "用户可以获取的奖励" "媒体币的名称"
        String userCurrency = ad.getUserCurrency() + " " + ad.getCurrencyName();
        holder.userCurrency.setText(userCurrency);
    }
    // 可以持续的天数
    if (ad.getRemainDay() > 0) {
        holder.remainDay.setVisibility(View.VISIBLE);
        holder.remainDay.setText(String.format(Locale.getDefault(), "可领%d天", ad.getRemainDay()));
    } else {
        holder.remainDay.setVisibility(View.GONE);
    }
    // 广告标题 (广告描述)
    if (!Objects.equals(ad.getSubtitle(), ad.getTaskDescription()) && ad.getAdName().length() < 6) {
        holder.subtitle.setVisibility(View.VISIBLE);
        holder.subtitle.setText(ad.getSubtitle());
    } else {
        holder.subtitle.setVisibility(View.GONE);
    }
    // 任务描述
    holder.taskDesc.setText(ad.getTaskDescription());
    // 可以获取到的总奖励(单位:媒体币)
    if (!TextUtils.isEmpty(ad.getTotalReward()) && !Objects.equals(ad.getTotalReward(), "0")) {
        holder.totalReward.setVisibility(View.VISIBLE);
        holder.totalReward.setText(String.format(Locale.getDefault(), "%s %s", ad.getTotalReward(), ad.getCurrencyName()));
    } else {
        holder.totalReward.setVisibility(View.GONE);
    }
    // 点击事件
    holder.btn.setText(ad.isPlaying() ? "继续赚" : "马上赚");
    holder.btn.setBackgroundResource(ad.isPlaying() ? R.drawable.shape_yw_mission_btn_bg_playing : R.drawable.shape_yw_mission_btn_bg_default);
    holder.btn.setOnClickListener(v -> ad.onClick(activity));
}
ublic fun onBindViewHolder(holder: ViewHolder, position: Int) {
    val ad = adList[position]
    // 广告图标
    Glide.with(activity).load(ad.appIcon).into(holder.icon)
    // 广告名称 (app名称)
    holder.adName.text = ad.adName
    // 用户可以获取的奖励(单位:媒体币)
    if (ad.currencyName.isNullOrEmpty()) {
        holder.userCurrency.visibility = View.GONE
    } else {
        holder.userCurrency.visibility = View.VISIBLE
        // "用户可以获取的奖励" "媒体币的名称"
        val userCurrency = "${ad.userCurrency} ${ad.currencyName}"
        holder.userCurrency.text = userCurrency
    }
    // 可以持续的天数
    if (ad.remainDay > 0) {
        holder.remainDay.visibility = View.VISIBLE
        holder.remainDay.text = String.format(Locale.getDefault(), "可领%d天", ad.remainDay)
    } else {
        holder.remainDay.visibility = View.GONE
    }
    // 广告标题 (广告描述)
    if (ad.subtitle != ad.taskDescription && ad.adName.length < 6) {
        holder.subtitle.visibility = View.VISIBLE
        holder.subtitle.text = ad.subtitle
    } else {
        holder.subtitle.visibility = View.GONE
    }
    // 任务描述
    holder.taskDesc.text = ad.taskDescription
    // 可以获取到的总奖励(单位:媒体币)
    if (!ad.totalReward.isNullOrBlank() && ad.totalReward != "0") {
        holder.totalReward.visibility = View.VISIBLE
        holder.totalReward.text = String.format(Locale.getDefault(), "%s %s", ad.totalReward, ad.currencyName)
    } else {
        holder.totalReward.visibility = View.GONE
    }
    // 点击事件
    holder.btn.text = if (ad.isPlaying) "继续赚" else "马上赚"
    holder.btn.setBackgroundResource(if (ad.isPlaying) R.drawable.shape_yw_mission_btn_bg_playing else R.drawable.shape_yw_mission_btn_bg_default)
    holder.btn.setOnClickListener { ad.onClick(activity) }
}

试玩任务服务端通知

开发者需要提供回调 URL。服务端回调是指在用户完成任务达到奖励条件时,服务端会向开发者服务端发送一个验证请求,开发者返回响应并根据回调进行奖励发放

请求说明

提示

服务器会以 POST 方式请求第三方服务的回调链接,包含以下参数

参数名必选类型备注
codeint返回状态码
msgstring返回提示
dataobject返回数据
-user_idstring媒体用户id
-order_nostring订单流水号
-stateint操作状态: 1-成功 0-失败
-success_atint任务完成时间戳
-created_atint任务创建时间戳
-media_moneyfloat媒体方可获取的金额,单位元(这个金额包含用户奖励)
-reward_user_ratefloat领取时媒体设置的用户奖励比
-currency_ratefloat媒体设置的媒体币兑换比率
-user_moneyfloat用户领取的金额
-user_currencyfloat用户领取的媒体币
-received_timeint奖励收取时间 (时间戳,单位秒)

请求示例

{
    "code": 200,
    "msg": "成功",
    "data": {
      "user_id": "1",
      "order_no": "12154545",
      "state": 1,
      "success_at": 1436864169 ,
      "created_at": 1436864169,
      "media_money": 0.48,
      "reward_user_rate": 50,
      "currency_rate": 1,
      "user_money": 0.24,
      "user_currency": 0.24,
      "received_time": 1436864169,
    }
}

响应说明

服务端需要对通知请求返回响应,消息的格式为JSON,内容为

参数名类型说明
codeint状态码200-成功,400-失败
msgstring提示信息自定义的消息

响应示例

{"code":400,"msg":"失败"}