添加版本下载代码
This commit is contained in:
parent
201a60cf65
commit
36e2b55b07
@ -20,6 +20,7 @@ import androidx.annotation.RequiresPermission
|
||||
import androidx.core.app.ActivityCompat
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import com.blankj.utilcode.constant.PermissionConstants
|
||||
import com.blankj.utilcode.util.AppUtils
|
||||
import com.blankj.utilcode.util.FileUtils
|
||||
import com.blankj.utilcode.util.GsonUtils
|
||||
import com.blankj.utilcode.util.LogUtils
|
||||
@ -46,6 +47,7 @@ import com.zs.smarthuman.sherpa.VoiceState
|
||||
import com.zs.smarthuman.toast.Toaster
|
||||
import com.zs.smarthuman.utils.AudioDebugUtil
|
||||
import com.zs.smarthuman.utils.AudioPcmUtil
|
||||
import com.zs.smarthuman.utils.DangerousUtils
|
||||
|
||||
import com.zs.smarthuman.utils.UnityPlayerHolder
|
||||
import com.zs.smarthuman.utils.ViewSlideAnimator
|
||||
@ -55,10 +57,12 @@ import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.SupervisorJob
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.flow.catch
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import rxhttp.awaitResult
|
||||
import rxhttp.toAwaitString
|
||||
import rxhttp.toDownloadFlow
|
||||
import rxhttp.wrapper.param.RxHttp
|
||||
import rxhttp.wrapper.param.toAwaitResponse
|
||||
import java.io.File
|
||||
@ -449,6 +453,42 @@ class MainActivity : BaseViewModelActivity<ActivityMainBinding, MainViewModel>()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载并且安装
|
||||
*/
|
||||
private suspend fun downloadApk(apkUrl: String) {
|
||||
val destPath =
|
||||
getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS)?.path + "/" + "smartHuman.apk"
|
||||
RxHttp.get(apkUrl)
|
||||
.toDownloadFlow(destPath)
|
||||
.onProgress {
|
||||
lifecycleScope.launch(Dispatchers.Main) {
|
||||
|
||||
}
|
||||
|
||||
}.catch {
|
||||
lifecycleScope.launch(Dispatchers.Main) {
|
||||
|
||||
}
|
||||
}.collect {
|
||||
//下载完成
|
||||
if (AppUtils.isAppRoot()) {
|
||||
lifecycleScope.launch(Dispatchers.Main) {
|
||||
DangerousUtils.installAppSilent(it, "-r")
|
||||
|
||||
}
|
||||
} else {
|
||||
lifecycleScope.launch(Dispatchers.Main) {
|
||||
AppUtils.installApp(it)
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
|
||||
383
app/src/main/java/com/zs/smarthuman/utils/DangeroutUtils.kt
Normal file
383
app/src/main/java/com/zs/smarthuman/utils/DangeroutUtils.kt
Normal file
@ -0,0 +1,383 @@
|
||||
package com.zs.smarthuman.utils
|
||||
|
||||
import android.Manifest.permission
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.PendingIntent
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Build
|
||||
import android.os.PowerManager
|
||||
import android.telephony.SmsManager
|
||||
import android.telephony.TelephonyManager
|
||||
import android.text.TextUtils
|
||||
import android.util.Log
|
||||
import androidx.annotation.RequiresPermission
|
||||
import com.blankj.utilcode.util.IntentUtils
|
||||
import com.blankj.utilcode.util.LogUtils
|
||||
import com.blankj.utilcode.util.ShellUtils
|
||||
import com.blankj.utilcode.util.Utils
|
||||
import java.io.File
|
||||
import kotlin.jvm.javaClass
|
||||
import kotlin.jvm.javaPrimitiveType
|
||||
import kotlin.text.contains
|
||||
import kotlin.text.toLowerCase
|
||||
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* author: Blankj
|
||||
* blog : http://blankj.com
|
||||
* time : 2019/06/29
|
||||
* desc :
|
||||
</pre> *
|
||||
*/
|
||||
class DangerousUtils private constructor() {
|
||||
companion object {
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// AppUtils
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
/**
|
||||
* Install the app silently.
|
||||
*
|
||||
* Without root permission must hold
|
||||
* `android:sharedUserId="android.uid.shell"` and
|
||||
* `<uses-permission android:name="android.permission.INSTALL_PACKAGES" />`
|
||||
*
|
||||
* @param filePath The path of file.
|
||||
* @return `true`: success<br></br>`false`: fail
|
||||
*/
|
||||
fun installAppSilent(filePath: String): Boolean {
|
||||
return installAppSilent(getFileByPath(filePath), null)
|
||||
}
|
||||
|
||||
/**
|
||||
* Install the app silently.
|
||||
*
|
||||
* Without root permission must hold
|
||||
* `android:sharedUserId="android.uid.shell"` and
|
||||
* `<uses-permission android:name="android.permission.INSTALL_PACKAGES" />`
|
||||
*
|
||||
* @param filePath The path of file.
|
||||
* @param params The params of installation(e.g.,`-r`, `-s`).
|
||||
* @return `true`: success<br></br>`false`: fail
|
||||
*/
|
||||
fun installAppSilent(filePath: String, params: String?): Boolean {
|
||||
return installAppSilent(getFileByPath(filePath), params)
|
||||
}
|
||||
/**
|
||||
* Install the app silently.
|
||||
*
|
||||
* Without root permission must hold
|
||||
* `android:sharedUserId="android.uid.shell"` and
|
||||
* `<uses-permission android:name="android.permission.INSTALL_PACKAGES" />`
|
||||
*
|
||||
* @param file The file.
|
||||
* @param params The params of installation(e.g.,`-r`, `-s`).
|
||||
* @param isRooted True to use root, false otherwise.
|
||||
* @return `true`: success<br></br>`false`: fail
|
||||
*/
|
||||
/**
|
||||
* Install the app silently.
|
||||
*
|
||||
* Without root permission must hold
|
||||
* `android:sharedUserId="android.uid.shell"` and
|
||||
* `<uses-permission android:name="android.permission.INSTALL_PACKAGES" />`
|
||||
*
|
||||
* @param file The file.
|
||||
* @param params The params of installation(e.g.,`-r`, `-s`).
|
||||
* @return `true`: success<br></br>`false`: fail
|
||||
*/
|
||||
/**
|
||||
* Install the app silently.
|
||||
*
|
||||
* Without root permission must hold
|
||||
* `android:sharedUserId="android.uid.shell"` and
|
||||
* `<uses-permission android:name="android.permission.INSTALL_PACKAGES" />`
|
||||
*
|
||||
* @param file The file.
|
||||
* @return `true`: success<br></br>`false`: fail
|
||||
*/
|
||||
@JvmOverloads
|
||||
fun installAppSilent(
|
||||
file: File?,
|
||||
params: String? = null,
|
||||
isRooted: Boolean = isDeviceRooted
|
||||
): Boolean {
|
||||
if (!isFileExists(file)) return false
|
||||
val filePath = Char.toString() + file!!.absolutePath + '"'
|
||||
val command = ("LD_LIBRARY_PATH=/vendor/lib*:/system/lib* pm install " +
|
||||
(if (params == null) "" else "$params ")
|
||||
+ filePath)
|
||||
val commandResult = ShellUtils.execCmd(command, isRooted)
|
||||
return if (commandResult.successMsg != null
|
||||
&& commandResult.successMsg.toLowerCase().contains("success")
|
||||
) {
|
||||
true
|
||||
} else {
|
||||
Log.e(
|
||||
"AppUtils", "installAppSilent successMsg: " + commandResult.successMsg +
|
||||
", errorMsg: " + commandResult.errorMsg
|
||||
)
|
||||
false
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Uninstall the app silently.
|
||||
*
|
||||
* Without root permission must hold
|
||||
* `android:sharedUserId="android.uid.shell"` and
|
||||
* `<uses-permission android:name="android.permission.DELETE_PACKAGES" />`
|
||||
*
|
||||
* @param packageName The name of the package.
|
||||
* @param isKeepData Is keep the data.
|
||||
* @param isRooted True to use root, false otherwise.
|
||||
* @return `true`: success<br></br>`false`: fail
|
||||
*/
|
||||
/**
|
||||
* Uninstall the app silently.
|
||||
*
|
||||
* Without root permission must hold
|
||||
* `android:sharedUserId="android.uid.shell"` and
|
||||
* `<uses-permission android:name="android.permission.DELETE_PACKAGES" />`
|
||||
*
|
||||
* @param packageName The name of the package.
|
||||
* @param isKeepData Is keep the data.
|
||||
* @return `true`: success<br></br>`false`: fail
|
||||
*/
|
||||
/**
|
||||
* Uninstall the app silently.
|
||||
*
|
||||
* Without root permission must hold
|
||||
* `android:sharedUserId="android.uid.shell"` and
|
||||
* `<uses-permission android:name="android.permission.DELETE_PACKAGES" />`
|
||||
*
|
||||
* @param packageName The name of the package.
|
||||
* @return `true`: success<br></br>`false`: fail
|
||||
*/
|
||||
@JvmOverloads
|
||||
fun uninstallAppSilent(
|
||||
packageName: String,
|
||||
isKeepData: Boolean = false,
|
||||
isRooted: Boolean = isDeviceRooted
|
||||
): Boolean {
|
||||
if (isSpace(packageName)) return false
|
||||
val command = ("LD_LIBRARY_PATH=/vendor/lib*:/system/lib* pm uninstall "
|
||||
+ (if (isKeepData) "-k " else "")
|
||||
+ packageName)
|
||||
val commandResult = ShellUtils.execCmd(command, isRooted)
|
||||
return if (commandResult.successMsg != null
|
||||
&& commandResult.successMsg.toLowerCase().contains("success")
|
||||
) {
|
||||
true
|
||||
} else {
|
||||
Log.e(
|
||||
"AppUtils", "uninstallAppSilent successMsg: " + commandResult.successMsg +
|
||||
", errorMsg: " + commandResult.errorMsg
|
||||
)
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
private fun isFileExists(file: File?): Boolean {
|
||||
return file != null && file.exists()
|
||||
}
|
||||
|
||||
private fun getFileByPath(filePath: String): File? {
|
||||
return if (isSpace(filePath)) null else File(filePath)
|
||||
}
|
||||
|
||||
private fun isSpace(s: String?): Boolean {
|
||||
if (s == null) return true
|
||||
var i = 0
|
||||
val len = s.length
|
||||
while (i < len) {
|
||||
if (!Character.isWhitespace(s[i])) {
|
||||
return false
|
||||
}
|
||||
++i
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
private val isDeviceRooted: Boolean
|
||||
private get() {
|
||||
val su = "su"
|
||||
val locations = arrayOf(
|
||||
"/system/bin/",
|
||||
"/system/xbin/",
|
||||
"/sbin/",
|
||||
"/system/sd/xbin/",
|
||||
"/system/bin/failsafe/",
|
||||
"/data/local/xbin/",
|
||||
"/data/local/bin/",
|
||||
"/data/local/",
|
||||
"/system/sbin/",
|
||||
"/usr/bin/",
|
||||
"/vendor/bin/"
|
||||
)
|
||||
for (location in locations) {
|
||||
if (File(location + su).exists()) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// DeviceUtils
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
/**
|
||||
* Shutdown the device
|
||||
*
|
||||
* Requires root permission
|
||||
* or hold `android:sharedUserId="android.uid.system"`,
|
||||
* `<uses-permission android:name="android.permission.SHUTDOWN" />`
|
||||
* in manifest.
|
||||
*
|
||||
* @return `true`: success<br></br>`false`: fail
|
||||
*/
|
||||
fun shutdown(): Boolean {
|
||||
return try {
|
||||
val result = ShellUtils.execCmd("reboot -p", true)
|
||||
if (result.result == 0) return true
|
||||
Utils.getApp()
|
||||
.startActivity(IntentUtils.getShutdownIntent())
|
||||
true
|
||||
} catch (e: Exception) {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reboot the device.
|
||||
*
|
||||
* Requires root permission
|
||||
* or hold `android:sharedUserId="android.uid.system"` in manifest.
|
||||
*
|
||||
* @return `true`: success<br></br>`false`: fail
|
||||
*/
|
||||
fun reboot(): Boolean {
|
||||
return try {
|
||||
val result = ShellUtils.execCmd("reboot", true)
|
||||
if (result.result == 0) return true
|
||||
val intent = Intent(Intent.ACTION_REBOOT)
|
||||
intent.putExtra("nowait", 1)
|
||||
intent.putExtra("interval", 1)
|
||||
intent.putExtra("window", 0)
|
||||
Utils.getApp().sendBroadcast(intent)
|
||||
true
|
||||
} catch (e: Exception) {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reboot the device.
|
||||
*
|
||||
* Requires root permission
|
||||
* or hold `android:sharedUserId="android.uid.system"`,
|
||||
* `<uses-permission android:name="android.permission.REBOOT" />`
|
||||
*
|
||||
* @param reason code to pass to the kernel (e.g., "recovery") to
|
||||
* request special boot modes, or null.
|
||||
* @return `true`: success<br></br>`false`: fail
|
||||
*/
|
||||
@SuppressLint("MissingPermission")
|
||||
fun reboot(reason: String?): Boolean {
|
||||
return try {
|
||||
val pm = Utils.getApp()
|
||||
.getSystemService(Context.POWER_SERVICE) as PowerManager
|
||||
pm.reboot(reason)
|
||||
true
|
||||
} catch (e: Exception) {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reboot the device to recovery.
|
||||
*
|
||||
* Requires root permission.
|
||||
*
|
||||
* @return `true`: success<br></br>`false`: fail
|
||||
*/
|
||||
fun reboot2Recovery(): Boolean {
|
||||
val result = ShellUtils.execCmd("reboot recovery", true)
|
||||
return result.result == 0
|
||||
}
|
||||
|
||||
/**
|
||||
* Reboot the device to bootloader.
|
||||
*
|
||||
* Requires root permission.
|
||||
*
|
||||
* @return `true`: success<br></br>`false`: fail
|
||||
*/
|
||||
fun reboot2Bootloader(): Boolean {
|
||||
val result = ShellUtils.execCmd("reboot bootloader", true)
|
||||
return result.result == 0
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable or disable mobile data.
|
||||
*
|
||||
* Must hold `android:sharedUserId="android.uid.system"`,
|
||||
* `<uses-permission android:name="android.permission.MODIFY_PHONE_STATE" />`
|
||||
*
|
||||
* @param enabled True to enabled, false otherwise.
|
||||
* @return `true`: success<br></br>`false`: fail
|
||||
*/
|
||||
@RequiresPermission(permission.MODIFY_PHONE_STATE)
|
||||
fun setMobileDataEnabled(enabled: Boolean): Boolean {
|
||||
try {
|
||||
val tm = Utils.getApp()
|
||||
.getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
tm.isDataEnabled = enabled
|
||||
return true
|
||||
}
|
||||
val setDataEnabledMethod = tm.javaClass.getDeclaredMethod(
|
||||
"setDataEnabled",
|
||||
Boolean::class.javaPrimitiveType
|
||||
)
|
||||
setDataEnabledMethod.invoke(tm, enabled)
|
||||
return true
|
||||
} catch (e: Exception) {
|
||||
Log.e("NetworkUtils", "setMobileDataEnabled: ", e)
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
/**
|
||||
* Send sms silently.
|
||||
*
|
||||
* Must hold `<uses-permission android:name="android.permission.SEND_SMS" />`
|
||||
*
|
||||
* @param phoneNumber The phone number.
|
||||
* @param content The content.
|
||||
*/
|
||||
@SuppressLint("UnspecifiedImmutableFlag")
|
||||
@RequiresPermission(permission.SEND_SMS)
|
||||
fun sendSmsSilent(phoneNumber: String?, content: String) {
|
||||
if (TextUtils.isEmpty(content)) return
|
||||
val sentIntent = PendingIntent.getBroadcast(
|
||||
Utils.getApp(),
|
||||
0,
|
||||
Intent("send"),
|
||||
0
|
||||
)
|
||||
val smsManager = SmsManager.getDefault()
|
||||
if (content.length >= 70) {
|
||||
val ms: List<String> = smsManager.divideMessage(content)
|
||||
for (str in ms) {
|
||||
smsManager.sendTextMessage(phoneNumber, null, str, sentIntent, null)
|
||||
}
|
||||
} else {
|
||||
smsManager.sendTextMessage(phoneNumber, null, content, sentIntent, null)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
init {
|
||||
throw kotlin.UnsupportedOperationException("u can't instantiate me...")
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user