利用系統(tǒng)downloadmanger實現(xiàn)下載更新讥耗,同時顯示下載進度打厘,不使用service。
android7.0之后秫逝,谷歌加強了權(quán)限控制恕出,用原來的安裝apk的方法會有異常。系統(tǒng)推薦使用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目錄下創(chuàng)建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在下一篇文章
具體實現(xiàn):
1.首先添加聯(lián)網(wǎng)和存儲卡權(quán)限
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.INTERNET"/>
2.代碼實現(xiàn)
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("修復(fù)若干不可描述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, "發(fā)現(xiàn)新版本",
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,
"更新失敗", "請在設(shè)置中開啟下載管理",
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) {
// 創(chuàng)建ProgressDialog對象
progressDialog = new DownloadProgressDialog(this);
// 設(shè)置進度條風格,風格為長形
progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
// 設(shè)置ProgressDialog 標題
progressDialog.setTitle("下載提示");
// 設(shè)置ProgressDialog 提示信息
progressDialog.setMessage("當前下載進度:");
// 設(shè)置ProgressDialog 的進度條是否不明確
progressDialog.setIndeterminate(false);
// 設(shè)置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();
}
}
// 下載完成監(jiān)聽尝胆,下載完成之后自動安裝
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;
//更新內(nèi)容
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;
}
}