安卓okhttpUtils下载文件(安装包)并打开(安装)实例

okhttpUtils是okhttp的一个工具包,首先在app的build.gradle中添加以下内容:

    implementation 'com.squareup.okhttp3:okhttp:4.3.0'
    implementation 'com.squareup.okio:okio:2.4.3'
    implementation 'com.zhy:okhttputils:2.6.2'

	//实例中使用了Toast和Dialog的第三方框架,如需使用请添加以下内容
	implementation 'com.github.GrenderG:Toasty:1.3.0'
    implementation 'com.afollestad.material-dialogs:core:0.9.6.0'

首先实例流程为:①获取当前APP版本号 ②请求检查更新接口 ③若有新版本则提示下载 ④若点击下载则通过异步请求将服务器上的APK文件下载完成后自动跳转安装界面

注意由于谷歌要求针对高版本安卓开发,低版本不允许上架, 所以当前实例并未考虑低版本安卓,测试机为安卓7-10

首先在安卓7以上存在一个问题,就是普通file格式的uri无法直接使用,需通过共享目录生成content格式的uri,所以我们需要在androidmanifest.xml的application中添加以下内容:

<provider
    android:name="android.support.v4.content.FileProvider"
    android:authorities="com.packagename.fileProvider" //改为你的包名.fileProvider即可
    android:exported="false"
    android:grantUriPermissions="true">
    <meta-data
        android:name="android.support.FILE_PROVIDER_PATHS"
        android:resource="@xml/file_paths" />
</provider>

然后在res目录中新建一个xml目录,如果已有则不需要新建,在xml中新建一个files_paths.xml并写入以下内容:

