【更新:2022年10月26日Blgly停止升级服务,此blog仅做记录,也可用来参考做升级UI】


升级使用的Bugly,由于Bugly最新sdk1.5.23未适配android12,当targetSDK设置为31时,点击升级会报错无法升级,反馈一个多月了未见改动,难道开发人员被裁了?

只能借助Bugly的后台和接口,自己撸一个简单的升级功能。
大概效果图如下

一. 禁止Bugly自带的检测升级并弹窗功能

  Beta.autoCheckUpgrade = falseBeta.init(this, isDebug)

二. 自己实现检测升级和弹窗功能

  1. 检测升级
//手动调用checkUpgrade接口
Beta.checkUpgrade(isManual, true)
delay(2000).run {//延时2s后读取结果,注意getUpgradeInfo api是读取本地的缓存结果,不会发起请求,所以要延时一下再读取会更好
var result = Beta.getUpgradeInfo()
}
  1. 制作升级弹窗
    layout布局而已,直接贴出来,可以自己diy
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:background="@color/white"android:orientation="vertical"><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:background="@color/primary_blue"android:orientation="vertical"android:paddingLeft="20dp"android:paddingTop="20dp"android:paddingRight="20dp"android:paddingBottom="20dp"><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="发现新版本"android:textColor="@color/white"android:textSize="20dp" /><TextViewandroid:id="@+id/tv_version"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginTop="15dp"android:lineSpacingMultiplier="1.2"android:text="版本号[0.0.0.8]\n发布日期[2022-06-01]"android:textColor="@color/white"android:textSize="16dp" /></LinearLayout><TextViewandroid:id="@+id/tv_feature"android:layout_width="match_parent"android:layout_height="wrap_content"android:minHeight="100dp"android:padding="20dp"android:text="版本特性:xxx"android:textSize="16dp" /><LinearLayoutandroid:id="@+id/fl_progress"android:layout_width="match_parent"android:layout_height="wrap_content"android:gravity="center_vertical"android:orientation="horizontal"android:padding="20dp"android:visibility="gone"tools:visibility="visible"><ProgressBarandroid:id="@+id/progressBar"style="?android:attr/progressBarStyleHorizontal"android:layout_width="0dp"android:layout_height="wrap_content"android:layout_weight="1"android:max="100"android:min="0"android:padding="@dimen/dp10"android:value="0" /><TextViewandroid:id="@+id/tv_progress"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginStart="5dp"android:text="0%" /></LinearLayout><LinearLayoutandroid:id="@+id/ll_actions"android:layout_width="match_parent"android:layout_height="wrap_content"android:gravity="center_vertical"android:orientation="horizontal"android:padding="20dp"><TextViewandroid:id="@+id/tv_cancel"android:layout_width="wrap_content"android:layout_height="wrap_content"android:padding="10dp"android:text="下次再说"android:textColor="@color/text_color2"android:textSize="16dp" /><TextViewandroid:id="@+id/tv_ignore"android:layout_width="wrap_content"android:layout_height="wrap_content"android:padding="10dp"android:text="忽略此版本"android:textColor="@color/text_color2"android:textSize="16dp" /><Viewandroid:layout_width="0dp"android:layout_height="0dp"android:layout_weight="1" /><TextViewandroid:id="@+id/tv_upgrade"android:layout_width="wrap_content"android:layout_height="wrap_content"android:padding="10dp"android:text="立即更新"android:textColor="@color/primary_blue"android:textSize="16dp" /></LinearLayout></LinearLayout>
</layout>
  1. 下载安装包
    这个地方,使用系统DownloadManager下载apk
val downloadManager = context.getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager
val request = DownloadManager.Request(Uri.parse(result.apkUrl))
request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, "labApks")
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE)
request.setMimeType("application/vnd.android.package-archive")val downloadId = downloadManager.enqueue(request)

downloadManger.enqueue(request)就会发起下载任务,但下载任务不是立即执行的需要等待系统调用。另外没有回调去接收下载进度,需要我们自己读取状态和进度

   suspend fun checkDownloadProgress(manager: DownloadManager,downloadId: Long,progressBar: ProgressBar, progressText: TextView): Boolean {while (true) {val q = DownloadManager.Query()q.setFilterById(downloadId)val cursor = manager.query(q)cursor.moveToFirst()val bytes_downloaded =cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR))val bytes_total =cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_TOTAL_SIZE_BYTES))val dl_progress = (bytes_downloaded * 100 / bytes_total)progressBar.post {progressBar.progress = dl_progressprogressText.text = "${dl_progress}%"}when (cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS))) {DownloadManager.STATUS_SUCCESSFUL -> {return true}DownloadManager.STATUS_RUNNING, DownloadManager.STATUS_PENDING -> {delay(500)}else -> {manager.remove(downloadId)return false}}}}

