# 云资源下载及上传 Android SDK

# 简介

SDK 支持播放视频、音频、Word/PDF文档、静态PPT4种类型的资源播放。其中,视频中支持倍速播放、切换清晰度,水印、指纹等基本视频播放功能

# 开发环境要求

  • Java 1.8
  • Android Studio 3.4.2 及以上
  • 最低支持Android 4.3 运行环境

# 快速集成

在工程根目录下build.gradle中添加以下引用地址:

maven {
    url "https://raw.github.com/codeages/maven/master/"
}

在libraray的build.gradle中添加Java 1.8:

android {
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
}

在libraray的build.gradle中添加gradle依赖:

implementation 'com.edusoho.cloud:manager:1.0.4-SNAPSHOT'

# 开发指南

# 初始化

在App首页启动完成后初始化

Downloader.init(getApplicationContext());

# ResourceTask 下载资源参数设置

# setResNo(String resNo)

  • 类型:String
  • 必填:是
  • 描述:设置云资源唯一编号。
  • 用法:
ResourceTask.Builder builder =  ResourceTask.Builder();
ResourceTask resourceTask = builder.setResNo(params.get("resNo"))
                                   .setToken(params.get("token"))
                                   .build();

# setToken(String token)

  • 类型:String
  • 必填:是
  • 描述:设置云资源播放令牌。
  • 用法:
ResourceTask.Builder builder =  ResourceTask.Builder();
ResourceTask resourceTask = builder.setResNo(params.get("resNo"))
                                   .setToken(params.get("token"))
                                   .build();

# setDefinition(ResourceDefinition resourceDefinition)

  • 参数:ResourceDefinition,详见参数说明。
  • 必填:否
  • 描述:设置下载资源的清晰度,如未找到指定清晰度,则按低一级清晰度下载。
  • 用法:
ResourceTask.Builder builder =  ResourceTask.Builder();
ResourceTask resourceTask = builder.setResNo(params.get("resNo"))
                                   .setToken(params.get("token"))
                                   .setDefinition(ResourceDefinition.SHD)
                                   .build();

# 下载回调

下载资源分为2个阶段:

  1. 请求资源获取下载信息
  2. 开始下载

一共4个回调事件,顺序:

taskStart -> infoReady -> progress -> taskEnd 。

# taskStart(ResourceTask task)

  • 参数:ResourceTask task,要下载的资源信息。
  • 描述:获取资源信息前回调。
  • 用法:
ResourceListener ResourceListener = new ResourceListener(){
    @Override
    public void taskStart(ResourceTask task) {
        // 处理你的下载前的业务
    }
};

# infoReady(ResourceTask task, long totalLength)

  • 参数:ResourceTask task,要下载的资源信息,long totalLength下载总数量
  • 描述:下载的资源信息获取完成回调。
  • 用法:
ResourceListener ResourceListener = new ResourceListener(){
    @Override
    public void infoReady(ResourceTask task, long totalLength) {
        //资源信息已经获取完成,即将开始下载
        progressBar.setMax((int) totalLength);
    }
};

# progress(ResourceTask task, long currentOffset, String speed)

  • 参数:ResourceTask task,要下载的资源信息,long currentOffset下载总数量,String speed返回下载速度,如:500kb/s,2M/s。
  • 描述:下载中,每100毫秒回调一次
  • 用法:
ResourceListener ResourceListener = new ResourceListener(){
    @Override
    public void progress(ResourceTask task, long currentOffset, String speed) {
        tvSpeed.setText(speed);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            progressBar.setProgress((int) currentOffset, true);
        } else {
            progressBar.setProgress((int) currentOffset);
        }
    }
};

# taskEnd(ResourceTask task)

  • 参数:ResourceTask task,资源信息。
  • 描述:下载完成回调。
  • 用法:
ResourceListener ResourceListener = new ResourceListener(){
    @Override
    public void taskEnd(ResourceTask task) {
        // 这个task下载完成,处理你的业务
    }
};

# 下载方式

# Downloader.enqueue(ResourceTask task, ResourceListener listener)

  • 描述:单个资源入下载队列。如该资源之前有以下载过,会入队列继续下载。
  • 用法:
Downloader.enqueue(task, listener);

# Downloader.enqueue(ResourceTask[] task, ResourceListener listener)

  • 描述:多个资源入下载队列。如资源之前有以下载过,会入队列继续下载。
  • 注意:多个资源会触发多个ResourceListener回调,可以回调中的ResourceTask来确定是哪个ResourceListener
  • 用法:
Downloader.enqueue(tasks, new new ResourceListener(){
    @Override
    public void progress(ResourceTask task, long currentOffset, String speed) {
        // 可以从task.getResNo()来获取这是哪个task的回调
    }
});

