Android利用FileDownloader实现APP自动更新并且安装

在Android中APP自动更新、安装是必然的,最近呢我们公司也有这样一个需求开始呢本菜鸟是打算用AppUpdate但是呢看了他的项目后发现真的是个好东西但是我不打算这样做打算自己来实现更新、安装。无意之间在一个项目中发现了FileDownloader这个真是个好东西那么我立马下手果然…做出来了 而且还挺简单…

第三方依赖说明

一、网络请求:Retrofit2+RxJava
 	implementation 'com.squareup.retrofit2:retrofit:2.3.0'
    implementation 'com.squareup.retrofit2:converter-gson:2.3.0'
    implementation 'com.squareup.retrofit2:converter-scalars:2.3.0'
    implementation 'com.squareup.retrofit2:adapter-rxjava2:2.3.0'
    implementation 'com.squareup.okhttp3:okhttp:3.9.0'
    implementation 'com.squareup.okhttp3:logging-interceptor:3.9.0'
    implementation 'io.reactivex.rxjava2:rxandroid:2.0.1'
    implementation 'io.reactivex.rxjava2:rxjava:2.1.5'
二、文件下载:FileDownloader
implementation 'com.liulishuo.filedownloader:library:1.7.5'

更新APP

一、查询APP和服务器版本是否一样(这里你可以和你们后台小哥协商)
  RequestManager.getInstance().getApi.getAppMsg().compose(RxThreadUtlis.rxSchedulerHelper())
                .subscribe(new RequestSubscribe() {
                    @Override
                    protected void onRequestScceed(RequestBaseBean response) {
                        if (response instanceof AppUpdateBean) {
                            AppUpdateBean appUpdateBean = (AppUpdateBean) response;
                            if (appUpdateBean != null) {
                            	//比较APP版本和服务器版本是否一样
                                if (appUpdateBean.getData().get(0).getAppMsgId() != PackageUtlis.packageCode(AppApdateActivity.this)) {
                                    new AlertDialog.Builder(AppApdateActivity.this)
                                            .setTitle("应用更新")
                                            .setMessage("检查到新版本啦,请安装更新~")
                                            .setPositiveButton("立即更新", (dialog, which) -> {
                                                dialog.dismiss();
                                                downloadAPK();
                                            }).setNeutralButton("稍后提醒", (dialog, which) -> dialog.dismiss()).create()
                                            .show();

                                }
                            }
                        }
                    }

                    @Override
                    protected void onRequestErro(RequestBaseBean response) {

                    }
                });
二、FileDownloader简单使用下载

1、初始化FileDownloader

FileDownloader.setupOnApplicationOnCreate(this);

2、获取文件路径(如果文件存在则删除不存在则创建)

private String apkPath() {
        String path = null;
        if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){
            File file = new File(Environment.getExternalStorageDirectory().toString()+File.separator+"AppApdate");
            if (file.exists() && file.isDirectory()){
                for (File fileDir : file.listFiles()) {
                    if (fileDir.isFile()) {
                        fileDir.delete(); // 删除所有文件
                    }
                }
            }else {
                file.mkdir();
            }
            path = file.getAbsolutePath();
        }
        return path;
    }

