美文网首页
下载自动安装apk(android10)

下载自动安装apk(android10)

作者: jiluyixia | 来源:发表于2020-11-12 14:51 被阅读0次

    首先是下载的时候,文件下不下来,加了权限也不行。
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

    需要在AndroidManifest中配置一下
    <application
    ...
    android:requestLegacyExternalStorage="true" // 这样就可以采用原有的存储策略

    参考:https://blog.csdn.net/hgy413/article/details/105902424?utm_medium=distribute.pc_aggpage_search_result.none-task-blog-2allsobaiduend~default-3-105902424.nonecase&utm_term=android%E6%B2%A1%E6%9D%83%E9%99%90%E5%88%9B%E5%BB%BA%E6%96%87%E4%BB%B6&spm=1000.2123.3001.4430

    下载后就是打开apk文件,7.0以上加上FileProvider和file_paths.xml。

    但是依然打不开apk文件。

    此时需要加一个权限<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES"/>

    参考:https://blog.csdn.net/chxc_yy/article/details/81536875

    注意,若代码里已经有了FileProvider和file_paths.xml,比喻,下载图片时也需要。
    此时需要重新为下载apk再来自定义一个FileProvider
    注意android:authorities和android:resource要不一样,区分开
    参考:https://www.pianshen.com/article/7748702374/

    <provider
                android:name="androidx.core.content.FileProvider"
                android:authorities="包名.fileprovider"
                android:exported="false"
                android:grantUriPermissions="true">
                <meta-data
                    android:name="android.support.FILE_PROVIDER_PATHS"
                    android:resource="@xml/file_paths" />
            </provider>
    
            <provider
                android:name="包名.utils.MyFileProvider"
                android:authorities="包名.download.fileprovider"
                android:exported="false"
                android:grantUriPermissions="true">
                <meta-data
                    android:name="android.support.FILE_PROVIDER_PATHS"
                    android:resource="@xml/download_file_paths" />
            </provider>
    

    附上下载安装代码:

    /**
     * 版本控制
     */
    @SuppressWarnings("ALL")
    public class VersionUpdateHelper {
        public static final String TAG = VersionUpdateHelper.class.getSimpleName();
    
        private static final int UPDATE_NOTIFICATION_PROGRESS = 0x1;
        private static final int COMPLETE_DOWNLOAD_APK = 0x2;
        private static final int DOWNLOAD_NOTIFICATION_ID = 0x3;
        private static final int FAILED_DOWNLOAD_APK = 0x4;
        private static final String CURRENT_TIME = "current_time";
        private static final String VERSION_CODE = "version_code";
    
        private Context mContext;
        private NotificationManager notificationManager;
        private NotificationCompat.Builder ntfBuilder;
        private static String sPath;
        private static final String SUFFIX = ".apk";//下载完成后的文件名后缀
        private static final String APP_NAME = "APP_NAME";//app名
    
        private HashMap<String, String> cache = new HashMap<String, String>();//存放路径名和app的名字
    
        private boolean isAutoInstall;//是否自动安装
    
        private static final int PUSH_NOTIFICATION_ID = (0x001);
        private static final String PUSH_CHANNEL_ID = "NOTIFY_ID";
        private static final String PUSH_CHANNEL_NAME = "PUSH_NOTIFY_NAME";
    
        ProgressDialog pd;    //进度条对话框
    
        public VersionUpdateHelper(Context mContext, boolean isAutoInstall) {
            this.mContext = mContext;
            this.isAutoInstall = isAutoInstall;
            getApkPath(mContext);
        }
    
        public static String getApkPath(Context context) {
            if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
                sPath = Environment.getExternalStorageDirectory().getAbsolutePath();
            } else {
                SDCardUtils.StorageList storageList = new SDCardUtils.StorageList(context);
                sPath = storageList.getVolumePaths()[1];
            }
            return sPath + File.separator + context.getString(R.string.app_name)
                    + File.separator + context.getString(R.string.app_name)
                    + SUFFIX;
        }
    
    
        private Handler handler = new DownloadHandler();
    
    
        public void loadVersion(Context mContext,String downloadURL) {
            downloadApk(mContext,downloadURL);
        }
    
    
        /**
         * 下载apk
         *
         * @param url apkUrl
         */
        private void downloadApk(Context mContex, String url) {
            pd = new ProgressDialog(mContex);
            pd.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
            pd.setMessage("正在下载...");
            pd.show();
            pd.setCancelable(false);
    
            Log.e("downloadApk", url);
            AsyncDownLoad asyncDownLoad = new AsyncDownLoad();
            asyncDownLoad.execute(url);
        }
    
        /**
         * 异步下载app任务
         */
        private class AsyncDownLoad extends AsyncTask<String, Integer, Boolean> {
            @Override
            protected Boolean doInBackground(String... params) {
                try {
    
                    URL url = new URL(params[0]);
                    HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                    conn.setConnectTimeout(10000);  // 连接超时时间 毫秒级 10S
                    conn.setReadTimeout(10000); //读取超时时间
                    conn.setRequestMethod("GET"); //请求方式
                    conn.setDoInput(true); //打开输入流
                    conn.connect(); //获取连接
                    long beforeTime = System.currentTimeMillis();
    
                    pd.setProgressNumberFormat("%1d M/%2d M");
                    pd.setMax((int)conn.getContentLength()/1024/1024);
    
                    if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) {
                        //获得网络字节输入流对象
                        InputStream is = conn.getInputStream();
                        long total = conn.getContentLength();
                        String apkName = mContext.getString(R.string.app_name)
                                + SUFFIX;
                        cache.put(APP_NAME, mContext.getString(R.string.app_name));
                        File savePath = new File(sPath + File.separator
                                + mContext.getString(R.string.app_name));
                        if (!savePath.exists())
                            savePath.mkdirs();
                        File apkFile = new File(savePath, apkName);
                        //如果文件已经存在,或者已经下载完成了,就不做下载操作
                        Log.v("ver","apkFile.exists()=="+apkFile.exists());
                        /*if (apkFile.exists() && apkFile.length() == total) {
                            return true;
                        }*/
                        FileOutputStream fos = null;
                        fos = new FileOutputStream(apkFile);
                        byte[] buf = new byte[1024];
                        int count = 0;
                        int length = -1;
                        while ((length = is.read(buf)) != -1) {
                            fos.write(buf, 0, length);
                            count += length;
    
                            pd.setProgress((int)count/1024/1024);
    
                        }
                        is.close();
                        fos.close();
                        return true;
                    }
                } catch (FileNotFoundException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                return false;
            }
    
            @Override
            protected void onPostExecute(Boolean flag) {
                pd.dismiss(); //结束掉进度条对话框
                if (flag) {
                    handler.obtainMessage(COMPLETE_DOWNLOAD_APK).sendToTarget();
                } else {
                    Log.e("Error", "下载失败。");
                }
            }
        }
    
    
        /**
         * 安装APK
         *
         * @param data
         */
        private void installApk(File file) {
            if (mContext != null) {
    
                if(Build.VERSION.SDK_INT>=24) {//判读版本是否在7.0以上
                    Uri apkUri = MyFileProvider.getUriForFile(mContext, "包名.download.fileprovider", file);
                    Intent install = new Intent(Intent.ACTION_VIEW);
                    install.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                    install.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);//添加这一句表示对目标应用临时授权该Uri所代表的文件
                    install.setDataAndType(apkUri, "application/vnd.android.package-archive");
                    mContext.startActivity(install);
    
                    if (notificationManager != null) {
                        notificationManager.cancel(DOWNLOAD_NOTIFICATION_ID);
                    }
                }else {
    
                    Intent i = new Intent(Intent.ACTION_VIEW);
                    i.setDataAndType(Uri.fromFile(file), "application/vnd.android.package-archive");
                    i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                    mContext.startActivity(i);
                    if (notificationManager != null) {
                        notificationManager.cancel(DOWNLOAD_NOTIFICATION_ID);
                    }
                }
    
            } else {
                Log.e("NullPointerException", "The context must not be null.");
            }
        }
    
        //负责接收进度以及下载完成后启动安装的activity
        @SuppressLint("HandlerLeak")
        private class DownloadHandler extends Handler {
            @Override
            public void handleMessage(Message msg) {
                super.handleMessage(msg);
                switch (msg.what) {
                    case COMPLETE_DOWNLOAD_APK:
                        if (isAutoInstall) {
                            installApk(new File(getApkPath(mContext)));
                        } else {
                            if (ntfBuilder == null) {
                                ntfBuilder = new NotificationCompat.Builder(mContext);
                            }
                            ntfBuilder.setSmallIcon(mContext.getApplicationInfo().icon)
                                    .setContentTitle(mContext.getString(R.string.app_name))
                                    .setContentText("下载完成,点击安装").setTicker("任务下载完成");
                            Intent intent = new Intent(Intent.ACTION_VIEW);
                            intent.setDataAndType(
                                    Uri.parse("file://" + getApkPath(mContext)),
                                    "application/vnd.android.package-archive");
                            PendingIntent pendingIntent = PendingIntent.getActivity(
                                    mContext, 0, intent, 0);
                            ntfBuilder.setContentIntent(pendingIntent);
                            if (notificationManager == null) {
                                notificationManager = (NotificationManager) mContext
                                        .getSystemService(Context.NOTIFICATION_SERVICE);
                            }
                            notificationManager.notify(DOWNLOAD_NOTIFICATION_ID,
                                    ntfBuilder.build());
                        }
                        break;
                    case FAILED_DOWNLOAD_APK:
                        if (ntfBuilder == null) {
                            ntfBuilder = new NotificationCompat.Builder(mContext);
                        }
                        ntfBuilder.setSmallIcon(mContext.getApplicationInfo().icon)
                                .setContentTitle(mContext.getString(R.string.app_name))
                                .setContentText("下载失败,请检查网络").setTicker("新版本下载失败");
                        notificationManager.notify(DOWNLOAD_NOTIFICATION_ID,
                                ntfBuilder.build());
                        break;
                }
            }
    
        }
    }
    

    相关文章

      网友评论

          本文标题:下载自动安装apk(android10)

          本文链接:https://www.haomeiwen.com/subject/tukpbktx.html