# Downloader.cancel(ResourceTask task)

  • 描述:单个资源暂停下载
  • 用法:
    Downloader.cancel(task);

# Downloader.cancel(ResourceTask[] tasks)

  • 描述:多个资源暂停下载
  • 用法:
    Downloader.cancel(tasks);

# Downloader.delete(ResourceTask task)

  • 描述:删除资源文件,如果资源正在下载中,将会先暂停下载,再从下载队列清除,最后删除资源文件。
  • 用法:
    Downloader.delete(task);

# Downloader.delete(ResourceTask[] tasks)

  • 描述:删除多个资源文件,如果资源正在下载中,将会先暂停下载,再从下载队列清除,最后删除资源文件。
  • 用法:
    Downloader.delete(tasks);

# Downloader.deleteAll()

  • 描述:删除下载过的所有资源
  • 用法:
    Downloader.deleteAll();

# 获取下载状态

# DownloadStatusUtils.getStatus(ResourceTask task)

  • 描述:获取下载资源的状态。
  • 参数:ResourceTask
  • 返回:DownloadInfo 对象
  • 用法:
    DownloadInfo downloadInfo = DownloadStatusUtils.getStatus(task);
    downloadInfo.getTotalLength(); // 下载总量
    downloadInfo.getCurrentOffset(); // 当前下载量
    downloadInfo.getStatus(); // 下载状态,DownloadInfo.Status

注意点:如果视频比较大,此方法比较耗时。大概是30毫秒左右。 因为HLS(m3u8)协议中,把视频分为很小的片段(大概10秒一个片段),假设你的视频有1小时,大概就会有360个片段 要下载完成一个视频,需要完成360个请求下载。所以在使用此方法时要去扫描360个片段的下载状态来判定视频的下载状态。 如果你有50个视频正在下载,那么会有30*50毫秒的阻塞,所以在多视频下载状态获取的时候,建议放入非主线程。 比如:在RecyclerView组件中,判断每个下载状态来处理业务:

//这里使用了RxJava-1.x来控制主线程和非主线程的切换
public void onBindViewHolder(VH holder, int position) {
    Observable.create((Observable.OnSubscribe<DownloadInfo>) subscriber -> {
                DownloadInfo downloadInfo = DownloadStatusUtils.getStatus(task);
                subscriber.onNext(downloadInfo);
            }).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(new Subscriber<DownloadInfo>() {
                @Override
                public void onCompleted() {

                }

                @Override
                public void onError(Throwable e) {

                }

                @Override
                public void onNext(DownloadInfo downloadInfo) {

                }
            });
}

# 上传

# Uploader.upload(String url, String extNo, File file,Uploader.OnUploadListener listner)

  • 描述:上传一个文件。
  • 参数:
    • url:网校上传地址。
    • extNo:随机生成数。
    • file:要上传的文件
    • listner:上传回调,详见参数说明。
  • 用法:
Uploader.upload(UPLOAD_START_URL, file.getName(), "xxxxx", file, new Uploader.OnUploadListener() {
    @Override
    public void onError(ResourceError error) {

    }

    @Override
    public void onSuccess(String result) {
        Toast.makeText(CourseActivity.this, "上传成功", Toast.LENGTH_LONG).show();
    }

    @Override
    public void progress(double percent) {
        progressBars[0].setProgress((int) (percent * 100));
    }

    @Override
    public boolean isCancelled() {
        return isCancelled;
    }
});

说明:

  1. 使用分片上传。本地会记录上传进度,取消以后继续上传再次调用Uploader.upload会继续上次的进度上传。
  2. isCancelled变量控制取消上传,可以放在控件事件中设置isCancelled = true

# 参数说明

# ResourceDefinition 视频清晰度

public enum ResourceDefinition {
    SHD,  //超清
    HD,   //高清
    SD    //标清
}

# DownloadInfo.Status 下载状态

public enum DownloadInfo.Status {
    PENDING, // 处于队列等待中
    RUNNING, // 正在下载
    COMPLETED, // 下载完成
    IDLE,  // 下载暂停
    NONE // 未找到下载任务
}

# Uploader.OnUploadListener 上传回调

  • onError:错误信息。
  • onSuccess:上传成功result为'true'。
  • progress:上传进度百分比,0~1。
  • isCancelled:是否取消,默认为false。
public interface OnUploadListener {
    void onError(ResourceError error);

    void onSuccess(String result);

    void progress(double percent);

    default boolean isCancelled() {
        return false;
    }
}

# ResourceError 错误信息

public class ResourceError {
    int    code;
    String message;
    String traceId;
}