3、使用FileDownloader下载

 FileDownloader.getImpl().create(Constant.APK_URL).setPath(apkPath()+File.separator+"app.apk")
                .setListener(new FileDownloadLargeFileListener() {
                    @Override
                    protected void pending(BaseDownloadTask task, long soFarBytes, long totalBytes) {
                        Log.e(DOWNLOAD_TAG,"pending");
                    }

                    @Override
                    protected void progress(BaseDownloadTask task, long soFarBytes, long totalBytes) {
                        Log.e(DOWNLOAD_TAG,"progress----"+(soFarBytes * 100 / totalBytes));
                        progressBar.setProgress((int) (soFarBytes * 100 / totalBytes));
                        tv_pg_d.setText("下载进度:"+(int) (soFarBytes * 100 / totalBytes)+"%  /  "+100+"%");
                        tv_pg_m.setText("已完成:"+soFarBytes/1024/1024+"MB / "+totalBytes/1024/1024+"MB");

                    }

                    @Override
                    protected void paused(BaseDownloadTask task, long soFarBytes, long totalBytes) {
                        Log.e(DOWNLOAD_TAG,"paused");

                    }

                    @Override
                    protected void completed(BaseDownloadTask task) {
                        Log.e(DOWNLOAD_TAG,"completed----------"+task.getPath());
                        progressBar.setProgress(100);
                        tv_pg_d.setText("下载进度:"+"100% / 100%");
                        installAPK(task.getPath());

                    }

                    @Override
                    protected void error(BaseDownloadTask task, Throwable e) {
                        Toast.makeText(AppApdateActivity.this,"下载错误",Toast.LENGTH_SHORT).show();

                    }

                    @Override
                    protected void warn(BaseDownloadTask task) {
                        Log.e(DOWNLOAD_TAG,"warn--:在下载队列中(正在等待/正在下载)已经存在相同下载连接与相同存储路径的任务");
                    }
                }).start();

4、安装APK

   /**
     * 安装APK
     * @param path
     */
    private void installAPK(String path) {
        File fileApk = new File(path);
        if (!fileApk.exists()) {
            Toast.makeText(IndexAc.this, "纯氧健身更新失败", Toast.LENGTH_SHORT).show();
            return;
        }
        Intent intent = new Intent(Intent.ACTION_VIEW);

        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        Uri apkUri = null;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            apkUri = FileProvider.getUriForFile(IndexAc.this, BuildConfig.APPLICATION_ID + ".provider", fileApk);
            //添加这一句表示对目标应用临时授权该Uri所代表的文件
            intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
        } else {
            apkUri = Uri.fromFile(fileApk);
        }

        intent.setDataAndType(apkUri,
                "application/vnd.android.package-archive");

        startActivity(intent);
    }
注:APK安装在7.0之后的版本运行以前apk安装代码会出现android.os.FileUriExposedException
原因:“私有目录被限制访问”是指在Android7.0中为了提高私有文件的安全性,面向 Android N 或更高版本的应用私有目录将被限制访问。 而7.0的” StrictMode API 政策” 是指禁止向你的应用外公开 file:// URI。 如果一项包含文件 file:// URI类型 的 Intent 离开你的应用,应用失败,并出现 FileUriExposedException 异常。 之前代码用到的Uri.fromFile就是商城一个file://的Uri在7.0之后,我们需要使用FileProvider来解决

5、配置:FileProvider

  • AndroidManifest.xml中application中添加
  <provider
            android:name="android.support.v4.content.FileProvider"
            android:authorities="${applicationId}.provider"
            android:grantUriPermissions="true"
            android:exported="false">
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/file_paths" />
        </provider>
  • 创建xml文件file_paths
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <paths>
        <external-path
            name="files_root"
            path="" />
    </paths>
</resources>

path:需要临时授权访问的路径(.代表所有路径)
name:就是你给这个访问路径起个名字

添加权限(Android 6.0 后记得加上运行时权限哦~WRITE_EXTERNAL_STORAGE 6.0后需要动态申请)

<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<!--安装权限-->
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />

参考文章:
https://blog.csdn.net/qq_24852599/article/details/72539523
https://blog.csdn.net/cfy137000/article/details/70257912
参考项目连接:
https://github.com/sdwfqin/AppUpdate
FileDownloader地址:
https://github.com/lingochamp/FileDownloader
Github(我做了稍稍的修改不影响正常使用):
https://github.com/distantplace-z/BaseTools/blob/master/sample/src/main/java/com/xiaohou/sample/ui/download/DownloadActivity.java

这样更新就完成啦~
(注:此方法仅供参考个人尝试是成功了的)

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值