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

相关文章

Linux系统中卸载与安装JDK的详细教程

《Linux系统中卸载与安装JDK的详细教程》本文详细介绍了如何在Linux系统中通过Xshell和Xftp工具连接与传输文件,然后进行JDK的安装与卸载,安装步骤包括连接Linux、传输JDK安装包... 目录1、卸载1.1 linux删除自带的JDK1.2 Linux上卸载自己安装的JDK2、安装2.1

Android中Dialog的使用详解

《Android中Dialog的使用详解》Dialog(对话框)是Android中常用的UI组件,用于临时显示重要信息或获取用户输入,本文给大家介绍Android中Dialog的使用,感兴趣的朋友一起... 目录android中Dialog的使用详解1. 基本Dialog类型1.1 AlertDialog(

Linux卸载自带jdk并安装新jdk版本的图文教程

《Linux卸载自带jdk并安装新jdk版本的图文教程》在Linux系统中,有时需要卸载预装的OpenJDK并安装特定版本的JDK,例如JDK1.8,所以本文给大家详细介绍了Linux卸载自带jdk并... 目录Ⅰ、卸载自带jdkⅡ、安装新版jdkⅠ、卸载自带jdk1、输入命令查看旧jdkrpm -qa

SpringBoot中封装Cors自动配置方式

《SpringBoot中封装Cors自动配置方式》:本文主要介绍SpringBoot中封装Cors自动配置方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录SpringBoot封装Cors自动配置背景实现步骤1. 创建 GlobalCorsProperties

idea中创建新类时自动添加注释的实现

《idea中创建新类时自动添加注释的实现》在每次使用idea创建一个新类时,过了一段时间发现看不懂这个类是用来干嘛的,为了解决这个问题,我们可以设置在创建一个新类时自动添加注释,帮助我们理解这个类的用... 目录前言:详细操作:步骤一:点击上方的 文件(File),点击&nbmyHIgsp;设置(Setti

MySQL Workbench 安装教程(保姆级)

《MySQLWorkbench安装教程(保姆级)》MySQLWorkbench是一款强大的数据库设计和管理工具,本文主要介绍了MySQLWorkbench安装教程,文中通过图文介绍的非常详细,对大... 目录前言:详细步骤:一、检查安装的数据库版本二、在官网下载对应的mysql Workbench版本,要是

Android Kotlin 高阶函数详解及其在协程中的应用小结

《AndroidKotlin高阶函数详解及其在协程中的应用小结》高阶函数是Kotlin中的一个重要特性,它能够将函数作为一等公民(First-ClassCitizen),使得代码更加简洁、灵活和可... 目录1. 引言2. 什么是高阶函数?3. 高阶函数的基础用法3.1 传递函数作为参数3.2 Lambda

Linux安装MySQL的教程

《Linux安装MySQL的教程》:本文主要介绍Linux安装MySQL的教程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录linux安装mysql1.Mysql官网2.我的存放路径3.解压mysql文件到当前目录4.重命名一下5.创建mysql用户组和用户并修

Android自定义Scrollbar的两种实现方式

《Android自定义Scrollbar的两种实现方式》本文介绍两种实现自定义滚动条的方法,分别通过ItemDecoration方案和独立View方案实现滚动条定制化,文章通过代码示例讲解的非常详细,... 目录方案一:ItemDecoration实现(推荐用于RecyclerView)实现原理完整代码实现

pip无法安装osgeo失败的问题解决

《pip无法安装osgeo失败的问题解决》本文主要介绍了pip无法安装osgeo失败的问题解决,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一... 进入官方提供的扩展包下载网站寻找版本适配的whl文件注意:要选择cp(python版本)和你py