读取的时候用while循环去读取,发现任务状态时Pending或Running时更新一下UI,500ms后再读取,直到状态变成Fail或Success

  1. 安装apk
    android apk安装需要用到下载文件的uri ,DownloadManager通过downloadId即可获取
  val uri = downloadManager.getUriForDownloadedFile(downloadId)

然后是通过uri安装

   private fun installAPK(context: Context, apkFile: Uri) {val intent = Intent(Intent.ACTION_VIEW)if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {intent.flags = Intent.FLAG_GRANT_READ_URI_PERMISSION} else {intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK}intent.setDataAndType(apkFile, "application/vnd.android.package-archive")context.startActivity(intent)}

注意一下申请文件存储权限

三. 添加调用时机

方法封装上,添加一个是否手动调用的参数

  fun checkNewVersion(context: Context, isManual: Boolean)
  • MainActivity的onResume()中自动调用此方法检测更新
  • 当有设计检测更新的功能时,手动调用,bugly的接口调用手动调用的参数设置为true(bugly会自动显示一个toast)

完整代码

本来想在github上找个完整替代的库,但发现基本上都没有适配android12,要么错误百出。。。
贴一下代码吧,有需要的可以自己diy,商业生产的话需要调试一下bug

import android.annotation.SuppressLint
import android.app.Dialog
import android.app.DownloadManager
import android.content.Context
import android.content.Intent
import android.net.Uri
import android.os.Build
import android.os.Environment
import android.view.LayoutInflater
import android.view.View
import android.widget.ProgressBar
import android.widget.TextView
import com.jxit.manufacture.activity.MainActivity
import com.jxit.manufacture.databinding.DialogUpgradeBinding
import com.tencent.bugly.beta.Beta
import kotlinx.coroutines.*
import java.text.SimpleDateFormatclass UpgradeUtil {companion object {var isIgnoreNewVersion = falseprivate const val mTag = "UpgradeUtil"fun checkNewVersion(context: Context, isManual: Boolean) {if (!isManual && isIgnoreNewVersion) returnMainScope().launch(Dispatchers.IO) {Beta.checkUpgrade(isManual, true)delay(2000).run {var result = Beta.getUpgradeInfo()if (result == null) {MLog.d(mTag, "没有新版本")} else {MainScope().launch {var dialog = Dialog(context)val bd = DialogUpgradeBinding.inflate(LayoutInflater.from(context))bd.tvVersion.text = "版本号:${result.versionName}\n发布时间:${SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(result.publishTime)}"bd.tvFeature.text = result.newFeaturebd.tvIgnore.setOnClickListener {isIgnoreNewVersion = truedialog.dismiss()}bd.tvCancel.setOnClickListener {dialog.dismiss()}bd.tvUpgrade.setOnClickListener {val downloadManager =context.getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManagerval request = DownloadManager.Request(Uri.parse(result.apkUrl))request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS,"labApks")request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE)request.setMimeType("application/vnd.android.package-archive")val downloadId = downloadManager.enqueue(request)bd.llActions.visibility = View.GONEbd.tvProgress.text = "0%"bd.progressBar.progress = 0bd.flProgress.visibility = View.VISIBLEMainScope().launch(Dispatchers.IO) {var success = checkDownloadProgress(downloadManager,downloadId,bd.progressBar,bd.tvProgress)MainScope().launch {dialog.dismiss()if (success) {val uri =downloadManager.getUriForDownloadedFile(downloadId)installAPK(context, uri)} else {(context as MainActivity).toast("下载失败,请重试")bd.flProgress.visibility = View.GONEbd.llActions.visibility = View.VISIBLE}}}}dialog.setContentView(bd.root)dialog.show()}}}}}private fun installAPK(context: Context, apkFile: Uri) {val intent = Intent(Intent.ACTION_VIEW)if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {intent.flags = Intent.FLAG_GRANT_READ_URI_PERMISSION} else {intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK}intent.setDataAndType(apkFile, "application/vnd.android.package-archive")context.startActivity(intent)}@SuppressLint("Range")suspend fun checkDownloadProgress(manager: DownloadManager,downloadId: Long,progressBar: ProgressBar, progressText: TextView): Boolean {while (true) {val q = DownloadManager.Query()q.setFilterById(downloadId)val cursor = manager.query(q)cursor.moveToFirst()val bytes_downloaded =cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR))val bytes_total =cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_TOTAL_SIZE_BYTES))val dl_progress = (bytes_downloaded * 100 / bytes_total)progressBar.post {progressBar.progress = dl_progressprogressText.text = "${dl_progress}%"}when (cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS))) {DownloadManager.STATUS_SUCCESSFUL -> {return true}DownloadManager.STATUS_RUNNING, DownloadManager.STATUS_PENDING -> {delay(500)}else -> {manager.remove(downloadId)return false}}}}}
}

