今天来个版本更新功能吧(下载和安装)!我也没用过第三方的,甚至不知道哪里有第三方的,而且我也不知道这种方式有没有什么弊端啥的,总之,它来了!!!话不多说,开干!!!

1、我这边封装了 一个类,先请求接口,查询是否更新。
 

/**
 * 检测版本更新
 */
public class UpdateUtils {
    /**
     *
     * @param context 暂未用到此参数
     */
    public static void upDateApp(Context context) {
        //线程池开启一个线程
        ExecutorService singleThreadPool = Executors.newSingleThreadExecutor();
        singleThreadPool.execute(new Runnable() {
            @Override
            public void run() {
                //传参时的参数,此时不需要,因为我的接口中没有要求传参
                FormBody.Builder builder = new FormBody.Builder();
                //OkhttpUtil类可以看我之前的文章
                OkhttpUtil.sendPostUrl("接口地址", builder, new Callback() {
                    @Override
                    public void onFailure(@NonNull Call call, @NonNull IOException e) {
                        //利用EventBus在请求接口失败时发送信息到主界面
                        //EventBus使用自己学习啦***
                        EventBus.getDefault().post(new UpdateEvent(e.toString()));
                        Log.d("UpdateUtils", "onFailure");
                    }

                    @Override
                    public void onResponse(@NonNull Call call, @NonNull Response response) throws IOException {
                        Log.d("UpdateUtils", "onResponse");
                        //解析所需要的数据
                        String string = response.body().string();
                        Log.d("UpdateUtils", string);
                        try {
                            //我这里使用原生解析了
                            JSONObject jsonObject = new JSONObject(string);
                            String result = jsonObject.getString("result");

                            JSONObject object = new JSONObject(result);
                            String number = object.getString("number");//版本号
                            String content = object.getString("content");//更新信息
                            String url = object.getString("url");//下载地址
                            String appname = object.getString("appname");//名称
                            //利用EventBus在请求接口成功时发送信息到主界面
                            EventBus.getDefault().post(new UpdateEvent(number, content, url, appname));
                        } catch (JSONException e) {
                            e.printStackTrace();
                        }
                    }
                });
            }
        });
    }
}

2、接下来使用次工具类

UpdateUtils.upDateApp(this);

3、工具类中写出,使用了EventBus将消息发送回主界面了

//接收检查版本更新
    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onEventUpdate(UpdateEvent event) {
        int number = Integer.parseInt(event.getNumber());//接收到的版本信息
        String content = event.getContent();//接收到的版本更新描述信息
        String url = event.getUrl();//接收到的下载地址
        String appName = event.getAppName();//接收到的名称
        //这里我获取了当前的versionCode,你们自行定义更新规则
        int version = Utils.getVersion(this);
        Log.d("version", version + "");

        if (number > version) {//判断是否更新
            DialogUtils.showDialog(this);//弹出对话框,对话框的简单使用就不用我多说了吧

            final Button btn_sure = (Button) DialogUtils.dialog.getWindow().findViewById(R.id.btn_sure);
            TextView tv_content = (TextView) DialogUtils.dialog.getWindow().findViewById(R.id.tv_content);

            tv_content.setText(content);
            btn_sure.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View arg0) {
                    new DownloadUtils(MainActivity.this, MainActivity.this, url, " " + appName);
                    Toast.makeText(MainActivity.this, "正在下载,请在通知栏中查看下载状态", Toast.LENGTH_LONG).show();
                    btn_sure.setText("正 在 下 载");
                    btn_sure.setBackgroundResource(R.drawable.btn_nocheck);
                    btn_sure.setEnabled(false);
                    DialogUtils.disDialog();
                }
            });
        }
    }

4、下载安装工具类,比较重要的一步!!!

/**
 * 下载apk工具类
 */
public class DownloadUtils {
    //下载器
    private DownloadManager downloadManager;
    private Context mContext;
    private Activity activity;
    //下载的ID
    private long downloadId;
    private String name;
    //构造方法,接收参数
    public DownloadUtils(Activity activity, Context context, String url, String name) {
        this.activity = activity;
        this.mContext = context;
        this.name = name;
        downloadAPK(url, name);
    }

    //下载apk
    private void downloadAPK(String url, String name) {
        DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url));
        //移动网络情况下是否允许漫游
        request.setAllowedOverRoaming(false);
        //在通知栏中显示,默认就是显示的
        request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE);
        request.setTitle("");
        request.setDescription("新版下载中···");
        request.setVisibleInDownloadsUi(true);

        //设置下载的路径
        File file = new File(mContext.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS), name);
        Log.d("downloadAPK", mContext.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS).getPath());
        request.setDestinationUri(Uri.fromFile(file));
        //获取DownloadManager
        if (downloadManager == null)
            downloadManager = (DownloadManager) mContext.getSystemService(Context.DOWNLOAD_SERVICE);
        //将下载请求加入下载队列,加入下载队列后会给该任务返回一个long型的id,通过该id可以取消任务,重启任务、获取下载的文件等等
        if (downloadManager != null) {
            downloadId = downloadManager.enqueue(request);
        }

        //注册广播接收者,监听下载状态
        mContext.registerReceiver(receiver, new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE));
    }

    //广播监听下载的各个状态
    private final BroadcastReceiver receiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context arg0, Intent arg1) {
            checkStatus();
        }
    };

    private void checkStatus() {
        DownloadManager.Query query = new DownloadManager.Query();
        //通过下载的id查找
        query.setFilterById(downloadId);
        Cursor cursor = downloadManager.query(query);
        if (cursor.moveToFirst()) {
            int status = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS));
            switch (status) {
                //下载暂停
                case DownloadManager.STATUS_PAUSED:
                    break;
                //下载延迟
                case DownloadManager.STATUS_PENDING:
                    break;
                //正在下载
                case DownloadManager.STATUS_RUNNING:
                    break;
                //下载完成
                case DownloadManager.STATUS_SUCCESSFUL:
                    //下载完成安装APK
                    installAPK();
                    cursor.close();
                    mContext.unregisterReceiver(receiver);
                    break;
                //下载失败
                case DownloadManager.STATUS_FAILED:
                    Toast.makeText(mContext, "下载失败", Toast.LENGTH_SHORT).show();
                    cursor.close();
                    mContext.unregisterReceiver(receiver);
                    break;
            }
        }
    }

    private void installAPK() {
        File file = new File(mContext.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS), name);
        Intent intent = new Intent();
        if (Build.VERSION.SDK_INT >= 24) {
            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
            Uri contentUri = FileProvider.getUriForFile(mContext, mContext.getPackageName() + ".provider", file);
            intent.setDataAndType(contentUri, "application/vnd.android.package-archive");
        } else {
            intent.setDataAndType(Uri.fromFile(file), "application/vnd.android.package-archive");
        }
        intent.setAction(Intent.ACTION_VIEW);
        mContext.startActivity(intent);
    }
}

5、此时重要的读写文件权限必须写哦,动态权限的添加也不要忘记

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.INTERNET" />
/*动态权限记得自行添加*/

6、对了,还有一步,下载安装的配置,这是必须滴!

<provider
            android:name="androidx.core.content.FileProvider"
            android:authorities="${applicationId}.provider"
            android:exported="false"
            android:grantUriPermissions="true">
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/file_path" />
        </provider>

7、file_path文件也给你们搞一下
 

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

到此呢,本文就结束了。如果你们在使用过程中遇到什么问题或者有什么其他代替的方法,可以在评论里面和我说,咱们一起探讨。不喜勿喷哦!!!

我会在之后的每周不定时更新我的文章,上传一些我自己总结的小知识,大家一起共勉!