每天都会去逛逛GitHub看下,刚刚看到一个DownloadManager写的挺好
https://www.cnblogs.com/zhaoyanjun/p/4591960.html
下载管理:
package com.tc.java.mvvmdagger.ui.activity.download.manager;
import android.app.DownloadManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.database.Cursor;
import android.net.Uri;
import android.os.Environment;
import android.util.Log;
import com.tc.java.mvvmdagger.ui.activity.download.listener.AndroidDownloadManagerListener;
import java.io.File;
import java.math.BigDecimal;
/**
* 下载管理类:只负责下载
*/
public class AndroidDownloadManager {
private DownloadManager downloadManager;
private Context context;
private long downloadId;
private String url;
private String name;
private String path;
private AndroidDownloadManagerListener listener;
public AndroidDownloadManager(Context context, String url) {
this(context, url, getFileNameByUrl(url));
}
public AndroidDownloadManager(Context context, String url, String name) {
this.context = context;
this.url = url;
this.name = name;
}
public AndroidDownloadManager setListener(AndroidDownloadManagerListener listener) {
this.listener = listener;
return this;
}
/**
* 开始下载
*/
public void download() {
DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url));
//移动网络情况下是否允许漫游
request.setAllowedOverRoaming(false);
//在通知栏中显示,默认就是显示的
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE);
request.setTitle(name);
request.setDescription("文件正在下载中......");
request.setVisibleInDownloadsUi(true);
///storage/emulated/0/Android/data/com.example.dell.mvvmdagger/files/Download/mobileqq_android.apk
//设置下载的路径
File file = new File(context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS), name);
request.setDestinationUri(Uri.fromFile(file));
path = file.getAbsolutePath();
//获取DownloadManager
if (downloadManager == null) {
downloadManager = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);
}
//将下载请求加入下载队列,加入下载队列后会给该任务返回一个long型的id,通过该id可以取消任务,重启任务、获取下载的文件等等
if (downloadManager != null) {
if (listener != null) {
listener.onPrepare();
}
downloadId = downloadManager.enqueue(request);
}
//IntentFilter filter=new IntentFilter();
//filter.addAction("downloadAction");
//注册广播接收者,监听下载状态
//context.registerReceiver(receiver,filter);
checkStatus();
}
private void checkStatus(){
boolean isRuning=true;
Intent intent=new Intent();
while (isRuning){
DownloadManager.Query query = new DownloadManager.Query();
//通过下载的id查找
query.setFilterById(downloadId);
Cursor cursor = downloadManager.query(query);
int[] bytesAndStatus = new int[]{
-1, -1, 0
};
if (cursor != null && cursor.moveToFirst()) {
int status = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS));
switch (status) {
//下载暂停
case DownloadManager.STATUS_PAUSED:
break;
//下载延迟
case DownloadManager.STATUS_PENDING:
break;
//正在下载
case DownloadManager.STATUS_RUNNING:
Log.i("gdchent", "下载中");
//已经下载文件大小
bytesAndStatus[0] = cursor.getInt(cursor.getColumnIndexOrThrow(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR));
//下载文件的总大小
bytesAndStatus[1] = cursor.getInt(cursor.getColumnIndexOrThrow(DownloadManager.COLUMN_TOTAL_SIZE_BYTES));
//下载状态
bytesAndStatus[2] = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS));
Log.i("gdchent", "下载文件的进度" + String.valueOf(bytesAndStatus[0]));
// intent.putExtra("data",bytesAndStatus[0]/bytesAndStatus[1]);
// intent.setAction("downloadAction");
// context.sendBroadcast(intent);
double dProgress=deciMal(bytesAndStatus[0],bytesAndStatus[1]);
if(listener!=null){
listener.onDownLoading((int) (dProgress*100));
}
break;
//下载完成
case DownloadManager.STATUS_SUCCESSFUL:
if (listener != null) {
listener.onSuccess(path);
}
cursor.close();
//context.unregisterReceiver(receiver);
isRuning=false ;
break;
//下载失败
case DownloadManager.STATUS_FAILED:
if (listener != null) {
listener.onFailed(new Exception("下载失败"));
}
cursor.close();
//context.unregisterReceiver(receiver);
isRuning=false ;
break;
}
} else {
Log.i("gdchent", "走这里");
}
}
}
//广播监听下载的各个状态
// private BroadcastReceiver receiver = new BroadcastReceiver() {
// @Override
// public void onReceive(Context context, Intent intent) {
// Log.i("gdchent","onReceiver");
// int num=intent.getIntExtra("data",-1);
// Log.i("gdchent","num:"+String.valueOf(num));
// }
// };
public String getName() {
return name;
}
/**
* 通过URL获取文件名
*
* @param url
* @return
*/
private static final String getFileNameByUrl(String url) {
String filename = url.substring(url.lastIndexOf("/") + 1);
filename = filename.substring(0, filename.indexOf("?") == -1 ? filename.length() : filename.indexOf("?"));
return filename;
}
private double deciMal(int top, int below) {
double result = new BigDecimal((float) top / below).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
Log.i("返回的两位数", result + "'");
return result;
}
}
下载进度监听接口
package com.tc.java.mvvmdagger.ui.activity.download.listener;
/**
* 下载监听
*/
public interface AndroidDownloadManagerListener {
void onPrepare() ;//准备
void onDownLoading(int progress);
void onSuccess(String path) ; //下载成功
void onFailed(Throwable throwable) ;//下载失败
}
下载的Activity示例:
package com.tc.java.mvvmdagger.ui.activity.download;
import android.content.Intent;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
import android.support.v4.content.FileProvider;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Toast;
import com.tc.java.mvvmdagger.BR;
import com.tc.java.mvvmdagger.R;
import com.tc.java.mvvmdagger.databinding.ActivityDownLoadManagerBinding;
import com.tc.java.mvvmdagger.rxjava.ComposerObserveable;
import com.tc.java.mvvmdagger.ui.activity.base.MvvmActivity;
import com.tc.java.mvvmdagger.ui.activity.download.listener.AndroidDownloadManagerListener;
import com.tc.java.mvvmdagger.ui.activity.download.manager.AndroidDownloadManager;
import com.tc.java.mvvmdagger.viewmodel.download.DownLoadManagerViewModel;
import com.trello.rxlifecycle2.components.support.RxAppCompatActivity;
import java.io.File;
import java.io.IOException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import io.reactivex.Observable;
import io.reactivex.ObservableEmitter;
import io.reactivex.ObservableOnSubscribe;
import io.reactivex.functions.Consumer;
public class DownLoadManagerActivity extends MvvmActivity {
private String apkUrl = "https://qd.myapp.com/myapp/qqteam/AndroidQQ/mobileqq_android.apk";
private AndroidDownloadManager androidDownloadManager;
private ExecutorService fixedThreadPool;
public DownLoadManagerActivity() {
super(R.layout.activity_down_load_manager, new int[]{
R.id.tv_down_load
});
}
@Override
protected void init() {
binding.setVariable(BR.vm, VM);
}
@Override
public void onClick(View v) {
super.onClick(v);
switch (v.getId()) {
case R.id.tv_down_load: //点击下载
androidDownloadManager = new AndroidDownloadManager(this, apkUrl)
.setListener(new AndroidDownloadManagerListener() {
@Override
public void onPrepare() {
Log.i("gdchent", "准备下载");
}
@Override
public void onSuccess(String path) {
Log.i("gdchent", "下载成功" + path);
installAPK(path);
}
@Override
public void onDownLoading(int progress) {
Log.i("gdchent","p:"+progress);
showProgress(progress);
}
@Override
public void onFailed(Throwable throwable) {
Log.i("gdchent", "faired" + throwable.getMessage());
}
});
//创建一个可重用固定个数的线程池
fixedThreadPool = Executors.newFixedThreadPool(3);
Thread thread=new Thread(new Runnable() {
@Override
public void run() {
Log.i("gdchent","线程池执行");
androidDownloadManager.download();
}
});
// thread.start();
fixedThreadPool.execute(thread);
break;
}
}
private void showProgress(int progress){
ComposerObserveable composerObserveable=new ComposerObserveable();
composerObserveable.wrapper((RxAppCompatActivity) context,Observable.just(progress))
.subscribe(new Consumer() {
@Override
public void accept(Object result) throws Exception {
binding.progressHorizontal.setProgress((Integer) result);
binding.tvProgress.setText("下载进度:"+result);
}
});
}
//安装apk
private void installAPK(String pathstr) {
setPermission(pathstr);
Intent intent = new Intent(Intent.ACTION_VIEW);
// 由于没有在Activity环境下启动Activity,设置下面的标签
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
//Android 7.0以上要使用FileProvider
if (Build.VERSION.SDK_INT >= 24) {
File file = (new File(pathstr));
//参数1 上下文, 参数2 Provider主机地址 和配置文件中保持一致 参数3 共享的文件
Uri apkUri = FileProvider.getUriForFile(context, getPackageName() + ".fileprovider", file);
//添加这一句表示对目标应用临时授权该Uri所代表的文件
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.setDataAndType(apkUri, "application/vnd.android.package-archive");
} else {
//new File(Environment.DIRECTORY_DOWNLOADS, androidDownloadManager.getName())
String fileName = androidDownloadManager.getName();
File file = new File(context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS), fileName);
intent.setDataAndType(Uri.fromFile(file), "application/vnd.android.package-archive");
}
startActivity(intent);
}
//修改文件权限
private void setPermission(String absolutePath) {
String command = "chmod " + "777" + " " + absolutePath;
Runtime runtime = Runtime.getRuntime();
try {
runtime.exec(command);
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
protected void onDestroy() {
super.onDestroy();
//关闭线程池
fixedThreadPool.shutdown();
}
}
要在AndroidManifest.xml文件中配置:
然后在res下新建xml的目录下新建filepath.xml文件: