资讯 News Android SDK 接入文档

概述

本文档描述了 Android 开发者如何集成 News SDK(后面简称为 NewsSdk),通过集成 NewsSdk 为 App 引入完备的信息流服务。

如果需要在信息流和资讯正文中展示广告,则需集成 AdSdk。本文档默认需要展示广告,展示广告可以创造收益。

术语介绍

AppId:应用 id,18位 hex 字符串。【注意】调试时请使用测试 appId:ba0063bfbc1a5ad878;外发版本请替换成正式 appId,否则不会产生收益。

UserId:用户 id,接入方定义的用户唯一标识,传入时可以哈希脱敏,主要用于排查问题。

SDK 集成

方法一:自动集成 (推荐)

通过在 Android Studio 工程的 build.gradle 配置脚本中添加 maven 依赖,导入最新版本 NewsSdk。

步骤一:添加 Maven 仓库地址

allprojects {
    repositories {
        maven {
            credentials {
                username 'iqLuKm'
                password 'pomH01oYcR'
            }
            url 'https://repo.rdc.aliyun.com/repository/117933-release-sPkE7F/'
        }
    }
}

【注意】加在 allprojects 中,不要加在 buildscript 中哦。

步骤二:添加依赖

dependencies {
    // 非 androidx 依赖
    // implementation 'com.android.support:design:28.0.0'

    // androidx 依赖
    implementation 'androidx.appcompat:appcompat:1.3.0'
    implementation 'androidx.localbroadcastmanager:localbroadcastmanager:1.0.0'
    implementation 'androidx.legacy:legacy-support-core-ui:1.0.0'
    implementation 'com.google.android.material:material:1.3.0'
    
    implementation 'com.mob.sdk:oaid-sdk:1.0.27' // 依赖 oaid
    implementation 'com.mob.sdk:adsdk:2.7.25'
    implementation 'com.mob.sdk:newssdk:2.3.5'
}

方法二:手动集成

将 NewsSdk 的 aar 包复制到 Application Module 的 libs 目录下(无此目录需手动创建), 并在工程的 build.gradle 中添加如下配置:

repositories {
    flatDir {
        dirs 'libs'
    }
}

depedencies {
    // 非 androidx 依赖
    // implementation 'com.android.support:design:28.0.0'

    // androidx 依赖
    implementation 'androidx.appcompat:appcompat:1.3.0'
    implementation 'androidx.localbroadcastmanager:localbroadcastmanager:1.0.0'
    implementation 'androidx.legacy:legacy-support-core-ui:1.0.0'
    implementation 'com.google.android.material:material:1.3.0'

    implementation(name: 'oaid-sdk', ext: 'aar') // 依赖 oaid
    implementation(name: 'adsdk-2.7.25', ext: 'aar')
    implementation(name: 'newssdk-2.3.5', ext: 'aar')
}

SDK 初始化

开发者需要在 Application 实例的 onCreate() 方法中调用以下代码来初始化 NewsSdk。

public class DemoApplication extends Application {

    @Override
    public void onCreate() {
        super.onCreate();

        // 初始化 AdSdk,资讯中可以展现广告
        AdSdk.getInstance().init(getApplicationContext(),
                new AdConfig.Builder()
                        .appId(APP_ID)
                        .userId(userId) // 未登录可不设置 userId,登录时再设置
                        .debug(BuildConfig.DEBUG)
                        .build(),
                null);

        NewsSdk.getInstance().init(getApplicationContext(),
                new NewsConfig.Builder()
                        .appId(APP_ID)
                        .userId(userId) // 未登录可不设置 userId,登录时再设置
                        .debug(BuildConfig.DEBUG)
                        .build(),
                null);
            
    }
}

初始化配置参数说明:

private String appId;           // 应用程序 id
private String userId;          // 用户 id
private boolean debug;          // 是否 debug 模式,是则输出日志

登录时请设置 userId:

AdSdk.getInstance().setUserId(userId);
NewsSdk.getInstance().setUserId(userId);

退出登录请重置 userId:

AdSdk.getInstance().setUserId(null);
NewsSdk.getInstance().setUserId(null);

多 TAB 信息流接入

NewsSdk 目前支持接入方采用多TAB的形式接入,已经对 NewsPortalFragment 进行封装,接入方只需将 NewsPortalFragment 放置在对应的 container 容器中即可,具体调用方式可以参考 Demo 中的 NewsPortalActivity。

public class NewsPortalActivity extends FragmentActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_news_portal);

        Fragment fragment = NewsPortalFragment.newInstance();
        getSupportFragmentManager() // fragment 嵌套替换成 getChildFragmentManager()
                .beginTransaction()
                .replace(R.id.container, fragment)
                .commitNowAllowingStateLoss();
    }
}

