Android DownloadManager下载更新及打开apk安装

在使用DownloadManager进行下载的时候遇到了一些问题,虽然大都通过网上找到了答案,但是废了一些时间。

  • DownloadManager下载:

  String DOWNLOAD_PATH = Environment.getExternalStorageDirectory().getAbsolutePath() +
                                    "/Android/data/" + getApplicationContext().getPackageName() + "/files/Download/hospitalManager.apk";
                            File file = new File(DOWNLOAD_PATH);
                            if (file.exists()) {
                                file.delete();
                            }
                            DownloadManager downloadManager;
                            DownloadManager.Request request = new DownloadManager.Request(Uri.parse(BASE_URL + "download"));
                            //设置在什么网络情况下进行下载
                            request.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI | DownloadManager.Request.NETWORK_MOBILE);
                            //设置通知栏标题
                            request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
                            request.setTitle("更新院前管理系统");
                            request.setAllowedOverRoaming(true);
                            //设置文件存放目录
                            request.setDestinationInExternalFilesDir(MainActivity.this, Environment.DIRECTORY_DOWNLOADS, "hospitalManager.apk");
                            downloadManager = (DownloadManager) getSystemService(Context.DOWNLOAD_SERVICE);
                            long enqueue = downloadManager.enqueue(request);
                            SharedPreferences usericonpreferencess = getSharedPreferences("xhx", Context.MODE_PRIVATE);
                            SharedPreferences.Editor edit = usericonpreferencess.edit();
                            edit.putLong("refernece",enqueue);
                            edit.commit();
  • 然后在AndroidManifest.xml里面做一个权限设置:

     <provider
                android:name="android.support.v4.content.FileProvider"
                android:authorities="xhx.hospitalmanagement.fileprovider"
                android:exported="false"
                android:grantUriPermissions="true">
                <meta-data
                    android:name="android.support.FILE_PROVIDER_PATHS"
                    android:resource="@xml/file_paths" />
            </provider>

    属性解释如下:

        authorities:是该项目的包名+provider
        grantUriPermissions:必须是true,表示授予 URI 临时访问权限
        exported:必须是false
        resource:中的@xml/file_paths是我们接下来要在资源文件目录下添加的文件

  • 放在application里面。

  • file_paths.xml:你要在res下面新建一个xm的文件夹再新建这个文件:

    <?xml version="1.0" encoding="utf-8"?>
    
        <paths>
        <external-path path="Android/data/xhx.hospitalmanagement/" name="files_root" />
        <external-path path="." name="external_storage_root" />
        </paths>

    其中:
    files-path代表的根目录: Context.getFilesDir()
    external-path代表的根目录: Environment.getExternalStorageDirectory()
    cache-path代表的根目录: getCacheDir()
    path 代表要共享的目录
    name 只是一个标示,随便取吧 自己看的懂就ok

  • 新建UpdataBroadcastReceiver广播类:

    /**
     * 项目名称: android-HospitalManagment
     * 类描述:广播,接收是否下载完成
     * 创建人:Andministrator
     * 创建时间:
     * 修改人:Andministrator
     * 修改时间:Andministrator
     * 修改备注:
     */
    public class UpdataBroadcastReceiver extends BroadcastReceiver {
    
        @SuppressLint("NewApi")
        public void onReceive(Context context, Intent intent) {
            //判断是否下载完成的广播
            if (intent.getAction().equals(DownloadManager.ACTION_DOWNLOAD_COMPLETE)) {
                long myDwonloadID = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1);
                SharedPreferences usericonpreferencess = context.getSharedPreferences("xhx", Context.MODE_PRIVATE);
                long refernece = usericonpreferencess.getLong("refernece", 0);
                Log.i("iii", refernece + "" + myDwonloadID + "");
                if (refernece != myDwonloadID) {
                    return;
                }
    
                DownloadManager dManager = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);
                Uri downloadFileUri = dManager.getUriForDownloadedFile(myDwonloadID);
                installAPK(context, downloadFileUri);
            }
        }
        private void installAPK(Context context,Uri apk ) {
            if (Build.VERSION.SDK_INT < 23) {
                Intent intents = new Intent();
                intents.setAction("android.intent.action.VIEW");
                intents.addCategory("android.intent.category.DEFAULT");
                intents.setType("application/vnd.android.package-archive");
                intents.setData(apk);
                intents.setDataAndType(apk, "application/vnd.android.package-archive");
                intents.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                context.startActivity(intents);
            } else {
                File file = queryDownloadedApk(context);
                Log.i("file", file+"");
                if (file.exists()) {
                    openFile(file, context);
                }
    
            }
        }
    
        /**
         * 通过downLoadId查询下载的apk,解决6.0以后安装的问题
         * @param context
         * @return
         */
        public static File queryDownloadedApk(Context context) {
            File targetApkFile = null;
            DownloadManager downloader = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);
            SharedPreferences usericonpreferencess = context.getSharedPreferences("xhx", Context.MODE_PRIVATE);
            long downloadId =  usericonpreferencess.getLong("refernece",-1);
            if (downloadId != -1) {
                DownloadManager.Query query = new DownloadManager.Query();
                query.setFilterById(downloadId);
                query.setFilterByStatus(DownloadManager.STATUS_SUCCESSFUL);
                Cursor cur = downloader.query(query);
                if (cur != null) {
                    if (cur.moveToFirst()) {
                        String uriString = cur.getString(cur.getColumnIndex(DownloadManager.COLUMN_LOCAL_URI));
                        if (!TextUtils.isEmpty(uriString)) {
                            targetApkFile = new File(Uri.parse(uriString).getPath());
                        }
                    }
                    cur.close();
                }
            }
            return targetApkFile;
    
        }
    
        private void openFile(File file, Context context) {
            Intent intent = new Intent(Intent.ACTION_VIEW);
            Uri photoURI;
            // 判断版本大于等于7.0
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
                 photoURI = FileProvider.getUriForFile(context, "xhx.hospitalmanagement.fileprovider", file);
                // 给目标应用一个临时授权
                intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
            } else {
                photoURI = Uri.fromFile(file);
            }
            intent.setDataAndType(photoURI, "application/vnd.android.package-archive");
            context.startActivity(intent);
        }
    }

    然后你要记得去AndroidManifest.xml里面去注册:

      <receiver android:name=".Util.UpdataBroadcastReceiver">
                <intent-filter>
                    <action android:name="android.intent.action.DOWNLOAD_COMPLETE" />
                    <!--<action android:name="android.intent.action.PACKAGE_INSTALL" />-->
                </intent-filter>
            </receiver>
    
  • 到这就结束了,这个下载的界面是在状态栏进行的,比较简陋,如果要求UI美观的话自己可以去设置设置,不难。然后说一些遇到的问题:

  1. android.os.FileUriExposedException: file:///storage/emulated.. exposed beyond app through Intent.getData()

  2. 你可能会遇到应用安装不成功的问题,这个有俩点原因:第一是因为你的本地签名也你的更新版本的签名不一样你需要去检查你的签名了。第二是因为在build.gradle文件的配置中,versionCode值变小了。
  3. 千万记住要细心,在权限问题上要看仔细了。

猜你喜欢

转载自blog.csdn.net/Liuxb_zao/article/details/84989511