前言
- 在android应用开发中经常会遇到应用升级和下载第三方应用的需求。
- 这篇博客介绍了关于下apk获取写入权限问题。和7.0以及7.0以上版本的手机读取不到apk而无法安装的问题。
- 该下载方式适应各种版本,处理了一系列遇到的问题。
正文
Activity类
/** * * 这demo有两个地方比较重要 * 1,下载apk的地址,这里决定了6.0和以上的额版本是否需要使用动态写入权限。 * 2,在DownloadManagerUtil类里面的StrictMode的使用。这将决定7.0以及7.0以上的系统是否能读取到apk文件并启动安装。 */ public class MainActivity extends Activity { private String url = "http://p.gdown.baidu.com/2c94946f0e26ae462034226fde89692a269f6bdf2aa6e9c8767d772124c9f7c7d260e6931fef78f570c881e16b38ef5c2078652c803b022fe844fb87d68c894ddbef8a9694a05f1e0ff373231ca712808c4440578d04145cdba6bc15f63a58840b47586cd429087098129921afed1197f1295b0f2cf49ff9250a04c0d4ef1ae92fdb5712c98e32f6be819bd5d37ee48e968923ef76a8cc7fb9742033e72b07c84dd4e14dc8d7931011e1242b1a867296948cf07eaea2a39a3dfd57541fe83eade2e5b448b9ba397e0a84fc90bc2405b969c9634da0803afc6b0464e4a7e333bb0c7072bd418e99312b5457043c33f156a13660aba0be6f15";//较小的apk文件 private String url2 = "http://mhhy.dl.gxpan.cn/apk/ml/MBGYD092101/Gardenscapes-ledou-MBGYD092101.apk";//梦幻花园游戏包体较大,可以很好的查看下载效果 private String title = "应用宝";//这里可以写应用名 private String desc = "大量优质应用,尽在应用宝。";//这里填写一些对应用的介绍 long downloadId = 0; DownloadManagerUtil downloadManagerUtil; private boolean isRegisterReceiver; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); PublicUtile.getInstance().setmActivity(this); setReceiver(); RelativeLayout rlParentContainer = new RelativeLayout(this.getApplicationContext()); setContentView(rlParentContainer); RelativeLayout.LayoutParams rlp_tv = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT); rlp_tv.addRule(RelativeLayout.CENTER_HORIZONTAL); TextView tv = new TextView(this.getApplicationContext()); tv.setText("DownLoadManager Test"); rlParentContainer.addView(tv, rlp_tv); RelativeLayout.LayoutParams rlp_button = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT); rlp_button.addRule(RelativeLayout.CENTER_IN_PARENT); Button download = new Button(this.getApplicationContext()); download.setText("开始下载..."); rlParentContainer.addView(download, rlp_button); downloadManagerUtil = new DownloadManagerUtil(this); download.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { //调起系统下载功能 if (downloadId != 0) { downloadManagerUtil.clearCurrentTask(downloadId); } downloadId = downloadManagerUtil.download(url, title, desc); } }); } /** * 注册下载成功的广播监听 */ private void setReceiver() { if (!isRegisterReceiver) { DownloadReceiver receiver = new DownloadReceiver(); IntentFilter intentFilter = new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE); this.registerReceiver(receiver, intentFilter); isRegisterReceiver = true; } }}
/** * Created by lenovo on 2018/6/17. * 下载成功广播类 */ public class DownloadReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { if (intent.getAction().equals(DownloadManager.ACTION_DOWNLOAD_COMPLETE)) { long id = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1); installApk(context, id, PublicUtile.getApkDownPath(context) + PublicUtile.TestApkName); } else if (intent.getAction().equals(DownloadManager.ACTION_NOTIFICATION_CLICKED)) { //处理 如果还未完成下载,用户点击Notification ,跳转到下载中心 Intent viewDownloadIntent = new Intent(DownloadManager.ACTION_VIEW_DOWNLOADS); viewDownloadIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); context.startActivity(viewDownloadIntent); } } /** * 启动安装 * * @param context * @param downloadApkId * @param apkPath */ private static void installApk(Context context, long downloadApkId, String apkPath) { DownloadManager dManager = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE); Intent install = new Intent(Intent.ACTION_VIEW); Uri downloadFileUri = dManager.getUriForDownloadedFile(downloadApkId); if (downloadFileUri != null) { Log.e("DownloadManager", downloadFileUri.toString()); install.setDataAndType(Uri.parse("file://" + apkPath), "application/vnd.android.package-archive"); install.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); context.startActivity(install); } else { Log.e("DownloadManager", "download error"); } } }
/** * Created by lenovo on 2018/6/17. * 下载类 */ public class DownloadManagerUtil { private Context mContext; public DownloadManagerUtil(Context context) { mContext = context; } // //简单的下载功能 // public long download(String url, String title, String desc) { // Uri uri = Uri.parse(url); // DownloadManager.Request req = new DownloadManager.Request(uri); // //设置WIFI下进行更新 // req.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI); // //下载中和下载完后都显示通知栏 // req.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED); // //使用系统默认的下载路径 此处为应用内 /android/data/packages ,所以兼容7.0 // req.setDestinationInExternalFilesDir(mContext, Environment.DIRECTORY_DOWNLOADS, title); // //通知栏标题 // req.setTitle(title); // //通知栏描述信息 // req.setDescription(desc); // //设置类型为.apk // req.setMimeType("application/vnd.android.package-archive"); // //获取下载任务ID // DownloadManager dm = (DownloadManager) mContext.getSystemService(Context.DOWNLOAD_SERVICE); // return dm.enqueue(req); // } /** * 比较实用的升级版下载功能 * * @param url 下载地址 * @param title 文件名字 * @param desc 文件路径 */ public long download(String url, String title, String desc) { DownloadManager downloadManager = (DownloadManager) mContext.getSystemService(Context.DOWNLOAD_SERVICE); long ID; //以下两行代码可以让下载的apk文件被直接安装而不用使用Fileprovider,系统7.0或者以上才启动。 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { StrictMode.VmPolicy.Builder localBuilder = new StrictMode.VmPolicy.Builder(); StrictMode.setVmPolicy(localBuilder.build()); } DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url)); // 仅允许在WIFI连接情况下下载 // request.setAllowedNetworkTypes(Request.NETWORK_WIFI); // 通知栏中将出现的内容 request.setTitle(title); request.setDescription(desc); //7.0以上的系统适配 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { request.setRequiresDeviceIdle(false); request.setRequiresCharging(false); } //制定下载的文件类型为APK request.setMimeType("application/vnd.android.package-archive"); // 下载过程和下载完成后通知栏有通知消息。 request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE | DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED); // 指定下载文件地址,使用这个指定地址可不需要WRITE_EXTERNAL_STORAGE权限。 request.setDestinationUri(Uri.fromFile(new File(PublicUtile.getApkDownPath(mContext) + PublicUtile.TestApkName))); //大于11版本手机允许扫描 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { //表示允许MediaScanner扫描到这个文件,默认不允许。 request.allowScanningByMediaScanner(); } Activity activity = PublicUtile.getInstance().getmActivity(); if (activity != null) { activity.startActivity(new android.content.Intent(DownloadManager.ACTION_VIEW_DOWNLOADS));//启动系统下载界面 } ID = downloadManager.enqueue(request); return ID; } /** * 下载前先移除前一个任务,防止重复下载 * * @param downloadId */ public void clearCurrentTask(long downloadId) { DownloadManager dm = (DownloadManager) mContext.getSystemService(Context.DOWNLOAD_SERVICE); try { dm.remove(downloadId); } catch (IllegalArgumentException ex) { ex.printStackTrace(); } } }具体的完整实现方式在Demo里面,以上为重要代码。
最后如果有更好的实现方式或者有其他问题,欢迎在评论区留言交流。