Android 实现一个检查版本更新功能(适配到8.0+)

          作为一个app,如果要长期使用,我们是要对它的版本进行更新迭代的,记录一下,网上参考一个一下别人的检查更新的做法,然后自己修改成自己需要的。

我们可以看一些效果图:

   以上是效果图

   我们还是看回自己的代码,布局那些就不放上来了,自己可以随便撸一个自己喜欢的样式出来。

这个是我的检查更新按钮:

   case R.id.ll_auto_update:
               //更新方法
                auto_update();
                break;

   1.auto_update()这个方法里,我去调用服务器上有apk 的接口,请求获得返回  版本号信息,apk下载链接,版本内容介绍。(代码不可以复制使用,可以参考),重要的是拿到接口返回来的apk下载链接

   //更新版本信息
    private void auto_update() {
        String url = "XXXXXXXXXXXXXX";
        //获取本地内部版本好
        final int vcode = PackageUtils.getVersionCode(getContext());
        Map<String, String> map = new HashMap<>();
        map.put("XXXXX", "XXXXX");
      //调用封装好的网络请求,返回json格式
        OkHttpRequest.getInstance().getRequest(url, map, getContext(), new Handler() {
            @Override
            public void handleMessage(Message msg) {
                super.handleMessage(msg);

                try {
                    ResponseModer responseModer = (ResponseModer) msg.obj;
                    JSONObject jsonObject = responseModer.getJsonResultData();
                    System.out.println("asdad" + jsonObject);
                   String version = jsonObject.getString("version");
                   //重要的是拿到下载apk链接
                   String update_url = jsonObject.getString("update_url");
                   int verion_int = jsonObject.getInt("verion_int");
                   String ver_introduction = jsonObject.getString("ver_introduction");
                    System.out.println("外部版本号==" + version);
                    System.out.println("下载链接==" + update_url);
                    System.out.println("内部版本号==" + verion_int);
                    System.out.println("版本介绍==" + ver_introduction);
                    if (verion_int <= vcode) {
                        Util.showToast(getContext(), "现在是最新的版本");
                    } else {
                        // Util.showToast(getContext(), "检查到有新版本信息更新");
                        showUpdateDialog();
                    }
                } catch (JSONException e) {
                    e.printStackTrace();
                }

            }
        });

    }

这里面去获取当前apk的信息,拿到当前的版本信息,我是通过一个(PackageUtils)类去获取的。

  

public class PackageUtils {
    /**
     * 获取版本名称
     *
     * @param context 上下文
     *
     * @return 版本名称
     */
    public static String getVersionName(Context context) {

        //获取包管理器
        PackageManager pm = context.getPackageManager();
        //获取包信息
        try {
            PackageInfo packageInfo = pm.getPackageInfo(context.getPackageName(), 0);
            //返回版本号
            return packageInfo.versionName;
        } catch (PackageManager.NameNotFoundException e) {
            e.printStackTrace();
        }

        return null;

    }

    /**
     * 获取版本号
     *
     * @param context 上下文
     *
     * @return 版本号
     */
    public static int getVersionCode(Context context) {

        //获取包管理器
        PackageManager pm = context.getPackageManager();
        //获取包信息
        try {
            PackageInfo packageInfo = pm.getPackageInfo(context.getPackageName(), 0);
            //返回版本号
            return packageInfo.versionCode;
        } catch (PackageManager.NameNotFoundException e) {
            e.printStackTrace();
        }

        return 0;

    }

    /**
     * 获取App的名称
     *
     * @param context 上下文
     *
     * @return 名称
     */
    public static String getAppName(Context context) {
        PackageManager pm = context.getPackageManager();
        //获取包信息
        try {
            PackageInfo packageInfo = pm.getPackageInfo(context.getPackageName(), 0);
            //获取应用 信息
            ApplicationInfo applicationInfo = packageInfo.applicationInfo;
            //获取albelRes
            int labelRes = applicationInfo.labelRes;
            //返回App的名称
            return context.getResources().getString(labelRes);
        } catch (PackageManager.NameNotFoundException e) {
            e.printStackTrace();
        }

        return null;
    }
}
//获取本地内部版本号
final int vcode = PackageUtils.getVersionCode(getContext());

    跟服务器返回接口的内部版本号(verion_int ) 进行比较;

服务器上的内部版本号大于本地的时候,我们在去拿到apk下载链接 去执行下一步的操作。

2.showUpdateDialog();这个方法,来处理;

  

 /**
     * 点击下载弹框
     */
    private void showUpdateDialog() {
        AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
        builder.setTitle("检测到新版本");
        builder.setMessage("版本介绍:\n" + ver_introduction);
        builder.setPositiveButton("以后再说", new DialogInterface.OnClickListener() {

            @Override
            public void onClick(DialogInterface dialog, int which) {

            }
        }).setNegativeButton("立即更新", new DialogInterface.OnClickListener() {

            @Override
            public void onClick(DialogInterface dialog, int which) {
                showDownloadDialog();
            }
        });
        builder.show();
    }