<?xml version="1.0" encoding="utf-8"?>
<paths>
    <!-- 物理路径为Context.getFilesDir() + /files/... -->
    <files-path path="files" name="files" />
    <!-- 物理路径为Context.getCacheDir() + /files/... -->
    <cache-path path="files" name="cache" />
    <!-- 物理路径为Environment.getExternalStorageDirectory() + /files/... -->
    <external-path path="files" name="external" />
    <!-- 物理路径为Context.getExternalFilesDir(String) + /files/... -->
    <external-files-path path="files" name="externalfiles"/>
    <!-- 物理路径为Context.getExternalCacheDir() + /files/... -->
    <external-cache-path  path="files" name="externalcache"/>
    <!-- 物理路径为`Context.getExternalMediaDirs() + /files/..., 要求API21+ -->
    <external-media-path name="externalmedia" path="files" />
    <root-path name="root_path" path="."/>
</paths>

这样我们的共享目录就配置好了,在代码中直接使用即可,接下来我将直接贴出检查更新的完整点击事件供大家参考(重要部分在代码中注释标出):

check_view.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        long versionCode = 1000;
        //获取当前APP的版本号
        try {
            PackageInfo packageInfo = getContext().getApplicationContext()
                    .getPackageManager()
                    .getPackageInfo(getContext().getPackageName(), 0);
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
                versionCode = packageInfo.getLongVersionCode();
            } else {
                versionCode = packageInfo.versionCode;
            }
        } catch (PackageManager.NameNotFoundException e) {
            Log.e("", e.getMessage());
        }

		//请求地址+等待提示框
        String host = new Defines().SERVER_HOST+"checkUpdate";
        final MaterialDialog waitForDialog = new MaterialDialog.Builder(getActivity())
                .content("请稍等...")
                .progress(true,-1)//等待图标 true=圆形icon false=进度条
                .cancelable(false)//不会被取消 (包括返回键和外部点击都无法取消)
                .build();
        waitForDialog.show();

		//调用检查更新接口,传入当前版本号
        OkHttpUtils
                .post()
                .url(host)
                .addParams("version_code",""+versionCode)
                .build()
                .execute(new StringCallback() {
                    @Override
                    public void onError(Call call, Exception e, int id) {
                        waitForDialog.dismiss();
                        Toasty.error(getActivity(),"服务器请求失败", Toast.LENGTH_SHORT).show();
                    }

                    @Override
                    public void onResponse(String response, int id) {
                        waitForDialog.dismiss();
                        try {
                            JSONObject jsonObject = new JSONObject(response);
                            int code = jsonObject.getInt("code");
                            //code=200为最新版本无需更新   code=250为有新版本可供下载
                            if (code==200) {
                                Toasty.success(getActivity(),jsonObject.getString("msg"),Toast.LENGTH_SHORT).show();
                            } else if(code==250) {
                                final JSONObject data = jsonObject.getJSONObject("data");
                                //将后台编写的更新日志的<br>打散重组为\n以在安卓可以换行提示
                                String log = "";
                                String[] chrstr = data.getString("update_log").split("<br>");
                                for(int i=0;i<chrstr.length;i++)
                                    log = log + chrstr[i]+"\n";

                                MaterialDialog dialog = new MaterialDialog.Builder(getContext())
                                        .title(jsonObject.getString("msg"))
                                        .content(log)
                                        .positiveText("下载更新")
                                        .negativeText("以后再说")
                                        .cancelable(true)
                                        .onPositive(new MaterialDialog.SingleButtonCallback() { 
                                            @Override
                                            public void onClick(@NonNull MaterialDialog dialog, @NonNull DialogAction which) {
												//获取APP内部存储的chche文件夹路径
                                                if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState()) || !Environment.isExternalStorageRemovable()) {
                                                    cachePath = getActivity().getExternalCacheDir().getPath();
                                                } else {
                                                    cachePath = getActivity().getFilesDir().getAbsolutePath();
                                                }
												//新建一个下载进度条并允许点击其他区域关闭
                                                final ProgressDialog progressDialog = new ProgressDialog(getContext());
                                                progressDialog.setTitle("正在下载,请耐心等待...");
                                                progressDialog.setMessage("点击其他区域或返回以转入后台下载");
                                                progressDialog.setCancelable(true);
                                                progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
                                                progressDialog.show();

                                                try {
                                                    //通过okhttpUtils下载文件
                                                    OkHttpUtils.get()
                                                            .url(data.getString("position"))
                                                            .build()
                                                            .execute(new FileCallBack(cachePath,"fingerdorm.apk") {
                                                                @Override
                                                                public void onError(Call call, Exception e, int id) {
                                                                    Toasty.error(getActivity(),"下载失败",Toast.LENGTH_SHORT).show();
                                                                }
																//inpogress回调为更新进度条
                                                                @Override
                                                                public void inProgress(float progress, long total, int id) {
                                                                    super.inProgress(progress, total, id);
                                                                    progressDialog.setProgress((int) (100 * progress));
                                                                }
																//下载完成,处理打开安装
                                                                @Override
                                                                public void onResponse(File downloadFile, int id) {
                                                                    Toasty.success(getActivity(),"下载完成,即将启动安装",Toast.LENGTH_LONG).show();
                                                                    progressDialog.hide();
                                                                    progressDialog.dismiss();
                                                                    //开启子线程,延迟三秒后执行安装
                                                                    new Thread(new Runnable()
                                                                    {
                                                                        @Override
                                                                        public void run()
                                                                        {
                                                                            try {
                                                                                sleep(3000);

                                                                                if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState()) || !Environment.isExternalStorageRemovable()) {
                                                                                    cachePath = getContext().getExternalCacheDir().getPath();
                                                                                } else {
                                                                                    cachePath = getContext().getFilesDir().getAbsolutePath();
                                                                                }
                                                                                File uriFile = new File(cachePath +"/fingerdorm.apk");												
                                                                                //这里获取uri的第二个参数一定要和androidmanifest中配置的的对应
                                                                                Uri uri = getUriForFile(getContext(), "com.packaname.fileProvider", uriFile);
                                                                                Intent intent = new Intent(Intent.ACTION_VIEW);
                                                                                intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                                                                                intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
                                                                                //打开APK执行的TYPE为"application/vnd.android.package-archive"
                                                                                intent.setDataAndType(uri,"application/vnd.android.package-archive");
                                                                                getContext().startActivity(intent);
                                                                            } catch (Exception e) {
                                                                                Looper.prepare();
                                                                                Toasty.error(getActivity(), "自动安装失败,请手动安装", Toast.LENGTH_SHORT).show();
                                                                                Looper.loop();
                                                                            }
                                                                        }
                                                                    }).start();
                                                                }
                                                            });
                                                } catch (JSONException e) {
                                                    Toasty.error(getActivity(), "服务器数据解析失败", Toast.LENGTH_SHORT).show();
                                                }
                                            }
                                        })
                                        .onNegative(new MaterialDialog.SingleButtonCallback() { 
                                        
                                            @Override
                                            public void onClick(@NonNull MaterialDialog dialog, @NonNull DialogAction which) {
                                            }
                                        })
                                        .build();
                                dialog.show();
                            }else{
                                Toasty.error(getActivity(),jsonObject.getString("msg"), Toast.LENGTH_SHORT).show();
                            }
                        } catch (JSONException e) {
                            e.printStackTrace();
                            Toasty.warning(getActivity(),"检查更新失败",Toast.LENGTH_LONG).show();
                        }
                    }
                });
    }
});
发布了29 篇原创文章 · 获赞 1 · 访问量 7813

猜你喜欢

转载自blog.csdn.net/qq_38280150/article/details/104154927
今日推荐