先看一下效果,有点问题是进度更新不够连续,通过query得到到的进度就这个屎样,几乎是按一秒一秒变的,我设置轮询的时间间隔是500毫秒,但是不顶用,跟1秒的效果一样:
说多了都是泪,话都在代码里。
public class DownloadActivity extends AppCompatActivity implements View.OnClickListener {
private static final String TAG = "DownloadActivity";
private static final String PACKAGE_URL = "http://gdown.baidu.com/data/wisegame/8d5889f722f640c8/weixin_800.apk";
private long mDownloadId;
private DownloadManager manager;
private DownloadManager.Request request;
private boolean isCompleted;
private ProgressDialog mProgressDialog;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_download);
initView();
}
private void initView() {
// 下载请求对象
request = new DownloadManager.Request(Uri.parse(PACKAGE_URL))
.setAllowedOverRoaming(false)//漫游网络是否可以下载
.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI)//仅在wifi下执行下载
.setNotificationVisibility(DownloadManager.Request.VISIBILITY_HIDDEN)//通知栏隐藏(默认可见)
.setVisibleInDownloadsUi(true)//下载时可见(默认可见)
.setDestinationInExternalPublicDir("/download/", "WeChart.apk");//设置下载路径,在Download文件夹下
manager = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
mProgressDialog = getProgressDialog();
Button downloadButton = (Button) findViewById(R.id.download_button);
downloadButton.setOnClickListener(this);
}
@Override
public void onClick(View v) {
//执行下载任务,反馈downloadId
mDownloadId = manager.enqueue(request);
//使用RxJava对下载信息进行轮询,500毫秒一次
Observable.interval(300, 500, TimeUnit.MILLISECONDS)
.takeUntil(new Func1<Long, Boolean>() {
@Override
public Boolean call(Long aLong) {
return isCompleted;
}
})
.subscribeOn(AndroidSchedulers.mainThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Action1<Long>() {
@Override
public void call(Long aLong) {
checkDownloadStatus();
}
});
}
private void checkDownloadStatus() {
DownloadManager.Query query = new DownloadManager.Query();
query.setFilterById(mDownloadId);//筛选下载任务,传入任务ID,可变参数
Cursor cursor = manager.query(query);
if (cursor.moveToFirst()) {
long downloadedBytes = cursor.getLong(
cursor.getColumnIndexOrThrow(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR));
long totalBytes = cursor.getLong(
cursor.getColumnIndexOrThrow(DownloadManager.COLUMN_TOTAL_SIZE_BYTES));
mProgressDialog.setMax(((int) (totalBytes / 1024)));
int status = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS));
switch (status) {
case DownloadManager.STATUS_RUNNING:
mProgressDialog.setProgress(((int) (downloadedBytes / 1024)));
if(!mProgressDialog.isShowing()){
mProgressDialog.show();
}
break;
case DownloadManager.STATUS_SUCCESSFUL:
isCompleted = true;
if(mProgressDialog.isShowing()){
mProgressDialog.dismiss();
}
break;
}
}
cursor.close();
}
private ProgressDialog getProgressDialog() {
ProgressDialog progressDialog = new ProgressDialog(this);
progressDialog.setProgressNumberFormat("%1d KB/%2d KB");
progressDialog.setMessage("正在更新...");
progressDialog.setIndeterminate(false);
progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
progressDialog.setCancelable(true);
return progressDialog;
}
}
记得在清单文件声明权限,最后一条在通知栏不显示进度要用到:
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.DOWNLOAD_WITHOUT_NOTIFICATION" />
Rxjava真是好东西,如此轻易就实现了轮询,在这里替代了ContentObserver或ScheduledExecutorService,省去了Handler直接实现了对下载进度的监听和ProgressDialog的更新。