android 12 bugly升级问题解决办法

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


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

只能借助Bugly的后台和接口,自己撸一个简单的升级功能。
大概效果图如下
在这里插入图片描述

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

  Beta.autoCheckUpgrade = false
  Beta.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">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@color/white"
        android:orientation="vertical">

        <LinearLayout
            android: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">


            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="发现新版本"
                android:textColor="@color/white"
                android:textSize="20dp" />


            <TextView
                android: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>

        <TextView
            android: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" />

        <LinearLayout
            android: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">

            <ProgressBar
                android: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" />

            <TextView
                android:id="@+id/tv_progress"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginStart="5dp"
                android:text="0%" />

        </LinearLayout>

        <LinearLayout
            android:id="@+id/ll_actions"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center_vertical"
            android:orientation="horizontal"
            android:padding="20dp">

            <TextView
                android: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" />

            <TextView
                android: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" />

            <View
                android:layout_width="0dp"
                android:layout_height="0dp"
                android:layout_weight="1" />

            <TextView
                android: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_progress
                    progressText.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.SimpleDateFormat


class UpgradeUtil {

    companion object {
        var isIgnoreNewVersion = false
        private const val mTag = "UpgradeUtil"
        fun checkNewVersion(context: Context, isManual: Boolean) {
            if (!isManual && isIgnoreNewVersion) return
            MainScope().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.newFeature
                            bd.tvIgnore.setOnClickListener {
                                isIgnoreNewVersion = true
                                dialog.dismiss()
                            }
                            bd.tvCancel.setOnClickListener {
                                dialog.dismiss()
                            }
                            bd.tvUpgrade.setOnClickListener {
                                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)
                                bd.llActions.visibility = View.GONE
                                bd.tvProgress.text = "0%"
                                bd.progressBar.progress = 0
                                bd.flProgress.visibility = View.VISIBLE
                                MainScope().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.GONE
                                            bd.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_progress
                    progressText.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
                    }
                }
            }
        }
    }
}
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值