弹出窗提示,版本介绍内容,当点击立即更新时,我们再进去下一步的下载操作。

3.showDownloadDialog(); 下载进度;

 /*
     * 显示正在下载对话框
     */
    protected void showDownloadDialog() {
        AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
        builder.setTitle("下载中");
        View view = LayoutInflater.from(getContext()).inflate(R.layout.dialog_progress, null);
        mProgressBar = view.findViewById(R.id.id_progress);
        builder.setView(view);

        builder.setNegativeButton("取消", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                // 隐藏当前对话框
                dialog.dismiss();
                // 设置下载状态为取消
                mIsCancel = true;
            }
        });

        mDownloadDialog = builder.create();
        mDownloadDialog.show();

        // 下载文件
        downloadAPK();
    }

    /* 开启新线程下载apk文件
     */
    private void downloadAPK() {

        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    mIsCancel = false;
                    if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
                        String sdPath = Environment.getExternalStorageDirectory() + "/";
//                      文件保存路径
                        mSavePath = sdPath + "lianzhandownload";
                        File dir = new File(mSavePath);
                        if (!dir.exists()) {
                            dir.mkdir();
                        }
                        // 下载文件
                        HttpURLConnection conn = (HttpURLConnection) new URL(update_url).openConnection();
                        conn.connect();
                        InputStream is = conn.getInputStream();
                        int length = conn.getContentLength();

                        File apkFile = new File(mSavePath, version);
                        FileOutputStream fos = new FileOutputStream(apkFile);

                        int count = 0;
                        byte[] buffer = new byte[1024];

                        while (!mIsCancel) {
                            int numread = is.read(buffer);
                            count += numread;
                            // 计算进度条的当前位置
                            mProgress = (int) (((float) count / length) * 100);
                            // 更新进度条
                            mUpdateProgressHandler.sendEmptyMessage(1);

                            // 下载完成
                            if (numread < 0) {
                                mUpdateProgressHandler.sendEmptyMessage(2);
                                break;
                            }
                            fos.write(buffer, 0, numread);
                        }
                        fos.close();
                        is.close();
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }

   开启线程介绍;下载进度更新ui显示:

 /**
     * 接收消息
     */
    private Handler mUpdateProgressHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case 1:
                    // 设置进度条
                    mProgressBar.setProgress(mProgress);
                    break;
                case 2:
                    // 隐藏当前下载对话框
                    mDownloadDialog.dismiss();
                    // 安装 APK 文件
                    installAPK();
            }
        }
    };

 当下载完成之后,我们再去安装新版的apk:

 我们要注意文件清单添加相应的权限:

  <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" />
  <uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES"/>

    如果没有添加到最后一条的权限,8.0下载完不会跳转获取apk安装。安装之前还要做一下的处理https://blog.csdn.net/zhaihaohao1/article/details/81809110参考别人的方法。

4。 installAPK()方法;

/*
     * 下载到本地后执行安装
     */
    protected void installAPK() {
        File apkFile = new File(mSavePath, version);
        if (!apkFile.exists()) {
            return;
        }


        Intent intent = new Intent(Intent.ACTION_VIEW);
        //判断是否是AndroidN以及更高的版本
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
            Uri contentUri = FileProvider.getUriForFile(getContext(), BuildConfig.APPLICATION_ID + ".fileProvider", apkFile);
            intent.setDataAndType(contentUri, "application/vnd.android.package-archive");
        } else {
            intent.setDataAndType(Uri.fromFile(apkFile), "application/vnd.android.package-archive");
            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        }
        getActivity().startActivity(intent);
    }

 文件清单多加

  <provider
            android:name="android.support.v4.content.FileProvider"
            android:authorities="包名.fileProvider"
            android:grantUriPermissions="true"
            android:exported="false">
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/file_paths" />
        </provider>

3、打开file_paths.xml文件添加如下内容

<?xml version="1.0" encoding="utf-8"?>
<paths>
    <external-path="包名/" name="fileProvider" />
    <external-path path="." name="apk下载文件夹名" />
</paths>

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

然后再去调用installAPK()。到这里就基本上就可以了。这是我修改了部分代码。如果你还是看不懂,你可以参考下别人的

https://blog.csdn.net/zhaihaohao1/article/details/81808902

       每个人的需求不一定相同,但大致的方向还是一样的,我们可以参考别的踩过的坑,避免再去踩,当然目前这样的方式还是多少会存在不足,但我们可以实现之前,有了大致的思路,我们再去深入学习探讨,这样的学习方式也是不错的,由于本人知识有限,上面的东西没过多的详细说明,只是简单的说明。如有什么问题,可在评论区留意,我们一起探讨学习,谢谢。

猜你喜欢

转载自blog.csdn.net/qq_36771930/article/details/89352835