关于安卓自动更新那点事


要实现自动更新,其实就三步: 1.检查最新版本号 2.对比本地版本号 3.不匹配那么获取最新版本地址进行更新 关于检查最新版本号,花样繁多,以下贴一个RXJAVA的方法作参考
private void getVersion() {
        service.getVersion()
                .subscribeOn(Schedulers.io())//指定网络请求在IO线程
                .subscribeOn(AndroidSchedulers.mainThread())//显示Dialog在主线程中
                .observeOn(AndroidSchedulers.mainThread())//显示数据在主线程
                .subscribe(new Subscriber<VersionModel>() {
                    @Override
                    public void onCompleted() {
                    }

                    @Override
                    public void onError(Throwable e) {
                        T.showShort(getBaseContext(), "网络连接失败");
                    }

                    @Override
                    public void onNext(VersionModel versionModel) {
                        String currentVersion = VersionUtils.getInstance(getBaseContext()).getVersionName();
                        Float currentVersionF = Float.parseFloat(currentVersion);
                        if (currentVersionF < Float.parseFloat(versionModel.getVersionID())) {
                            //需要更新
                            PermissionGen.needPermission(WelcomeActivity.this, 100, new String[]{    //6.0以上权限
                                    android.Manifest.permission.READ_EXTERNAL_STORAGE,
                                    android.Manifest.permission.WRITE_EXTERNAL_STORAGE,
                            });
                        } else {
                            //不需要更新
                        }
                    }
                });
    }
接着就是对本地APP进行更新,更新一般分为强制更新或自由更新,参数一般由服务器推送决定 区别大致在于一个可以选择是否更新,而另一个不更新就不能进入APP 先贴上强制更新方法
private void forceUpdate(final Context context, final String versionID, final String appName, final String downUrl, final String updateinfo) {
        mDialog = new AlertDialog.Builder(this);
        mDialog.setCancelable(false).create().show();
        mDialog.setTitle("发现新版本");
        mDialog.setMessage(updateinfo);
        mDialog.setPositiveButton("立即更新", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                if (!canDownloadState()) {
                    showDownloadSetting();
                    return;
                }
                //DownLoadApk.download(MainActivity.this,downUrl,updateinfo,appName);
                AppInnerDownLoder.downLoadApk(context, downUrl, appName);
            }
        }).setCancelable(false).create().show();
    }
这里只有一个“立即更新”的按钮 自由更新的方法
private void freeUpdate(final Context context, final String versionID, final String appName, final String downUrl, final String updateinfo) {
        mDialog = new AlertDialog.Builder(this);
        //mDialog.setCancelable(false).create().show();
        mDialog.setTitle("发现新版本 " + versionID);
        mDialog.setMessage(updateinfo);

        mDialog.setPositiveButton("立即更新", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                if (!canDownloadState()) {
                    showDownloadSetting();
                    return;
                }
                //DownLoadApk.download(MainActivity.this,downUrl,updateinfo,appName);
                AppInnerDownLoder.downLoadApk(context, downUrl, appName);
            }
        }).setNegativeButton("下次更新", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                //不更新返回
                return;
            }
        }).setNeutralButton("不再提醒", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                //以后不更新,返回
                return;
            }
        }).setCancelable(false).create().show();
    }
代码上区别其实不是很大,方法中canDownloadState只是检查是否具有下载文件权限
private boolean canDownloadState() {
        try {
            int state = this.getPackageManager().getApplicationEnabledSetting("com.android.providers.downloads");
            if (state == PackageManager.COMPONENT_ENABLED_STATE_DISABLED
                    || state == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER
                    || state == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED) {
                return false;
            }

        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }

    private void showDownloadSetting() {
        String packageName = "com.android.providers.downloads";
        Intent intent = new Intent(android.provider.Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
        intent.setData(Uri.parse("package:" + packageName));
        startActivity(intent);
    }
上述代码中还包括一个VersionUtil会直接放在附件中,附件中还包括通用更新方法AppInnerDownLoder和通用下载方法DownLoadApk 不一定全用 AppInnerDownLoder中包含7.0兼容的代码
if (Build.VERSION.SDK_INT >= 24) {  //7.0兼容
            fileUri = FileProvider.getUriForFile(mContext, "com.com.suchbear.fileprovider", file);
            Log.e("fileUri", String.valueOf(fileUri));
            it.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); //添加这一句表示对目标应用临时授权该Uri所代表的文件
        } else {
            fileUri = Uri.fromFile(file);
        }
其中com.com.suchbear.fileprovider 需要在AndroidManifest中注册,注册代码为
<!-- 7.0注册provider -->
        <provider
            android:name="android.support.v4.content.FileProvider"
            android:authorities="com.com.suchbear.fileprovider"
            android:exported="false"
            android:grantUriPermissions="true">
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/file_paths" />
        </provider>
关键在于authorities匹配 更新用到的工具类