参考博客:http://blog.csdn.net/u013277740/article/details/51737080
最近做用DownloadManager进行自更新升级,下载安装时!发现6.0以上的系统有的机型,下载完成后,无法自动安装,
原来是这么写的,也没注意过:
// 通过Intent安装APK文件
Intent intents = new Intent();
intents.setAction(Intent.ACTION_DEFAULT);
intents.addCategory(Intent.CATEGORY_DEFAULT);
intents.setDataAndType(uri, "application/vnd.android.package-archive");
intents.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intents);
但是最近6.0有些系统安装不了,发现是这句话里的uri问题,
intents.setDataAndType(uri, "application/vnd.android.package-archive");
以前这个uri是通过DownloadManager里面的getUriForDownloadedFile(longid)获取的!而现在上面的这行代码没有获取uri对应的文件的真实路径,没能成功解析这个uri(具体原因,感兴趣的童鞋,可以去看源码!)所以现在我现在换成下面的写法:
Intent intent = new Intent(); intent.setAction(Intent.ACTION_DEFAULT); intent.addCategory(Intent.CATEGORY_DEFAULT); File apkFile = queryDownloadedApk(); if(apkFile.exists()){ intent.setDataAndType(Uri.fromFile(apkFile), "application/vnd.android.package-archive"); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); startActivity(intent);
}
通过queryDownloadedApk()获取真实文件,然后再生成uri = Uri.fromFile(apkFile);
public File queryDownloadedApk() { File targetApkFile = null; if (downloadId != -1) { DownloadManager.Query query = new DownloadManager.Query(); query.setFilterById(downloadId); query.setFilterByStatus(DownloadManager.STATUS_SUCCESSFUL); Cursor cur = downloadManager.query(query); if (cur != null) { if (cur.moveToFirst()) { String uriString = cur.getString(cur.getColumnIndex(DownloadManager.COLUMN_LOCAL_URI)); if (!OdyUtil.isEmpty(uriString)) { targetApkFile = new File(Uri.parse(uriString).getPath()); } } cur.close(); } } return targetApkFile; }
当然也可以通过下面的方法getRealFilePath(final Context context, final Uri uri)正确解析DownloadManager里面的getUriForDownloadedFile(long id)获取的uri 然后再放入intents.setDataAndType()方法中:
public String getRealFilePath(final Context context, final Uri uri) { if (null == uri) return null; final String scheme = uri.getScheme(); String data = null; if (scheme == null) data = uri.getPath(); else if (ContentResolver.SCHEME_FILE.equals(scheme)) { data = uri.getPath(); } else if (ContentResolver.SCHEME_CONTENT.equals(scheme)) { Cursor cursor = context.getContentResolver().query(uri, new String[]{MediaStore.Images.ImageColumns.DATA}, null, null, null); if (null != cursor) { if (cursor.moveToFirst()) { int index = cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA); if (index > -1) { data = cursor.getString(index); } } cursor.close(); } } return data; }
下面代码是一个简单的防止重复下载判断:
private boolean isNeedDownloadAgain() { boolean isNeedDownloadAgain = true; DownloadManager.Query query = new DownloadManager.Query(); downloadManager = (DownloadManager) getSystemService(Context.DOWNLOAD_SERVICE); long id = ServiceProviderApplication.getValueByKey("serviceProviderDownloadManagerId", -1L); // Toast.makeText(getApplicationContext(), "id..."+id, Toast.LENGTH_SHORT).show(); if (id != -1) { query.setFilterById(id); Cursor cursor = downloadManager.query(query); if (cursor != null && cursor.moveToFirst()) { int columnIndex = cursor.getColumnIndex(DownloadManager.COLUMN_STATUS); int status = cursor.getInt(columnIndex); int columnReason = cursor.getColumnIndex(DownloadManager.COLUMN_REASON); int reason = cursor.getInt(columnReason); switch (status) { case DownloadManager.STATUS_FAILED: switch (reason) { case DownloadManager.ERROR_CANNOT_RESUME: //some possibly transient error occurred but we can't resume the download break; case DownloadManager.ERROR_DEVICE_NOT_FOUND: //no external storage device was found. Typically, this is because the SD card is not mounted break; case DownloadManager.ERROR_FILE_ALREADY_EXISTS: //the requested destination file already exists (the download manager will not overwrite an existing file) break; case DownloadManager.ERROR_FILE_ERROR: //a storage issue arises which doesn't fit under any other error code break; case DownloadManager.ERROR_HTTP_DATA_ERROR: //an error receiving or processing data occurred at the HTTP level break; case DownloadManager.ERROR_INSUFFICIENT_SPACE://sd卡满了 //here was insufficient storage space. Typically, this is because the SD card is full break; case DownloadManager.ERROR_TOO_MANY_REDIRECTS: //there were too many redirects break; case DownloadManager.ERROR_UNHANDLED_HTTP_CODE: //an HTTP code was received that download manager can't handle break; case DownloadManager.ERROR_UNKNOWN: //he download has completed with an error that doesn't fit under any other error code break; } isNeedDownloadAgain = true; break; case DownloadManager.STATUS_PAUSED: switch (reason) { case DownloadManager.PAUSED_QUEUED_FOR_WIFI: //the download exceeds a size limit for downloads over the mobile network and the download manager is waiting for a Wi-Fi connection to proceed break; case DownloadManager.PAUSED_UNKNOWN: //the download is paused for some other reason break; case DownloadManager.PAUSED_WAITING_FOR_NETWORK: //the download is waiting for network connectivity to proceed break; case DownloadManager.PAUSED_WAITING_TO_RETRY: //the download is paused because some network error occurred and the download manager is waiting before retrying the request break; } isNeedDownloadAgain = false; break; case DownloadManager.STATUS_PENDING: isNeedDownloadAgain = false; // Toast.makeText(getApplicationContext(), "STATUS_PENDING...", Toast.LENGTH_SHORT).show(); break; case DownloadManager.STATUS_RUNNING: Toast.makeText(getApplicationContext(), "正在下载...", Toast.LENGTH_SHORT).show(); isNeedDownloadAgain = false; break; case DownloadManager.STATUS_SUCCESSFUL: //the download has successfully completed isNeedDownloadAgain = true; // isNeedDownloadAgain = false; // installApk(id, downloadManager, mContext); break; } } } return isNeedDownloadAgain; }
public class ApplicationUpdateService extends Service { private String path = "http://gdown.baidu.com/data/wisegame/91319a5a1dfae322/baidu_16785426.apk"; /** * 安卓系统下载类 **/ private DownloadManager downloadManager; private long downloadId; /** * 接收下载完的广播 **/ DownloadCompleteReceiver receiver; /** * 初始化下载器 **/ private void initDownManager(String url) { // downloadManager = (DownloadManager) getSystemService(DOWNLOAD_SERVICE); receiver = new DownloadCompleteReceiver(); //设置下载地址 DownloadManager.Request request = new DownloadManager.Request( Uri.parse(url)); Log.v("url:", url); // 设置允许使用的网络类型,这里是移动网络和wifi都可以 request.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_MOBILE | DownloadManager.Request.NETWORK_WIFI); request.setMimeType("application/vnd.android.package-archive"); // 下载时,通知栏显示途中 request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE); // 显示下载界面 request.setVisibleInDownloadsUi(true); // 设置下载后文件存放的位置 request.setDestinationInExternalFilesDir(this, Environment.DIRECTORY_DOWNLOADS, getPackageName()); // request.setTitle(getApplicationContext().getResources().getString(R.string.app_name)); request.setDescription("新版本更新"); // 将下载请求放入队列 downloadId = downloadManager.enqueue(request); ServiceProviderApplication.putValueByKey("serviceProviderDownloadManagerId", downloadId); //注册下载广播 registerReceiver(receiver, new IntentFilter( DownloadManager.ACTION_DOWNLOAD_COMPLETE)); } @Override public int onStartCommand(Intent intent, int flags, int startId) {
//url是传过来的下载路径,如果想直接用,可以用上面的百度apk地址path代替 String url = intent.getStringExtra("url"); if (url != null && !"".equals(url)) { if (isNeedDownloadAgain()) { Toast.makeText(getApplicationContext(), "开始下载...", Toast.LENGTH_SHORT).show(); // 调用下载 initDownManager(url); } } return Service.START_REDELIVER_INTENT; } @Override public void onCreate() { super.onCreate(); } @Override public IBinder onBind(Intent intent) { return null; } @Override public void onDestroy() { // 注销下载广播 if (receiver != null) unregisterReceiver(receiver); super.onDestroy(); } private boolean isNeedDownloadAgain() { boolean isNeedDownloadAgain = true; DownloadManager.Query query = new DownloadManager.Query(); downloadManager = (DownloadManager) getSystemService(Context.DOWNLOAD_SERVICE); long id = ServiceProviderApplication.getValueByKey("serviceProviderDownloadManagerId", -1L); // Toast.makeText(getApplicationContext(), "id..."+id, Toast.LENGTH_SHORT).show(); if (id != -1) { query.setFilterById(id); Cursor cursor = downloadManager.query(query); if (cursor != null && cursor.moveToFirst()) { int columnIndex = cursor.getColumnIndex(DownloadManager.COLUMN_STATUS); int status = cursor.getInt(columnIndex); int columnReason = cursor.getColumnIndex(DownloadManager.COLUMN_REASON); int reason = cursor.getInt(columnReason); switch (status) { case DownloadManager.STATUS_FAILED: switch (reason) { case DownloadManager.ERROR_CANNOT_RESUME: //some possibly transient error occurred but we can't resume the download break; case DownloadManager.ERROR_DEVICE_NOT_FOUND: //no external storage device was found. Typically, this is because the SD card is not mounted break; case DownloadManager.ERROR_FILE_ALREADY_EXISTS: //the requested destination file already exists (the download manager will not overwrite an existing file) break; case DownloadManager.ERROR_FILE_ERROR: //a storage issue arises which doesn't fit under any other error code break; case DownloadManager.ERROR_HTTP_DATA_ERROR: //an error receiving or processing data occurred at the HTTP level break; case DownloadManager.ERROR_INSUFFICIENT_SPACE://sd卡满了 //here was insufficient storage space. Typically, this is because the SD card is full break; case DownloadManager.ERROR_TOO_MANY_REDIRECTS: //there were too many redirects break; case DownloadManager.ERROR_UNHANDLED_HTTP_CODE: //an HTTP code was received that download manager can't handle break; case DownloadManager.ERROR_UNKNOWN: //he download has completed with an error that doesn't fit under any other error code break; } isNeedDownloadAgain = true; break; case DownloadManager.STATUS_PAUSED: switch (reason) { case DownloadManager.PAUSED_QUEUED_FOR_WIFI: //the download exceeds a size limit for downloads over the mobile network and the download manager is waiting for a Wi-Fi connection to proceed break; case DownloadManager.PAUSED_UNKNOWN: //the download is paused for some other reason break; case DownloadManager.PAUSED_WAITING_FOR_NETWORK: //the download is waiting for network connectivity to proceed break; case DownloadManager.PAUSED_WAITING_TO_RETRY: //the download is paused because some network error occurred and the download manager is waiting before retrying the request break; } isNeedDownloadAgain = false; break; case DownloadManager.STATUS_PENDING: isNeedDownloadAgain = false; // Toast.makeText(getApplicationContext(), "STATUS_PENDING...", Toast.LENGTH_SHORT).show(); break; case DownloadManager.STATUS_RUNNING: Toast.makeText(getApplicationContext(), "正在下载...", Toast.LENGTH_SHORT).show(); isNeedDownloadAgain = false; break; case DownloadManager.STATUS_SUCCESSFUL: //the download has successfully completed isNeedDownloadAgain = true; // isNeedDownloadAgain = false; // installApk(id, downloadManager, mContext); break; } } } return isNeedDownloadAgain; } // 接受下载完成后的intent class DownloadCompleteReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { //判断是否下载完成的广播 if (intent.getAction().equals( DownloadManager.ACTION_DOWNLOAD_COMPLETE)) { //获取下载的文件id long completeDownloadId = intent.getLongExtra( DownloadManager.EXTRA_DOWNLOAD_ID, -1); Uri uri = downloadManager.getUriForDownloadedFile(completeDownloadId); if (uri != null) { //自动安装apk installAPK(downloadManager.getUriForDownloadedFile(completeDownloadId)); } else { Toast.makeText(getApplicationContext(), "下载失败!", Toast.LENGTH_SHORT).show(); } //停止服务并关闭广播 ApplicationUpdateService.this.stopSelf(); } }
/** * 安装apk文件 */ private void installAPK(Uri apk) { // 通过Intent安装APK文件 Intent intent = new Intent(); intent.setAction(Intent.ACTION_DEFAULT); intent.addCategory(Intent.CATEGORY_DEFAULT); File apkFile = queryDownloadedApk();
// String path = getRealFilePath(getApplicationContext(), apk); // File apkFile = new File(path);if(apkFile.exists()){
intent.setDataAndType(Uri.fromFile(apkFile), "application/vnd.android.package-archive");
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
}else {
OdyUtil.showShortToast("安装文件不存在");
}
}
//解析uri,,获取下载文件真实路径
public String getRealFilePath(final Context context, final Uri uri) { if (null == uri) return null; final String scheme = uri.getScheme(); String data = null; if (scheme == null) data = uri.getPath(); else if (ContentResolver.SCHEME_FILE.equals(scheme)) { data = uri.getPath(); } else if (ContentResolver.SCHEME_CONTENT.equals(scheme)) { Cursor cursor = context.getContentResolver().query(uri, new String[]{MediaStore.Images.ImageColumns.DATA}, null, null, null); if (null != cursor) { if (cursor.moveToFirst()) { int index = cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA); if (index > -1) { data = cursor.getString(index); } } cursor.close(); } } return data; } //获取下载文件 public File queryDownloadedApk() { File targetApkFile = null; if (downloadId != -1) { DownloadManager.Query query = new DownloadManager.Query(); query.setFilterById(downloadId); query.setFilterByStatus(DownloadManager.STATUS_SUCCESSFUL); Cursor cur = downloadManager.query(query); if (cur != null) { if (cur.moveToFirst()) { String uriString = cur.getString(cur.getColumnIndex(DownloadManager.COLUMN_LOCAL_URI)); if (!OdyUtil.isEmpty(uriString)) { targetApkFile = new File(Uri.parse(uriString).getPath()); } } cur.close(); } } return targetApkFile; }
}
}