本文主要是介绍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的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!