Android:使用 DownloadManager 进行版本更新
app 以前的版本更新使用的自己写的代码从服务器下载,结果出现了下载完成以后,提示解析包错误的问题,但是呢,找到该 apk 点击安装是可以安装成功的,估计就是最后几秒安装包没有下载完成然后点击了安装出现的解析包错误的问题。目前修改为通过 DownloadManager 进行下载。
代码如下:
1. 判断当前是否可以使用 DownloadManager (根据搜索结果,反馈说有些国产手机会把 DownloadManager 进行阉割掉,目前测试在 Nexus6, 华为Mate9, 小米 Note,华为Mate8, HTC D820U, 三星 S7 上可以使用)
1 private static boolean canDownloadState(Context ctx) { 2 try { 3 int state = ctx.getPackageManager().getApplicationEnabledSetting("com.android.providers.downloads"); 4 5 if (state == PackageManager.COMPONENT_ENABLED_STATE_DISABLED 6 || state == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER 7 || state == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED) { 8 return false; 9 } 10 } catch (Exception e) { 11 e.printStackTrace(); 12 return false; 13 } 14 return true; 15 }
2. 出现可以使用和不可以使用的情况。可以使用的话,就使用 DownloadManager 进行下载,不可以使用就交给浏览器进行下载
1 if (canDownloadState(ctx)) { 2 MLog.d("UpdateVersion", "DownloadManager 可用"); 3 Intent downloadApkIntent = new Intent(ctx, DownApkServer.class); 4 Bundle bundle = new Bundle(); 5 bundle.putString("downloadUrl", url); 6 bundle.putString("title", subAppName); 7 downloadApkIntent.putExtra("download", bundle); 8 ctx.startService(downloadApkIntent); 9 } else { 10 MLog.d("UpdateVersion", "DownloadManager 不可用"); 11 Intent intent = new Intent(); 12 intent.setAction("android.intent.action.VIEW"); 13 Uri content_url = Uri.parse(url); 14 intent.setData(content_url); 15 ctx.startActivity(intent); 16 }
3. 启动 DownApkServer 服务
1 public class DownApkServer extends Service { 2 static final String TAG = "DownApkServer"; 3 Context context = this; 4 SharedPreferences mSp; 5 6 public DownApkServer() { 7 8 } 9 10 @Override 11 public IBinder onBind(Intent intent) { 12 return null; 13 } 14 15 @Override 16 public int onStartCommand(Intent intent, int flags, int startId) { 17 Bundle downloadBundle = intent.getBundleExtra("download"); 18 if (downloadBundle != null) { 19 String downloadUrl = downloadBundle.getString("downloadUrl"); 20 String title = downloadBundle.getString("title"); 21 if (!TextUtils.isEmpty(downloadUrl)) { 22 mSp = context.getSharedPreferences("downloadApk", MODE_PRIVATE); 23 long downloadId = downloadApk(downloadUrl, title); 24 mSp.edit().putLong("downloadId", downloadId).commit(); 25 } 26 } 27 stopSelf(); 28 return super.onStartCommand(intent, flags, startId); 29 } 30 31 32 private long downloadApk(String url, String title) { 33 Uri downloadUri = Uri.parse(url); 34 DownloadManager.Request request = new DownloadManager.Request(downloadUri); 35 String apkName = title + ".apk"; 36 File file = context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS + "/" + apkName); 37 if (file != null && file.exists()) { 38 file.delete(); 39 } 40 request.setDestinationInExternalFilesDir(context, Environment.DIRECTORY_DOWNLOADS, 41 apkName); 42 mSp.edit().putString("apkName", apkName).commit(); 43 request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED); 44 request.setVisibleInDownloadsUi(true); 45 request.setTitle(title); 46 DownloadManager mDownloadManager = (DownloadManager) getSystemService(DOWNLOAD_SERVICE); 47 return mDownloadManager.enqueue(request); 48 } 49 }
4. 注册一个广播,DownApkReceiver
1 public class DownApkReceiver extends BroadcastReceiver { 2 private static final String TAG = "DownApkReceiver"; 3 SharedPreferences mSharedP; 4 DownloadManager mManager; 5 Context ctx; 6 7 @Override 8 public void onReceive(Context context, Intent intent) { 9 ctx = context; 10 if (intent.getAction().equals(DownloadManager.ACTION_DOWNLOAD_COMPLETE)) { 11 long downloadApkId = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1L); 12 mSharedP = context.getSharedPreferences("downloadApk", MODE_PRIVATE); 13 long saveApkId = mSharedP.getLong("downloadId", -1L); 14 if (downloadApkId == saveApkId) { 15 checkDownloadStatus(context, downloadApkId); 16 } 17 } 18 } 19 20 private void checkDownloadStatus(Context context, long downloadId) { 21 mManager = (DownloadManager) context.getSystemService(DOWNLOAD_SERVICE); 22 DownloadManager.Query query = new DownloadManager.Query(); 23 query.setFilterById(downloadId); 24 Cursor cursor = mManager.query(query); 25 if (cursor.moveToFirst()) { 26 int status = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS)); 27 switch (status) { 28 case DownloadManager.STATUS_SUCCESSFUL: 29 installApk(context); 30 break; 31 case DownloadManager.STATUS_FAILED: 32 MLog.d("DownApkReceiver", "下载失败....."); 33 break; 34 case DownloadManager.STATUS_RUNNING: 35 MLog.d("DownApkReceiver", "正在下载....."); 36 break; 37 default: 38 break; 39 } 40 } 41 } 42 43 private void installApk(Context context) { 44 String apkName = mSharedP.getString("apkName", null); 45 if (apkName != null) { 46 MLog.d("DownApkReceiver", "apkName 为" + apkName); 47 File file = context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS + "/" + apkName); 48 if (file != null) { 49 Intent install = new Intent("android.intent.action.VIEW"); 50 Uri downloadFileUri = Uri.fromFile(file); 51 install.setDataAndType(downloadFileUri, "application/vnd.android.package-archive"); 52 install.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 53 context.startActivity(install); 54 } else { 55 MLog.d("DownApkReceiver", "下载失败"); 56 } 57 } else { 58 MLog.d("DownApkReceiver", "apkName 为 null"); 59 } 60 } 61 }
5. 在清单文件中,注册该广播
1 <receiver android:name=".subapps.api.utils.DownApkReceiver"> 2 <intent-filter> 3 <action android:name="android.intent.action.DOWNLOAD_COMPLETE"></action> 4 </intent-filter> 5 </receiver>
直面挑战,躬身入局