【Android】轻松实现 APK 在线升级

时间:2024-03-24 16:16:16

【Android】轻松实现 APK 在线升级

APK 在线升级

APK 在线升级几乎是所有程序必备的功能。

在线升级功能能解决已有的问题并提供更丰富的新功能。

基本的流程是:

  1. 检测到新版本信息
  2. 弹出升级提示窗口
  3. 点击 No 不进行升级,完毕!
  4. 点击 Yes 后台下载升级程序
  5. 程序下载完成进入安装页面
  6. 安装成功,进入新程序

下面将介绍使用 UpdateAppUtil 实现在线升级功能

0. 需要权限

需要授权 android.permission.INTERNETandroid.permission.WRITE_EXTERNAL_STORAGE 权限,具体申请版本在这里不展开了。

有兴趣的小伙伴可以看以往的文章。

1. 获取新版本信息

一般是访问服务器,获取新版本信息(以下面为例)


{
    "url":"https://www.google.com/test/a670ef11/apk/test.apk",
    "versionCode":1,
    "versionName":"v2.1.0",
    "create_time":"2019-12-14 03:44:34",
    "description":"新增卫星链路,支持全球访问。"
}

必须要有 APK 的下载链接(url),版本号(versionCode)或者版本名(versionName)。

都是接下来需要用到的。

2. 设置信息


UpdateAppUtil.from(MainActivity.this)
        .checkBy(UpdateAppUtil.CHECK_BY_VERSION_NAME) //更新检测方式,默认为VersionCode
        .serverVersionCode(0)
        .serverVersionName(version)
        .updateInfo(description)
        .apkPath(url)
        .update();

字段 说明
checkBy 是否需要弹出升级提示的依据。CHECK_BY_VERSION_NAME 是根据 serverVersionName 的不同就弹出升级提示。CHECK_BY_VERSION_CODE 是根据 serverVersionCode 高于当前软件版本弹出升级提示。
serverVersionCode 设置新软件的 versionCode (如示例的 1 )
serverVersionName 设置新软件的 versionName (如示例的 “v2.1.0” )
updateInfo 升级提示窗口显示的新软件描述
apkPath 新软件下载链接(需要通过此链接下载新软件)
update 马上进行升级检查(如满足升级要求,弹出升级提示)
isForce 如果不选择升级,直接退出程序

3. 下载升级程序

Android 有多种框架可以下载程序(okhttp等),也可以开启一个线程去下载(IntentService)。

而 UpdateAppUtil 采用 Android SDK 提供的下载框架 DownloadManager


public static void downloadWithAutoInstall(Context context, String url, String fileName, String notificationTitle, String descriptInfo) {
    if (TextUtils.isEmpty(url)) {
        Log.e(TAG, "url为空!!!!!");
        return;
    }
    try {
        Uri uri = Uri.parse(url);
        Log.i(TAG, String.valueOf(uri));
        DownloadManager downloadManager = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);
        DownloadManager.Request request = new DownloadManager.Request(uri);
        // 在通知栏中显示
        request.setVisibleInDownloadsUi(true);
        request.setTitle(notificationTitle);
        request.setDescription(descriptInfo);
        request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
        request.setMimeType("application/vnd.android.package-archive");

        String filePath = null;
        if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {//SD卡是否正常挂载
            filePath = Environment.getExternalStorageDirectory().getAbsolutePath();
        } else {
            Log.i(TAG, "没有SD卡" + "filePath:" + context.getFilesDir().getAbsolutePath());
            return;
        }

        downloadUpdateApkFilePath = filePath + File.separator + fileName;
        // 若存在,则删除
        deleteFile(downloadUpdateApkFilePath);
        Uri fileUri = Uri.parse("file://" + downloadUpdateApkFilePath);
        request.setDestinationUri(fileUri);
        downloadUpdateApkId = downloadManager.enqueue(request);
    } catch (Exception e) {
        e.printStackTrace();
    }
}

request.setVisibleInDownloadsUi 下载UI显示到通知栏上

request.setTitle 设置通知栏的标题

request.setDescription 设置通知栏的消息

request.setNotificationVisibility 下载过程中一直显示下载信息,下载完后也存在(直到用户消除)

会清除没完成的文件,重新下载。

DownloadManager 下载过程中(下载完成)会发出广播,想要对下载完成进行处理需要监听广播。

(downloadUpdateApkFilePath 保存下载文件的路径,下载完成后可以通过此进行安装)

4. 进入安装

DownloadManager 下载完成后会发出 ACTION_DOWNLOAD_COMPLETE


public class UpdateAppReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        Cursor cursor = null;
        try {
            if (! intent.getAction().equals(DownloadManager.ACTION_DOWNLOAD_COMPLETE)) {
                return;
            }
            if (DownloadAppUtil.downloadUpdateApkId <= 0) {
                return;
            }
            long downloadId = DownloadAppUtil.downloadUpdateApkId;
            DownloadManager.Query query = new DownloadManager.Query();
            query.setFilterById(downloadId);
            DownloadManager manager = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);
            cursor = manager.query(query);
            if (cursor.moveToNext()) {
                int staus = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS));
                if (staus == DownloadManager.STATUS_FAILED) {
                    manager.remove(downloadId);
                } else if ((staus == DownloadManager.STATUS_SUCCESSFUL)
                        && (DownloadAppUtil.downloadUpdateApkFilePath != null)) {
                    Intent it = new Intent(Intent.ACTION_VIEW);
                    it.setDataAndType(Uri.parse("file://" + DownloadAppUtil.downloadUpdateApkFilePath),
                            "application/vnd.android.package-archive");
                    // todo 针对不同的手机 以及 sdk 版本, 这里的 uri 地址可能有所不同
                    it.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                    context.startActivity(it);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (cursor != null) {
                cursor.close();
            }
        }
    }
}

判断是 DownloadManager.ACTION_DOWNLOAD_COMPLETE 获取 APK 路径进行安装。

【Android】轻松实现 APK 在线升级

【Android】轻松实现 APK 在线升级

【Android】轻松实现 APK 在线升级

【Android】轻松实现 APK 在线升级