利用系统downloadmanger实现下载更新,同时显示下载进度,不使用service。
android7.0之后,谷歌加强了权限控制,用原来的安装apk的方法会有异常。系统推荐使用fileprovider。修改方式如下:
<1>.在清单文件中注册
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="${applicationId}.provider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/provider_paths"/>
</provider>
<2>在res目录下创建xml目录,在xml目录中添加provider_paths文件
<?xml version="1.0" encoding="utf-8"?>
<paths>
<external-path name="download" path="" />
</paths>
<3>使用fileprovider。具体使用请看下面installApkByGuide方法。
思路:
1.先确定是否要更新
2.需要更新时获取安装包信息如大小版本号下载地址
3.代码中用的DownloadProgressDialog在上一篇文章
4.文章中的自定义弹窗CustomDialog在下一篇文章
具体实现:
1.首先添加联网和存储卡权限
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.INTERNET"/>
2.代码实现
public class MainActivity extends AppCompatActivity {
private DownloadManager mDownloadManager;
//下载ID
private long mDownloadId;
//下载进度弹窗
private DownloadProgressDialog progressDialog;
//文件名
private String mApkName;
private final QueryRunnable mQueryProgressRunnable = new QueryRunnable();
private final Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
if (msg.what == 1001) {
if (progressDialog != null) {
progressDialog.setProgress(msg.arg1);
progressDialog.setMax(msg.arg2);
}
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initReceiver();
if (isNeedUpdate())
DownloadApkInfo apkInfo = getDownloadApkInfo();
if(apkInfo!=null) {
startUpDate(apkInfo);
}
}
}
//初始化广播接收者
private void initReceiver(){
IntentFilter downloadCompleteFilter = new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE);
registerReceiver(mDownloadCompleteReceiver, downloadCompleteFilter);
IntentFilter downloadDetailsFilter = new IntentFilter(DownloadManager.ACTION_NOTIFICATION_CLICKED);
registerReceiver(mDownloadDetailsReceiver, downloadDetailsFilter);
}
//是否需要下载更新
private boolean isNeedUpdate() {
return true;
}
//获取安装包信息
private DownloadApkInfo getDownloadApkInfo(){
DownloadApkInfo downloadApkInfo=new DownloadApkInfo();
downloadApkInfo.setDownloadUrl("http://www.xxx.com/downloadmangedemo.apk");
downloadApkInfo.setDescription("修复若干不可描述bug");
downloadApkInfo.setDownloadSize(16.3f);
downloadApkInfo.setVersionName("2.02");
return downloadApkInfo;
}
//开始更新
private void startUpDate(final DownloadApkInfo apkInfo) {
mDownloadManager = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
TipsUtils.showDialog(this, "发现新版本",
apkInfo.getDescription(),
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
startDownloadApk(apkInfo);
}
}, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
stopQuery();
finish();
}
}, "立即下载", "取消", false);
}
//开始下载apk文件
private void startDownloadApk(DownloadApkInfo apkInfo) {
mApkName= "DownloadManagerDemo" + "_v" + apkInfo.getVersionName() + ".apk";
DownloadManager.Request request = new DownloadManager.Request(
Uri.parse(apkInfo.getDownloadUrl()));
request.setAllowedNetworkTypes(
DownloadManager.Request.NETWORK_MOBILE
| DownloadManager.Request.NETWORK_WIFI)
.setTitle("DownloadManagerDemo" + "_v" + apkInfo.getVersionName() + ".apk") // 用于信息查看
.setDescription("新版本升级") // 用于信息查看
.setDestinationInExternalPublicDir(
Environment.DIRECTORY_DOWNLOADS,
mApkName);
try {
mDownloadId = mDownloadManager.enqueue(request); // 加入下载队列
startQuery();
} catch (IllegalArgumentException e) {
TipsUtils.showDialog(MainActivity.this,
"更新失败", "请在设置中开启下载管理",
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
intent.setData(Uri.parse("package:" + "com.android.providers.downloads"));
if (intent.resolveActivity(getPackageManager()) != null) {
startActivity(intent);
}
finish();
}
}, null, "确定", "", false);
}
}
//更新下载进度
private void startQuery() {
if (mDownloadId != 0) {
displayProgressDialog();
mHandler.post(mQueryProgressRunnable);
}
}
//查询下载进度
private class QueryRunnable implements Runnable {
@Override
public void run() {
queryState();
mHandler.postDelayed(mQueryProgressRunnable,100);
}
}
//查询下载进度
private void queryState() {
// 通过ID向下载管理查询下载情况,返回一个cursor
Cursor c = mDownloadManager.query(new DownloadManager.Query().setFilterById(mDownloadId));
if (c == null) {
Toast.makeText(this, "下载失败",Toast.LENGTH_SHORT).show();
finish();
} else { // 以下是从游标中进行信息提取
if (!c.moveToFirst()) {
Toast.makeText(this,"下载失败",Toast.LENGTH_SHORT).show();
finish();
if(!c.isClosed()) {
c.close();
}
return;
}
int mDownload_so_far = c.getInt(c.getColumnIndex(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR));
int mDownload_all = c.getInt(c.getColumnIndex(DownloadManager.COLUMN_TOTAL_SIZE_BYTES));
Message msg=Message.obtain();
if(mDownload_all>0) {
msg.what = 1001;
msg.arg1=mDownload_so_far;
msg.arg2=mDownload_all;
mHandler.sendMessage(msg);
}
if(!c.isClosed()){
c.close();
}
}
}
//停止查询下载进度
private void stopQuery() {
mHandler.removeCallbacks(mQueryProgressRunnable);
}
//下载停止同时删除下载文件
private void removeDownload() {
if(mDownloadManager!=null){
mDownloadManager.remove(mDownloadId);
}
}
//进度对话框
private void displayProgressDialog() {
if (progressDialog == null) {
// 创建ProgressDialog对象
progressDialog = new DownloadProgressDialog(this);
// 设置进度条风格,风格为长形
progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
// 设置ProgressDialog 标题
progressDialog.setTitle("下载提示");
// 设置ProgressDialog 提示信息
progressDialog.setMessage("当前下载进度:");
// 设置ProgressDialog 的进度条是否不明确
progressDialog.setIndeterminate(false);
// 设置ProgressDialog 是否可以按退回按键取消
progressDialog.setCancelable(false);
progressDialog.setProgressDrawable(getResources().getDrawable(R.drawable.download_progressdrawable));
progressDialog.setButton(DialogInterface.BUTTON_NEGATIVE, "取消", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
removeDownload();
dialog.dismiss();
finish();
}
});
}
if (!progressDialog.isShowing()) {
// 让ProgressDialog显示
progressDialog.show();
}
}
// 下载完成监听,下载完成之后自动安装
private final BroadcastReceiver mDownloadCompleteReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (DownloadManager.ACTION_DOWNLOAD_COMPLETE.equals(action)) {
long downloadId = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, 0);
// 查询
DownloadManager.Query query = new DownloadManager.Query();
query.setFilterById(downloadId);
Cursor c = mDownloadManager.query(query);
if (c!=null && c.moveToFirst()) {
int columnIndex = c.getColumnIndex(DownloadManager.COLUMN_STATUS);
if (DownloadManager.STATUS_SUCCESSFUL == c.getInt(columnIndex)) {
String uriString = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getPath()+
File.separator+mApkName;
finish();
installApkByGuide(uriString);
}
}
if(c != null && ! c.isClosed()){
c.close();
}
}
}
};
//安装apk
private void installApkByGuide(String uriString) {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
Uri uri;
if(Build.VERSION.SDK_INT > = 24){
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
uri = FileProvider.getUriForFile(context, context.getPackageName() + ".provider", new File(localFilePath));
}else{
uri=Uri.fromFile(new File(localFilePath));
}
intent.setDataAndType(uri,
"application/vnd.android.package-archive");
context.startActivity(intent);
}
// 通知栏点击事件,点击进入下载详情
private final BroadcastReceiver mDownloadDetailsReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (DownloadManager.ACTION_NOTIFICATION_CLICKED.equals(action)) {
lookDownload();
}
}
};
//进入下载详情
private void lookDownload() {
Intent intent=new Intent(DownloadManager.ACTION_VIEW_DOWNLOADS);
if(intent.resolveActivity(getPackageManager())!=null){
startActivity(intent);
}
}
@Override
protected void onDestroy() {
super.onDestroy();
if(mDownloadCompleteReceiver!=null) {
unregisterReceiver(mDownloadCompleteReceiver);
}
if(mDownloadDetailsReceiver!=null) {
unregisterReceiver(mDownloadDetailsReceiver);
}
}
}
3.DownloadApkInfo
public class DownloadApkInfo {
//下载地址
private String downloadUrl;
//更新内容
private String description;
//apk大小(单位是M)
private float downloadSize;
//显示版本号 如1.01
private String versionName;
public String getDownloadUrl() {
return downloadUrl;
}
public void setDownloadUrl(String downloadUrl) {
this.downloadUrl = downloadUrl;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public float getDownloadSize() {
return downloadSize;
}
public void setDownloadSize(float downloadSize) {
this.downloadSize = downloadSize;
}
public String getVersionName() {
return versionName;
}
public void setVersionName(String versionName) {
this.versionName = versionName;
}
}