Android 实现自动更新及强制更新功能

版权声明:本文为博主原创文章,可以随意转载,但请附原地址或原作者名。谢谢! https://blog.csdn.net/farley119/article/details/82753103

引言

 目的不言而喻,肯定是为了自己版本的迭代更新。想做到版本的完全控制手段还是比较多的。今天我要分享的这个方法是用蒲公英提供的版本查询接口和版本下载接口来做的。有条件的同学也可以在自己的服务端开这两个接口。

需求分析

 我们要想实现这个自动更新的功能大致分三步:

  1. 查询线上版本号,然后拿本地版本号与之对比。
  2. 若线上版本号比本地版本号大,则下载线上版本号
  3. 把下载好的版本号安装,并替换当前旧版本

权限

 根据上面的需求我们可以知道,需要用到的权限应该有网络权限、本地文件写入权限,本地文件读取权限。使用网络权限去获取线上的版本号,然后下载保存到本地,安装的时候再去本地取来。

	<uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>

步骤

 根据上面的需求,我们一步一步来实现这个功能。首先在APP的入口处去检测版本号。

ProUtils.canUpdata(this);

在这里我把检测方法给封装到了utils中,这样用起来也方便。

1,检测线上版本

 public void check() {
        //当所用app前版本号
        int codeversin = getVersion();
        getLineVersion(checkurl, codeversin);
    }

这个方法里面包含了两步,第一步是去获取本地版本号,第二步是去获取线上版本号
获取本地版本号:

public int getVersion() {
        PackageInfo pkg;
        int versionCode = 0;
        String versionName = "";
        try {
            pkg = activity.getPackageManager().getPackageInfo(activity.getApplication().getPackageName(), 0);
            versionCode = pkg.versionCode;

        } catch (PackageManager.NameNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return versionCode;
    }

获取线上版本号:

OkHttpClient okHttpClient = new OkHttpClient();
        RequestBody formBody = new FormBody.Builder()
                .add("_api_key", BuildConfig.PYAPIKEY)
                .add("appKey", BuildConfig.PYAPPID)
                .build();
        Request request = new Request.Builder()
                .url(url)
                .post(formBody)
                .build();
        Call call = okHttpClient.newCall(request);
        call.enqueue(new Callback() {

            @Override
            public void onFailure(Call call, IOException e) {

            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
               
            }

        });

在上面有两个KEY,这两个可以都是从蒲公英上取来的。就像引言所说,若有条件可以自己搭建。

版本比较

 在上面请求成功后,在response中就会获取到我们的线上版本号。然后我们拿上一步中获取到的线上版本号和本地版本号来做对比:

if (lineVersion > nowcodeversin) {
        //去弹窗提示用户
}

这个时候,如果比较的结果是线上版本比较大,则去下载线上版本

提示用户

 我们要给用户提示的,当然你若想直接下载也可以,只不过为了用户体验而已,自己斟酌。
提醒用户

AlertDialog dialog = new AlertDialog.Builder(activity).setTitle
           ("Tips").setMessage("Have new version,please update!")
            .setNeutralButton("Cancel", new DialogInterface
                      .OnClickListener() {
                      @Override
                        public void onClick(DialogInterface dialog, int which) {
                               dialog.dismiss();
                        }
             }).setNegativeButton("Update", new DialogInterface
                         .OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int which) {
                                  pyUtils.downUrl();
                             }
               }).show();
              dialog.setCanceledOnTouchOutside(false);//可选
              dialog.setCancelable(false);//可选

在这里我给了用户两种选择,一种是立即更新,一种是稍后再说。点击稍后,那就会在下次再出发的时候再去提醒用户。点击更新的话,会立刻开始下载应用的新版本。
如果你想强制用户去更新的话,可以把稍后的选项去掉,顺便把
dialog.setCanceledOnTouchOutside(false);//可选,点击dialog其它地方dismiss无效
dialog.setCancelable(false);//可选,点击返回键无效
这两项给加上,用户就不得不更新了。

下载

上面都做好了,那就下载吧,就是一个文件下载的方法:

public void downUrl() {
       DownloadUtil.get().download(downUrl,activity.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS).getAbsolutePath(), new DownloadUtil.OnDownloadListener() {
            @Override
            public void onDownloadSuccess(File file) {
                LogUtils.e("AutoUpdate","下载完成去安装");
            }

            @Override
            public void onDownloading(int progress) {
            }

            @Override
            public void onDownloadFailed() {
                LogUtils.e("AutoUpdate","下载失败");
            }
        });

    }

这个下载没什么好说的

安装

下载好之后,我们直接使用系统的方法去安装即可

 ////调用系统的安装方法
    private void installAPK(File savedFile) {
        //调用系统的安装方法
        Intent intent = new Intent(Intent.ACTION_VIEW);
        Uri data;
        // 判断版本大于等于7.0
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            // "net.csdn.blog.ruancoder.fileprovider"即是在清单文件中配置的authorities
            data = FileProvider.getUriForFile(activity, "com.thinker.member.bull.android_bull_member.fileprovider", savedFile);
            // 给目标应用一个临时授权
            intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
            LogUtils.e("AutoUpdate","7.0data="+data);
        } else {
            data = Uri.fromFile(savedFile);
            LogUtils.e("AutoUpdate","111data="+data);
        }
        intent.setDataAndType(data, "application/vnd.android.package-archive");
        activity.startActivity(intent);
        activity.finish();
    }

在这里需要注意,有个7.0的方法。需要在你的项目清单文件中配置如下

<!-- 解决apk安装失败的问题 -->
        <provider
            android:name="android.support.v4.content.FileProvider"
            android:authorities="com.ligo.anomo.fileprovider"
            android:exported="false"
            android:grantUriPermissions="true">
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/file_paths" />
        </provider>

然后再资源res中添加xml/file_paths.xml

<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:android="http://schemas.android.com/apk/res/android">
    <paths>
        <external-path path="" name="download"/>
    </paths>
</resources>

基本就可以了。读书百卷,不如手写一遍。自己去试试吧。

猜你喜欢

转载自blog.csdn.net/farley119/article/details/82753103