Android app在后台静默升级,安装成功之后自动打开app

2024-05-12 18:48

本文主要是介绍Android app在后台静默升级,安装成功之后自动打开app,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

一、使用Android自带的DownloadManager远程下载APK;

    val handler = Handler()private fun downLoadApk(apkUrl: String) {//创建request对象val request: DownloadManager.Request =DownloadManager.Request(Uri.parse(apkUrl))//显示还是隐藏 隐藏加权限:DOWNLOAD_WITHOUT_NOTIFICATION//request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_HIDDEN)//设置通知栏的标题request.setTitle("下载")//设置通知栏的messagerequest.setDescription("正在下载.....")//设置下载文件类型request.setMimeType("application/vnd.android.package-archive")//设置文件存放目录request.setDestinationInExternalFilesDir(this,Environment.DIRECTORY_DOWNLOADS,"update.apk")//获取系统服务val downloadManager = getSystemService(DOWNLOAD_SERVICE) as DownloadManager//进行下载val id = downloadManager.enqueue(request)val runnable = object : Runnable {override fun run() {val cursor = downloadManager.query(DownloadManager.Query().setFilterById(id))cursor?.apply {if (moveToFirst()) {val title =getString(getColumnIndex(DownloadManager.COLUMN_TITLE))val uri =getString(getColumnIndex(DownloadManager.COLUMN_LOCAL_URI))val current =getInt(getColumnIndex(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR))val total =getInt(getColumnIndex(DownloadManager.COLUMN_TOTAL_SIZE_BYTES))LogUtil.e(current.toString())//获取下载状态信息if (getInt(getColumnIndex(DownloadManager.COLUMN_STATUS)) == DownloadManager.STATUS_SUCCESSFUL) {//下载完成handler.removeCallbacksAndMessages(null)LogUtil.e("下载完成:$uri")val file = File(uri.substring(7)RootUtil.sinlenceInstallApk(file)}}}cursor?.close()handler.postDelayed(this, 1000)}}handler.postDelayed(runnable, 1000)}

二,下载完之后,通过封装的RootUtils工具类安装重启

object RootsUtils {/*** 判断手机是否有root权限*/private fun sysHasRootPerssion(): Boolean {var printWriter: PrintWriter?var process: Process? = nulltry {process = Runtime.getRuntime().exec("su")printWriter = PrintWriter(process.outputStream)printWriter.flush()printWriter.close()val value = process.waitFor()return returnResult(value)} catch (e: Exception) {e.printStackTrace()} finally {process?.destroy()}return false}/*** root下执行cmd的返回值*/private fun returnResult(value: Int): Boolean {// 代表成功return when (value) {0 -> {true}1 -> { // 失败false}else -> { // 未知情况false}}}/*** root下静默安装*/private fun rootSlienceInstallApk(apkPath: String): Boolean {var printWriter: PrintWriter?var process: Process? = nulltry {process = Runtime.getRuntime().exec("su")printWriter = PrintWriter(process.outputStream)printWriter.println("pm install -r $apkPath")printWriter.flush()printWriter.close()execLinuxCommand()val value = process.waitFor()return returnResult(value)} catch (e: Exception) {e.printStackTrace()} finally {process?.destroy()}return false}/*** 通过Linux延时执行重启*/private fun execLinuxCommand() {val cmd = "sleep 1; am start -n com.xx.xxx/.LunchActivity"//Runtime对象val runtime = Runtime.getRuntime()try {val localProcess = runtime.exec("su")val localOutputStream = localProcess.outputStreamval localDataOutputStream = DataOutputStream(localOutputStream)localDataOutputStream.writeBytes(cmd)localDataOutputStream.flush()LogUtil.e("设备准备重启")} catch (e: IOException) {e.printStackTrace()}}fun rootInstallApk(file: File) {if (!sysHasRootPerssion()) {LogUtil.e("系统尚无Root权限")return}LogUtil.i("系统有Root权限")if (!file.exists()) {LogUtil.e("尚无APK文件")return}//静默安装if (rootSlienceInstallApk(file.path)) {LogUtil.d("静默安装成功")} else {LogUtil.e("静默安装失败!!!")}}
}

三、使用的是Android7.1已经root的,经过反复测试,是可以静默安装并且安装成功之后自动重启成功的;

四、单个应用,在安装成功app之后,这个App的进程都被杀掉了,根本收不到广播重启打开了,如果非要使用广播打开的话,需要另外做一个无UI的App,做成双守护进程,把版本升级任务都交给它,通过它重启打开已安装的App,广播代码如下;

class BootReceiver : BroadcastReceiver() {override fun onReceive(context: Context, intent: Intent) {val action = intent.actionintent.dataString?.substring(8)?.apply {LogUtil.d("BootReceiver onReceive():接收到Intent.getAction() = " + intent.action + " , 包名 = " + intent.dataString)/*** 接收安装广播* android.intent.action.PACKAGE_ADDED*/if (action == Intent.ACTION_PACKAGE_ADDED) {LogUtil.d("BootReceiver onReceive():安装了:" + this + "包名的程序")}/*** 接收卸载广播* android.intent.action.PACKAGE_REMOVED*/if (action == Intent.ACTION_PACKAGE_REMOVED) {LogUtil.d("BootReceiver onReceive():卸载了:" + this + "包名的程序")}/*** 接收更新广播* android.intent.action.PACKAGE_REPLACED*/if (action == Intent.ACTION_PACKAGE_REPLACED) {LogUtil.d("BootReceiver onReceive():更新了:" + this + "包名的程序,context.getPackageName()=" + context.packageName)//更新的软件包名是否和我的工程一致if (this == context.packageName) {//更新完后打开val it = Intent()it.setClassName(this, "$this.xxxActivity") //启动类it.action = "android.intent.action.MAIN" //首个启动类actionit.addCategory("android.intent.category.LAUNCHER") //放入程序列表//it.addCategory("android.intent.category.HOME");                           //作为桌面,Home键打开,可做启动默认程序it.addCategory("android.intent.category.DEFAULT") //隐式打开,如果没main可有,如果main可有可无it.flags = Intent.FLAG_ACTIVITY_NEW_TASKcontext.startActivity(it)}}/*** 接收重启广播* android.intent.action.PACKAGE_REPLACED*/if (action == Intent.ACTION_PACKAGE_RESTARTED) {LogUtil.d("BootReceiver onReceive():重启了:" + this + "包名的程序")}/*** 接收开机广播* android.intent.action.BOOT_COMPLETED*/if (action == Intent.ACTION_BOOT_COMPLETED) {LogUtil.d("BootReceiver onReceive():仪器开机,开启了:" + this + "包名的程序")}}}
}
        <receiverandroid:name=".install.BootReceiver"android:label="@string/app_name"> <!-- app open/delete/upgrade/completed receiver --><intent-filter><action android:name="android.intent.action.PACKAGE_ADDED" /> <!-- add --><action android:name="android.intent.action.PACKAGE_REPLACED" /> <!-- update --><action android:name="android.intent.action.PACKAGE_REMOVED" /> <!-- delete --><action android:name="android.intent.action.PACKAGE_RESTARTED" /> <!-- restart --><action android:name="android.intent.action.BOOT_COMPLETED" /> <!-- completed --><data android:scheme="package" /></intent-filter></receiver>

五、在静默安装之后执行重启代码

    /*** 执行此命令后:BootReceiver 监听到Intent.ACTION_PACKAGE_REPLACED,然后自启动* */fun rootStartApk(packageName: String, activityName: String): Boolean {val isSuccess = falsevar process: Process? = nulltry {process = Runtime.getRuntime().exec("su")val printWriter = PrintWriter(process.outputStream)printWriter.println("am start -n $packageName/.$activityName")printWriter.flush()printWriter.close()val value = process.waitFor()return returnResult(value)} catch (e: java.lang.Exception) {e.printStackTrace()} finally {process?.destroy()}return isSuccess}

 

这篇关于Android app在后台静默升级,安装成功之后自动打开app的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/983447

相关文章

MyBatis Plus实现时间字段自动填充的完整方案

《MyBatisPlus实现时间字段自动填充的完整方案》在日常开发中,我们经常需要记录数据的创建时间和更新时间,传统的做法是在每次插入或更新操作时手动设置这些时间字段,这种方式不仅繁琐,还容易遗漏,... 目录前言解决目标技术栈实现步骤1. 实体类注解配置2. 创建元数据处理器3. 服务层代码优化填充机制详

深入浅出Spring中的@Autowired自动注入的工作原理及实践应用

《深入浅出Spring中的@Autowired自动注入的工作原理及实践应用》在Spring框架的学习旅程中,@Autowired无疑是一个高频出现却又让初学者头疼的注解,它看似简单,却蕴含着Sprin... 目录深入浅出Spring中的@Autowired:自动注入的奥秘什么是依赖注入?@Autowired

Debian 13升级后网络转发等功能异常怎么办? 并非错误而是管理机制变更

《Debian13升级后网络转发等功能异常怎么办?并非错误而是管理机制变更》很多朋友反馈,更新到Debian13后网络转发等功能异常,这并非BUG而是Debian13Trixie调整... 日前 Debian 13 Trixie 发布后已经有众多网友升级到新版本,只不过升级后发现某些功能存在异常,例如网络转

RabbitMQ 延时队列插件安装与使用示例详解(基于 Delayed Message Plugin)

《RabbitMQ延时队列插件安装与使用示例详解(基于DelayedMessagePlugin)》本文详解RabbitMQ通过安装rabbitmq_delayed_message_exchan... 目录 一、什么是 RabbitMQ 延时队列? 二、安装前准备✅ RabbitMQ 环境要求 三、安装延时队

Ubuntu如何升级Python版本

《Ubuntu如何升级Python版本》Ubuntu22.04Docker中,安装Python3.11后,使用update-alternatives设置为默认版本,最后用python3-V验证... 目China编程录问题描述前提环境解决方法总结问题描述Ubuntu22.04系统自带python3.10,想升级

解决升级JDK报错:module java.base does not“opens java.lang.reflect“to unnamed module问题

《解决升级JDK报错:modulejava.basedoesnot“opensjava.lang.reflect“tounnamedmodule问题》SpringBoot启动错误源于Jav... 目录问题描述原因分析解决方案总结问题描述启动sprintboot时报以下错误原因分析编程异js常是由Ja

Android协程高级用法大全

《Android协程高级用法大全》这篇文章给大家介绍Android协程高级用法大全,本文结合实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友跟随小编一起学习吧... 目录1️⃣ 协程作用域(CoroutineScope)与生命周期绑定Activity/Fragment 中手

linux系统上安装JDK8全过程

《linux系统上安装JDK8全过程》文章介绍安装JDK的必要性及Linux下JDK8的安装步骤,包括卸载旧版本、下载解压、配置环境变量等,强调开发需JDK,运行可选JRE,现JDK已集成JRE... 目录为什么要安装jdk?1.查看linux系统是否有自带的jdk:2.下载jdk压缩包2.解压3.配置环境

基于Redis自动过期的流处理暂停机制

《基于Redis自动过期的流处理暂停机制》基于Redis自动过期的流处理暂停机制是一种高效、可靠且易于实现的解决方案,防止延时过大的数据影响实时处理自动恢复处理,以避免积压的数据影响实时性,下面就来详... 目录核心思路代码实现1. 初始化Redis连接和键前缀2. 接收数据时检查暂停状态3. 检测到延时过

Python库 Django 的简介、安装、用法入门教程

《Python库Django的简介、安装、用法入门教程》Django是Python最流行的Web框架之一,它帮助开发者快速、高效地构建功能强大的Web应用程序,接下来我们将从简介、安装到用法详解,... 目录一、Django 简介 二、Django 的安装教程 1. 创建虚拟环境2. 安装Django三、创