单列表信息流接入

NewsListFragment 支持展示自定义的频道列表,接入方需要在创建 NewsListFragment 传入频道名称,具体调用方式可以参考 Demo 中的 NewsListActivity。

public class NewsListActivity extends FragmentActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_news_list);

        Fragment fragment = NewsListFragment.newInstance("推荐", false);
        getSupportFragmentManager() // fragment 嵌套替换成 getChildFragmentManager()
                .beginTransaction()
                .replace(R.id.container, fragment)
                .commitNowAllowingStateLoss();
    }
}

主题设置

设置浅色主题(默认)

NewsThemeManager.setLightTheme();

设置深色主题

 NewsThemeManager.setDarkTheme();

自定义主题样式

 NewsThemeManager.setCustomTheme(R.style.NewsStyle);

阅读倒计时(可选)

阅读资讯时可以显示倒计时,倒计时结束后给用户发放奖励。
开发者可调用 NewsSdk 实例的方法来配置倒计时:

public void configReadingCountdown(
    Class<? extends AbstractCountdownView> viewClass,   // 倒计时 View 类,实现了倒计时的交互视觉逻辑
    ViewGroup.LayoutParams params,  // 倒计时 View 布局参数
    ReadingCountdownListener listener   // 倒计时回调
)

可以参考 Demo 中的 CountdownView 类,请根据需求修改此类。自定义的视图类必须继承 AbstractCountdownView,实现构造方法和以下抽象方法:

// 倒计时开始
public abstract void onStart(Object rewardData);

// 进度条更新
public abstract void onProgressUpdate(float progress, int totalSeconds);

// 倒计时结束,并返回奖励结果
public abstract void onEnd(boolean rewardSuccess, Object rewardData);

配置倒计时示例代码如下:

// 请按照设计修改 CountdownView 类,这里是 demo 给出的示例
NewsSdk.getInstance().configReadingCountdown(CountdownView.class, layoutParams,
        new NewsSdk.ReadingCountdownListener() {
            @Override
            public void onReadingStart(NewsSdk.ReadingCountdownHandler handler, String id, String newsUrl, int newsType) {
                // 请按照产品需求,根据 newsUrl、newsType 判断是否启动倒计时,不给奖励可以不调用
                if (NewsType.ARTICLE == newsType || NewsType.VIDEO == newsType) {
                    int countdownSeconds = 10;
                    int scrollEffectSeconds = 3; // 滚动作用时间,到期后暂停计时,再滚动继续计时;小于等于0不滚动也不会暂停计时
                    int rewardData = 4;
                    handler.startCountdown(countdownSeconds, scrollEffectSeconds, rewardData);
                }
            }

            @Override
            public void onReadingPause(String id, String newsUrl, int newsType) {
            }

            @Override
            public void onReadingResume(NewsSdk.ReadingCountdownHandler handler, String id, String newsUrl, int newsType) {
            }
                    
            @Override
            public void onReward(NewsSdk.ReadingRewardHandler handler, String id, String newsUrl, int newsType, Object rewardData) {
                // 在此发放奖励,并设置奖励结果
                boolean success = true;
                handler.setRewardResult(success, rewardData);
            }
            
            @Override
            public void onReadingEnd(String id, String newsUrl, int newsType) {
            }
        });

ReadingCountdownListener 接口说明:

public interface ReadingCountdownListener {
    // 资讯开始阅读回调,此时可以决定是否显示倒计时
    void onReadingStart(ReadingCountdownHandler handler, String id, String newsUrl, int newsType);

    // 资讯暂停阅读回调
    void onReadingPause(String id, String newsUrl, int newsType);

    // 资讯恢复阅读回调
    void onReadingResume(NewsSdk.ReadingCountdownHandler handler, String id, String newsUrl, int newsType);

    // 倒计时结束回调,此时可以给用户发放奖励
    void onReward(ReadingRewardHandler handler, String id, String newsUrl, int newsType, Object rewardData);
    
    // 资讯结束阅读回调
    void onReadingEnd(String id, String newsUrl, int newsType);
}

ReadingCountdownHandler 接口说明:

public interface ReadingCountdownHandler {
    // 启动倒计时
    void startCountdown(int countdownSeconds, int scrollEffectSeconds, Object rewardData);
}

ReadingRewardHandler 接口说明:

public interface ReadingRewardHandler {
    // 设置奖励结果
    void setRewardResult(boolean rewardSuccess, Object rewardData);
}