android 12 bugly升级问题解决办法相关推荐

  1. 最新的三星android版本号,三星率先公布Android 12/13升级机型名单,可惜S9/Note9被抛弃...

    三星率先公布Android 12/13升级机型名单,可惜S9/Note9被抛弃 2020-08-18 17:07:15 5点赞 5收藏 25评论 前不久发布Galaxy Note20系列手机时,三星曾 ...

  2. Invoke-customs are only supported starting with Android O (--min-api 26)问题解决办法

    在APP设置中添加了AndroidX的PreferenceFragment支持,结果Make Project出现此错误. 出现此问题是因为项目未设置Java8的支持,有两种解决方案. 第一种: 在项目 ...

  3. android 虚拟机键盘无法使用问题解决办法

    android在运行时候,发射的虚拟机键盘一直无法使用,这个问题一直遗留到现在,每次用起来都不方便,经过在网上查阅资料,这个问题终于得以解决.解决办法:创建虚拟机的时候,在hardware选项里面,点 ...

  4. android 模块不编译错误,Android 编译出错版本匹配问题解决办法

    Android 编译出错版本匹配问题解决办法 解决问题的关键在于版本匹配, compileSdkVersion compileSdkVersion targetSdkVersion 这三个参数的整数值 ...

  5. [RN] React Native 键盘管理 在Android TextInput遮盖,上移等问题解决办法

    [RN] React Native 键盘管理 在Android TextInput遮盖,上移等问题解决办法 参考文章: (1)[RN] React Native 键盘管理 在Android TextI ...

  6. ubuntu oracle 10g 安装,Ubuntu 12.04 安装Oracle 10g 全过程(完美)及问题解决办法

    PS:Ubuntu 12.04 安装Oracle 10g 全过程(完美)及问题解决办法正常情况下,完美无错..如果遇到问题,也有解决办法 1.安装前准备工作 1.1 到oracle官网下载适合自己电脑 ...

  7. android 屏幕旋转不重新加载,Android webview旋转屏幕导致页面重新加载问题解决办法...

    Android webview旋转屏幕导致页面重新加载问题解决办法 1. 在create时候加个状态判断 protected void onCreate(Bundle savedInstanceSta ...

  8. Android ScrollView嵌套ScrollView滚动的问题解决办法

    引用:http://mengsina.iteye.com/blog/1707464 http://fenglog.com/article.asp?id=449 Android ScrollView嵌套 ...

  9. android web连接问题,Android WebView或手机浏览器打开连接问题解决办法总结

    Android WebView或手机浏览器打开连接问题解决办法总结 1.通常情况下 大家可能都想使用WebView打开网页内部链接而不想再调用手机浏览器, 我们可以通过以下两种方法实现: (1)为We ...

最新文章

  1. python3迭代器和可迭代对象_一文读懂 Python3 可迭代对象、迭代器、生成器区别...
  2. Eclipse 常用快捷键(转)
  3. Crnn中文end-to-end识别
  4. XBMC源代码分析 6:视频播放器(dvdplayer)-文件头(以ffmpeg为例)
  5. 我想创业,但不懂技术怎么办
  6. 基于离线策略的强化学习(PPO)
  7. pygame游戏之旅2:创建游戏窗口界面
  8. Python开发基础(一)基本数据类型
  9. webx框架 实现文件上传保存服务器 解析
  10. 查询江苏丹阳高考成绩2021,2020年江苏县级市各大高中高考成绩回顾
  11. Kotlin和Swift语言在Redmonk榜上排名大幅提升
  12. wps文字 用WPS如何演示制作英语有声读物
  13. 如何使用Arcgis10.6在影像中画shp继而对影像做出裁剪
  14. 目前最好用的云电脑排行有哪些?免费阿里云无影云电脑
  15. 学习没有动力的解决方法
  16. 什么是随机种子(random seed)?
  17. 制作Centos7自动安装镜像(二)
  18. hp服务器启动u盘装系统,hp惠普笔记本进入bios设置u盘启动装系统的方法步骤详细教程...
  19. sublime text3使用卡顿,代码提示卡顿终极解决办法
  20. shopex仿红孩子商城模板

热门文章

  1. Kafka的生成者、消费者、broker的基本概念
  2. SELinux is preventing /usr/sbin/httpd from name_bind access on the tcp_socket port XXX
  3. css,一些经常忘掉的简单布局 笔记
  4. 练习2-3 输出倒三角图案(打印图案)
  5. Ensp配置Telnet远程登录
  6. python 词云生成鹿鼎记关键词
  7. 作为技术人,我们能为世界做些什么?
  8. 玩转TM4C1294XL(1)——安装ICDI驱动
  9. 关于父元素设置maxHeight或minHeight,子元素高度设置%的不生效的问题
  10. Clibrary | 【02】文件访问fclose、fflush、fopen、freopen、setbuf、setvbuf