改机流程
This commit is contained in:
parent
727df6f21f
commit
79598df25d
|
@ -51,10 +51,12 @@
|
||||||
<provider
|
<provider
|
||||||
android:name=".provider.DeviceInfoProvider"
|
android:name=".provider.DeviceInfoProvider"
|
||||||
android:authorities="com.android.grape.deviceinfo.provider"
|
android:authorities="com.android.grape.deviceinfo.provider"
|
||||||
|
android:enabled="true"
|
||||||
android:exported="true">
|
android:exported="true">
|
||||||
</provider>
|
</provider>
|
||||||
<activity
|
<activity
|
||||||
android:name=".MainActivity"
|
android:name=".MainActivity"
|
||||||
|
android:launchMode="singleTask"
|
||||||
android:exported="true">
|
android:exported="true">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.MAIN" />
|
<action android:name="android.intent.action.MAIN" />
|
||||||
|
@ -124,6 +126,10 @@
|
||||||
android:name="android.accessibilityservice"
|
android:name="android.accessibilityservice"
|
||||||
android:resource="@xml/accessibility_service_config" />
|
android:resource="@xml/accessibility_service_config" />
|
||||||
</service>
|
</service>
|
||||||
|
<service android:name="com.android.grape.job.StartVpnPortJobService"
|
||||||
|
android:enabled="true"
|
||||||
|
android:exported="true"
|
||||||
|
android:permission="android.permission.BIND_JOB_SERVICE"/>
|
||||||
</application>
|
</application>
|
||||||
|
|
||||||
</manifest>
|
</manifest>
|
|
@ -3,7 +3,6 @@ package com.android.grape
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.util.Log
|
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.activity.enableEdgeToEdge
|
import androidx.activity.enableEdgeToEdge
|
||||||
import androidx.activity.viewModels
|
import androidx.activity.viewModels
|
||||||
|
@ -13,29 +12,26 @@ import androidx.core.view.ViewCompat
|
||||||
import androidx.core.view.WindowInsetsCompat
|
import androidx.core.view.WindowInsetsCompat
|
||||||
import com.android.grape.databinding.ActivityMainBinding
|
import com.android.grape.databinding.ActivityMainBinding
|
||||||
import com.android.grape.job.MonitorService
|
import com.android.grape.job.MonitorService
|
||||||
import com.android.grape.provider.DeviceDataAccessor
|
import com.android.grape.service.SocketServer
|
||||||
import com.android.grape.provider.DeviceInfoHelper
|
|
||||||
import com.android.grape.util.ClashUtil
|
import com.android.grape.util.ClashUtil
|
||||||
import com.android.grape.util.MockTools
|
import com.android.grape.util.MockTools
|
||||||
import com.android.grape.util.NotificationPermissionHandler
|
import com.android.grape.util.NotificationPermissionHandler
|
||||||
import com.android.grape.util.ScriptUtil
|
import com.android.grape.util.ScriptUtil
|
||||||
import com.android.grape.util.ShellUtils
|
|
||||||
import com.android.grape.util.StoragePermissionHelper
|
import com.android.grape.util.StoragePermissionHelper
|
||||||
import com.android.grape.util.Util
|
|
||||||
import com.android.grape.util.Util.AUTO_JSPACKAGENAME
|
|
||||||
import com.android.grape.util.Util.killRecordProcess
|
import com.android.grape.util.Util.killRecordProcess
|
||||||
import com.google.gson.Gson
|
|
||||||
|
|
||||||
class MainActivity : AppCompatActivity() {
|
class MainActivity : AppCompatActivity() {
|
||||||
private val viewModel by viewModels<MainViewModel>()
|
private val viewModel by viewModels<MainViewModel>()
|
||||||
private lateinit var viewBinding: ActivityMainBinding
|
private lateinit var viewBinding: ActivityMainBinding
|
||||||
private lateinit var permissionHandler: NotificationPermissionHandler
|
private lateinit var permissionHandler: NotificationPermissionHandler
|
||||||
|
private lateinit var socketServer: SocketServer
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
enableEdgeToEdge()
|
enableEdgeToEdge()
|
||||||
init()
|
init()
|
||||||
viewBinding = ActivityMainBinding.inflate(layoutInflater)
|
viewBinding = ActivityMainBinding.inflate(layoutInflater)
|
||||||
setContentView(viewBinding.root)
|
setContentView(viewBinding.root)
|
||||||
|
socketServer = SocketServer(8888)
|
||||||
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main)) { v, insets ->
|
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main)) { v, insets ->
|
||||||
val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
|
val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
|
||||||
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom)
|
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom)
|
||||||
|
@ -45,13 +41,22 @@ class MainActivity : AppCompatActivity() {
|
||||||
ScriptUtil.registerScriptResultReceiver()
|
ScriptUtil.registerScriptResultReceiver()
|
||||||
viewBinding.start.setOnClickListener {
|
viewBinding.start.setOnClickListener {
|
||||||
MonitorService.onEvent(MainApplication.instance)
|
MonitorService.onEvent(MainApplication.instance)
|
||||||
// DeviceDataAccessor.saveDeviceInfo(this, DeviceInfoHelper.getDeviceId(this))
|
|
||||||
}
|
}
|
||||||
viewBinding.stop.setOnClickListener {
|
viewBinding.stop.setOnClickListener {
|
||||||
killRecordProcess(this, packageName)
|
killRecordProcess(this, packageName)
|
||||||
// DeviceDataAccessor.deleteDeviceInfo(this, DeviceInfoHelper.getDeviceId(this))
|
// val deviceInfo = DeviceDataAccessor.getDeviceInfo(this, DeviceInfoHelper.getDeviceId())
|
||||||
// val deviceInfo = DeviceDataAccessor.getDeviceInfo(this, DeviceInfoHelper.getDeviceId(this))
|
// FileUtils.writeDevice("com.headway.books", deviceInfo?:"")
|
||||||
// Log.d("TAG", "onCreate: ${Gson().toJson(deviceInfo?:"")}")
|
// socketServer.start { client, message ->
|
||||||
|
// Log.d("Server", "收到消息: $message")
|
||||||
|
//
|
||||||
|
// // 处理消息并回复
|
||||||
|
// val response = "服务器已收到: $message"
|
||||||
|
// runOnUiThread {
|
||||||
|
// findViewById<TextView>(R.id.text).append("$message\n")
|
||||||
|
// }
|
||||||
|
// socketServer.sendToClient(client, deviceInfo?:"没有设备信息")
|
||||||
|
// }
|
||||||
|
// FileUtils.runPlugin("com.headway.books")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -63,6 +68,7 @@ class MainActivity : AppCompatActivity() {
|
||||||
|
|
||||||
override fun onDestroy() {
|
override fun onDestroy() {
|
||||||
super.onDestroy()
|
super.onDestroy()
|
||||||
|
// socketServer.stop()
|
||||||
ClashUtil.unregisterReceiver(this)
|
ClashUtil.unregisterReceiver(this)
|
||||||
ScriptUtil.unregisterScriptResultReceiver()
|
ScriptUtil.unregisterScriptResultReceiver()
|
||||||
}
|
}
|
||||||
|
|
|
@ -95,7 +95,8 @@ data class Device(
|
||||||
var scO: String = "",
|
var scO: String = "",
|
||||||
var sdk: String = "",
|
var sdk: String = "",
|
||||||
var sdkVer: String = "",
|
var sdkVer: String = "",
|
||||||
var sensor: List<Sensor> = listOf(),
|
@Transient
|
||||||
|
var sensor: JSONArray = JSONArray(),
|
||||||
var sensorReset: Int = 0,
|
var sensorReset: Int = 0,
|
||||||
@SerializedName("sensor_size")
|
@SerializedName("sensor_size")
|
||||||
var sensorSize: Int = 0,
|
var sensorSize: Int = 0,
|
||||||
|
@ -115,7 +116,7 @@ data class Device(
|
||||||
){
|
){
|
||||||
fun toJson(): String {
|
fun toJson(): String {
|
||||||
return JSONObject().apply {
|
return JSONObject().apply {
|
||||||
put("sensors", JSONArray(sensor))
|
put("sensors", sensor)
|
||||||
put("arch", arch)
|
put("arch", arch)
|
||||||
put("cpu_abi", cpuAbi)
|
put("cpu_abi", cpuAbi)
|
||||||
put("cpu_abi2", cpuAbi2)
|
put("cpu_abi2", cpuAbi2)
|
||||||
|
|
|
@ -6,6 +6,7 @@ import android.os.Handler
|
||||||
import android.os.Looper
|
import android.os.Looper
|
||||||
import androidx.core.app.JobIntentService
|
import androidx.core.app.JobIntentService
|
||||||
import com.android.grape.util.ScriptUtil
|
import com.android.grape.util.ScriptUtil
|
||||||
|
import com.android.grape.util.Util
|
||||||
|
|
||||||
class AutoJobService : JobIntentService() {
|
class AutoJobService : JobIntentService() {
|
||||||
override fun onHandleWork(intent: Intent) {
|
override fun onHandleWork(intent: Intent) {
|
||||||
|
@ -15,7 +16,7 @@ class AutoJobService : JobIntentService() {
|
||||||
Handler(Looper.getMainLooper()).postDelayed({
|
Handler(Looper.getMainLooper()).postDelayed({
|
||||||
ScriptUtil.execScript(
|
ScriptUtil.execScript(
|
||||||
this@AutoJobService,
|
this@AutoJobService,
|
||||||
"/sdcard/script/main.js"
|
"/sdcard/script/${Util.recordPackageName}/main.js"
|
||||||
)
|
)
|
||||||
}, 2000L)
|
}, 2000L)
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -24,12 +24,9 @@ class MonitorService : JobIntentService() {
|
||||||
try {
|
try {
|
||||||
val apkRoot = "chmod 777 $packageCodePath"
|
val apkRoot = "chmod 777 $packageCodePath"
|
||||||
MockTools.exec(apkRoot)
|
MockTools.exec(apkRoot)
|
||||||
Log.i(TAG, "set to top")
|
|
||||||
Util.setTopApp(this)
|
|
||||||
|
|
||||||
|
|
||||||
Log.i(TAG, "auto stop vpn")
|
Log.i(TAG, "auto stop vpn")
|
||||||
ClashUtil.stopProxy(this)
|
ClashUtil.switchProxyGroup("PROXY", "DIRECT", "http://127.0.0.1:6170")
|
||||||
Thread.sleep(3000)
|
Thread.sleep(3000)
|
||||||
|
|
||||||
if (Util.clickTime > 0L) {
|
if (Util.clickTime > 0L) {
|
||||||
|
|
|
@ -2,10 +2,14 @@ package com.android.grape.job
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
|
import android.text.TextUtils
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import androidx.core.app.JobIntentService
|
import androidx.core.app.JobIntentService
|
||||||
import com.android.grape.net.ChangeCallBack
|
import com.android.grape.net.ChangeCallBack
|
||||||
|
import com.android.grape.provider.DeviceDataAccessor
|
||||||
|
import com.android.grape.provider.DeviceInfoHelper
|
||||||
import com.android.grape.util.ChangeDeviceInfoUtil
|
import com.android.grape.util.ChangeDeviceInfoUtil
|
||||||
|
import com.android.grape.util.FileUtils
|
||||||
import com.android.grape.util.MockTools
|
import com.android.grape.util.MockTools
|
||||||
import com.android.grape.util.ServiceUtils
|
import com.android.grape.util.ServiceUtils
|
||||||
import com.android.grape.util.Util
|
import com.android.grape.util.Util
|
||||||
|
@ -23,25 +27,26 @@ class OpenAppService : JobIntentService() {
|
||||||
ServiceUtils.setEnableApp("com.google.android.webview", true)
|
ServiceUtils.setEnableApp("com.google.android.webview", true)
|
||||||
ServiceUtils.setEnableApp("com.android.chrome", true)
|
ServiceUtils.setEnableApp("com.android.chrome", true)
|
||||||
ServiceUtils.setEnableApp("com.UCMobile", true)
|
ServiceUtils.setEnableApp("com.UCMobile", true)
|
||||||
|
try {
|
||||||
|
ChangeDeviceInfoUtil.changeDevice(callBack = object : ChangeCallBack {
|
||||||
|
override fun changeSuccess() {
|
||||||
|
runCatching {
|
||||||
if (Util.isCanAuto && Util.canAutoLc.isNotEmpty()) {
|
if (Util.isCanAuto && Util.canAutoLc.isNotEmpty()) {
|
||||||
|
val deviceInfo = DeviceDataAccessor.getDeviceInfo(applicationContext, DeviceInfoHelper.getDeviceId())
|
||||||
|
FileUtils.writePackageName(Util.recordPackageName?:"")
|
||||||
|
FileUtils.writeDevice(Util.recordPackageName?:"", deviceInfo?: "")
|
||||||
|
FileUtils.runPlugin(Util.recordPackageName?:"")
|
||||||
MockTools.exec("pm grant ${Util.AUTO_JSPACKAGENAME} android.permission.READ_EXTERNAL_STORAGE") //sdcard权限
|
MockTools.exec("pm grant ${Util.AUTO_JSPACKAGENAME} android.permission.READ_EXTERNAL_STORAGE") //sdcard权限
|
||||||
MockTools.exec("pm grant ${Util.AUTO_JSPACKAGENAME} android.permission.SYSTEM_ALERT_WINDOW") //悬浮窗权限
|
MockTools.exec("pm grant ${Util.AUTO_JSPACKAGENAME} android.permission.SYSTEM_ALERT_WINDOW") //悬浮窗权限
|
||||||
MockTools.exec("settings put secure enabled_accessibility_services ${Util.AUTO_JSPACKAGENAME}/${Util.AUTO_JSPACKAGENAME}.core.accessibility.AccessibilityService")
|
MockTools.exec("settings put secure enabled_accessibility_services ${Util.AUTO_JSPACKAGENAME}/${Util.AUTO_JSPACKAGENAME}.core.accessibility.AccessibilityService")
|
||||||
Util.doScript(this, Util.AUTO_JSPACKAGENAME) //autojs
|
Util.doScript(this@OpenAppService, Util.AUTO_JSPACKAGENAME) //autojs
|
||||||
|
}else {
|
||||||
|
Util.setFinish(this@OpenAppService)
|
||||||
|
}
|
||||||
|
}.onFailure {
|
||||||
|
it.printStackTrace()
|
||||||
|
Util.setFinish(this@OpenAppService)
|
||||||
}
|
}
|
||||||
try {
|
|
||||||
//todo fix 改机流程
|
|
||||||
// if (Util.isNeedRestored) {
|
|
||||||
// Log.d("IOSTQ:", "执行留存任务")
|
|
||||||
// Util.setRrInfo(this)
|
|
||||||
// } else {
|
|
||||||
// Log.d("IOSTQ:", "执行新装任务")
|
|
||||||
// Util.setInfo(this)
|
|
||||||
// }
|
|
||||||
// ChangeDeviceInfoUtil.changeDeviceInfo()
|
|
||||||
ChangeDeviceInfoUtil.changeDevice(callBack = object : ChangeCallBack {
|
|
||||||
override fun changeSuccess() {
|
|
||||||
Util.openRecordApp(this@OpenAppService)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun changeFailed() {
|
override fun changeFailed() {
|
||||||
|
@ -51,6 +56,7 @@ class OpenAppService : JobIntentService() {
|
||||||
})
|
})
|
||||||
} catch (e: IOException) {
|
} catch (e: IOException) {
|
||||||
e.printStackTrace()
|
e.printStackTrace()
|
||||||
|
Util.setFinish(this@OpenAppService)
|
||||||
}
|
}
|
||||||
// Util.hookOpenApp(this);
|
// Util.hookOpenApp(this);
|
||||||
}
|
}
|
||||||
|
|
|
@ -199,11 +199,11 @@ class SendCallbackJobService : JobIntentService() {
|
||||||
file1 = File(fileName1)
|
file1 = File(fileName1)
|
||||||
}
|
}
|
||||||
|
|
||||||
Util.chownSh(this, fileName, Util.getMainUserAndGroup(this))
|
Util.chownSh(fileName, Util.getMainUserAndGroup(this))
|
||||||
var url = "http://192.168.1.111/tt/ddj/backup.do"
|
var url = "http://39.103.73.250/tt/ddj/backup.do"
|
||||||
if (Util.backUpServerIp != "") {
|
// if (Util.backUpServerIp != "") {
|
||||||
url = "http://" + Util.backUpServerIp + "/tt/ddj/backup.do"
|
// url = "http://" + Util.backUpServerIp + "/tt/ddj/backup.do"
|
||||||
}
|
// }
|
||||||
LogUtils.i(TAG, "sendBackupEvent-> file length = " + file.length())
|
LogUtils.i(TAG, "sendBackupEvent-> file length = " + file.length())
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -1,20 +1,20 @@
|
||||||
package com.android.grape.job
|
package com.android.grape.job
|
||||||
|
|
||||||
|
import android.app.ActivityManager
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import androidx.core.app.JobIntentService
|
import androidx.core.app.JobIntentService
|
||||||
import com.android.grape.util.MockTools
|
import com.android.grape.util.MockTools
|
||||||
import com.android.grape.util.Util
|
import com.android.grape.util.Util
|
||||||
|
import com.blankj.utilcode.util.LogUtils
|
||||||
|
|
||||||
|
|
||||||
class UnInstallService : JobIntentService() {
|
class UnInstallService : JobIntentService() {
|
||||||
override fun onHandleWork(intent: Intent) {
|
override fun onHandleWork(intent: Intent) {
|
||||||
|
|
||||||
Util.backUp(this)
|
Util.backUp(this)
|
||||||
Util.setInstallRet(true)
|
Util.setInstallRet(true)
|
||||||
MockTools.exec("pm clear " + Util.recordPackageName)
|
MockTools.exec("pm clear " + Util.recordPackageName)
|
||||||
Util.delFiles(this@UnInstallService)
|
Util.delFiles(this@UnInstallService)
|
||||||
|
|
||||||
Util.setFinish(this@UnInstallService)
|
Util.setFinish(this@UnInstallService)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,13 +3,16 @@ package com.android.grape.provider
|
||||||
import android.content.ContentValues
|
import android.content.ContentValues
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
|
import android.util.Log
|
||||||
import com.android.grape.data.Device
|
import com.android.grape.data.Device
|
||||||
|
import com.blankj.utilcode.util.LogUtils
|
||||||
|
|
||||||
// DeviceDataAccessor.kt
|
// DeviceDataAccessor.kt
|
||||||
object DeviceDataAccessor {
|
object DeviceDataAccessor {
|
||||||
|
|
||||||
// 保存设备信息到提供方
|
// 保存设备信息到提供方
|
||||||
fun saveDeviceInfo(context: Context, device: Device): Uri? {
|
fun saveDeviceInfo(context: Context, device: Device): Uri? {
|
||||||
|
LogUtils.d("TAG", "saveDeviceInfo: ${device.toJson()}")
|
||||||
val resolver = context.contentResolver
|
val resolver = context.contentResolver
|
||||||
val actualDeviceId = DeviceInfoHelper.getDeviceId()
|
val actualDeviceId = DeviceInfoHelper.getDeviceId()
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,79 @@
|
||||||
|
package com.android.grape.service
|
||||||
|
|
||||||
|
import android.util.Log
|
||||||
|
import java.io.BufferedReader
|
||||||
|
import java.io.InputStreamReader
|
||||||
|
import java.io.PrintWriter
|
||||||
|
import java.net.ServerSocket
|
||||||
|
import java.net.Socket
|
||||||
|
|
||||||
|
class SocketServer(private val port: Int = 8888) {
|
||||||
|
private var serverSocket: ServerSocket? = null
|
||||||
|
private var running = false
|
||||||
|
private val clients = mutableListOf<Socket>()
|
||||||
|
private var messageListener: ((Socket, String) -> Unit)? = null
|
||||||
|
|
||||||
|
fun start(listener: (Socket, String) -> Unit) {
|
||||||
|
messageListener = listener
|
||||||
|
running = true
|
||||||
|
|
||||||
|
Thread {
|
||||||
|
try {
|
||||||
|
serverSocket = ServerSocket(port)
|
||||||
|
Log.d("SocketServer", "服务器已启动,监听端口: $port")
|
||||||
|
|
||||||
|
while (running) {
|
||||||
|
val clientSocket = serverSocket?.accept()
|
||||||
|
clientSocket?.let {
|
||||||
|
Log.d("SocketServer", "客户端已连接: ${it.inetAddress.hostAddress}")
|
||||||
|
clients.add(it)
|
||||||
|
handleClient(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Log.e("SocketServer", "服务器错误", e)
|
||||||
|
}
|
||||||
|
}.start()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun handleClient(clientSocket: Socket) {
|
||||||
|
Thread {
|
||||||
|
try {
|
||||||
|
val reader = BufferedReader(InputStreamReader(clientSocket.getInputStream()))
|
||||||
|
|
||||||
|
while (running) {
|
||||||
|
val message = reader.readLine() ?: break
|
||||||
|
messageListener?.invoke(clientSocket, message)
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Log.e("SocketServer", "客户端处理错误", e)
|
||||||
|
} finally {
|
||||||
|
clients.remove(clientSocket)
|
||||||
|
clientSocket.close()
|
||||||
|
}
|
||||||
|
}.start()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun sendToClient(clientSocket: Socket, message: String) {
|
||||||
|
try {
|
||||||
|
PrintWriter(clientSocket.getOutputStream(), true).println(message)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Log.e("SocketServer", "发送消息失败", e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun broadcast(message: String) {
|
||||||
|
clients.forEach { sendToClient(it, message) }
|
||||||
|
}
|
||||||
|
|
||||||
|
fun stop() {
|
||||||
|
running = false
|
||||||
|
clients.forEach { it.close() }
|
||||||
|
clients.clear()
|
||||||
|
try {
|
||||||
|
serverSocket?.close()
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Log.e("SocketServer", "关闭服务器错误", e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -8,7 +8,7 @@ import com.android.grape.data.Device
|
||||||
import com.android.grape.net.Api
|
import com.android.grape.net.Api
|
||||||
import com.android.grape.net.ChangeCallBack
|
import com.android.grape.net.ChangeCallBack
|
||||||
import com.android.grape.provider.DeviceDataAccessor
|
import com.android.grape.provider.DeviceDataAccessor
|
||||||
import com.android.grape.util.Util.paramsJson
|
import com.android.grape.util.Util.taskJson
|
||||||
import com.blankj.utilcode.util.LogUtils
|
import com.blankj.utilcode.util.LogUtils
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
@ -23,12 +23,14 @@ object ChangeDeviceInfoUtil {
|
||||||
val scope = CoroutineScope(Dispatchers.IO)
|
val scope = CoroutineScope(Dispatchers.IO)
|
||||||
fun changeDevice(callBack: ChangeCallBack){
|
fun changeDevice(callBack: ChangeCallBack){
|
||||||
try {
|
try {
|
||||||
val deviceObject = paramsJson?.getJSONObject("device")
|
val deviceObject = taskJson?.getJSONObject("device")
|
||||||
if (deviceObject == null) {
|
if (deviceObject == null) {
|
||||||
LogUtils.d("ERROR", "ChangeDeviceInfoUtil", "device is null")
|
LogUtils.d("ERROR", "ChangeDeviceInfoUtil", "device is null")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
val device = GsonUtils.fromJsonObject(deviceObject.toString(), Device::class.java)
|
val device = GsonUtils.fromJsonObject(deviceObject.toString(), Device::class.java)
|
||||||
|
device.sensor = deviceObject.optJSONArray("sensor")?:JSONArray()
|
||||||
|
LogUtils.d("DeviceSensor---->${device.sensor}")
|
||||||
DeviceDataAccessor.saveDeviceInfo(MainApplication.instance, device)
|
DeviceDataAccessor.saveDeviceInfo(MainApplication.instance, device)
|
||||||
val padCode = ShellUtils.execRootCmdAndGetResult("getprop ro.boot.pad_code")
|
val padCode = ShellUtils.execRootCmdAndGetResult("getprop ro.boot.pad_code")
|
||||||
Log.d("TAG", "changeDevice: $padCode")
|
Log.d("TAG", "changeDevice: $padCode")
|
||||||
|
@ -162,6 +164,8 @@ object ChangeDeviceInfoUtil {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}else{
|
||||||
|
callBack.changeFailed()
|
||||||
}
|
}
|
||||||
} catch (e: JSONException) {
|
} catch (e: JSONException) {
|
||||||
e.printStackTrace()
|
e.printStackTrace()
|
||||||
|
@ -174,7 +178,7 @@ object ChangeDeviceInfoUtil {
|
||||||
MockTools.exec("pm grant com.android.grape android.permission.INTERACT_ACROSS_USERS")
|
MockTools.exec("pm grant com.android.grape android.permission.INTERACT_ACROSS_USERS")
|
||||||
MockTools.exec("pm grant com.android.grape android.permission.WRITE_SECURE_SETTINGS")
|
MockTools.exec("pm grant com.android.grape android.permission.WRITE_SECURE_SETTINGS")
|
||||||
MockTools.exec("pm setenforce 0")
|
MockTools.exec("pm setenforce 0")
|
||||||
val deviceObject = paramsJson?.getJSONObject("device")
|
val deviceObject = taskJson?.getJSONObject("device")
|
||||||
if (deviceObject == null) {
|
if (deviceObject == null) {
|
||||||
LogUtils.d("ERROR", "ChangeDeviceInfoUtil", "device is null")
|
LogUtils.d("ERROR", "ChangeDeviceInfoUtil", "device is null")
|
||||||
return
|
return
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package com.android.grape.util
|
package com.android.grape.util
|
||||||
|
|
||||||
import android.os.Environment
|
import android.os.Environment
|
||||||
|
import android.util.Base64
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import com.blankj.utilcode.util.LogUtils
|
import com.blankj.utilcode.util.LogUtils
|
||||||
import java.io.BufferedInputStream
|
import java.io.BufferedInputStream
|
||||||
|
@ -417,4 +418,28 @@ object FileUtils {
|
||||||
// 6. 可以考虑添加重试机制或通知用户
|
// 6. 可以考虑添加重试机制或通知用户
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun writeDevice(packageName: String, device: String) {
|
||||||
|
LogUtils.d("TAG", "writeDevice: $device")
|
||||||
|
val base64Content: String =
|
||||||
|
Base64.encodeToString(device.toByteArray(StandardCharsets.UTF_8), Base64.NO_WRAP)
|
||||||
|
// 构造安全命令
|
||||||
|
val filePath = "/data/data/$packageName/device.txt"
|
||||||
|
val cmd = "sh -c 'printf %s '\''" + base64Content + "'\'' > " + filePath + "'"
|
||||||
|
val result = ShellUtils.execRootCmdAndGetResult(cmd)
|
||||||
|
ShellUtils.execRootCmdAndGetResult("chmod 777 $filePath")
|
||||||
|
LogUtils.d("TAG", "writeDevice: $result")
|
||||||
|
}
|
||||||
|
|
||||||
|
fun runPlugin(packageName: String){
|
||||||
|
val cmd = "apmt patch add -n ArmCloudAF -p $packageName -f /sdcard/Download/ArmCloudAF_lo.apk"
|
||||||
|
val result = ShellUtils.execRootCmdAndGetResult(cmd)
|
||||||
|
LogUtils.d("TAG", "runPlugin: $result")
|
||||||
|
}
|
||||||
|
|
||||||
|
fun deletePlugin(){
|
||||||
|
val cmd = "apmt patch del -n ArmCloudAF"
|
||||||
|
val result = ShellUtils.execRootCmdAndGetResult(cmd)
|
||||||
|
LogUtils.d("TAG", "deletePlugin: $result")
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -19,6 +19,7 @@ object ScriptUtil {
|
||||||
var scriptResultReceiver: BroadcastReceiver? = null
|
var scriptResultReceiver: BroadcastReceiver? = null
|
||||||
fun execScript(context: Context, src: String) {
|
fun execScript(context: Context, src: String) {
|
||||||
if (!isAppInstalled("org.autojs.autojs6")) {
|
if (!isAppInstalled("org.autojs.autojs6")) {
|
||||||
|
LogUtils.e("AutoJsUtil", "Auto.js app not installed")
|
||||||
runOnUiThread {
|
runOnUiThread {
|
||||||
Toast.makeText(context, "Auto.js app not installed", Toast.LENGTH_SHORT).show()
|
Toast.makeText(context, "Auto.js app not installed", Toast.LENGTH_SHORT).show()
|
||||||
}
|
}
|
||||||
|
|
|
@ -392,7 +392,7 @@ object Util {
|
||||||
* @param groupanduser组和用户以“组:用户”的形式
|
* @param groupanduser组和用户以“组:用户”的形式
|
||||||
* @return true如果操作成功,则否则为否则
|
* @return true如果操作成功,则否则为否则
|
||||||
*/
|
*/
|
||||||
fun chownSh(context: Context?, dir: String?, groupAndUser: String?): Boolean {
|
fun chownSh(dir: String?, groupAndUser: String?): Boolean {
|
||||||
try {
|
try {
|
||||||
val cmd = "chown -R $groupAndUser $dir"
|
val cmd = "chown -R $groupAndUser $dir"
|
||||||
Log.i(TAG, "chownSh cmd:$cmd")
|
Log.i(TAG, "chownSh cmd:$cmd")
|
||||||
|
@ -469,9 +469,9 @@ object Util {
|
||||||
MockTools.exec(cmd)
|
MockTools.exec(cmd)
|
||||||
val uid = getPackageUserID(
|
val uid = getPackageUserID(
|
||||||
context,
|
context,
|
||||||
recordPackageName!!
|
recordPackageName?:""
|
||||||
)
|
)
|
||||||
chownSh(context, getMonitorDir(context), uid)
|
chownSh(getMonitorDir(context), uid)
|
||||||
return true
|
return true
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
e.printStackTrace()
|
e.printStackTrace()
|
||||||
|
@ -733,16 +733,10 @@ object Util {
|
||||||
*/
|
*/
|
||||||
fun execInstallTask(context: Context) {
|
fun execInstallTask(context: Context) {
|
||||||
init()
|
init()
|
||||||
// adInfo = AdvertisingIdClient.getAdvertisingIdInfo(context);
|
|
||||||
val url = "http://39.103.73.250/tt/ddj/preRequest!requestInstall.do"
|
val url = "http://39.103.73.250/tt/ddj/preRequest!requestInstall.do"
|
||||||
|
val ANDROID_ID = Settings.System.getString(context.contentResolver, Settings.System.ANDROID_ID)
|
||||||
// String params = "platform=Android&tag="+getTag(context)+"&uuid="+PrefUtil.getUUID(context);
|
|
||||||
val ANDROID_ID =
|
|
||||||
Settings.System.getString(context.contentResolver, Settings.System.ANDROID_ID)
|
|
||||||
|
|
||||||
val params = "platform=Android&tag=119&uuid=$ANDROID_ID"
|
val params = "platform=Android&tag=119&uuid=$ANDROID_ID"
|
||||||
//+ "&id=515382023";
|
|
||||||
// boolean valid = false;
|
|
||||||
printStr("IOSTQ:request result : $url?$params")
|
printStr("IOSTQ:request result : $url?$params")
|
||||||
try {
|
try {
|
||||||
val result: String? = MyPost.postData(" ".toByteArray(charset = Charsets.UTF_8),
|
val result: String? = MyPost.postData(" ".toByteArray(charset = Charsets.UTF_8),
|
||||||
|
@ -754,8 +748,7 @@ object Util {
|
||||||
if (result != null && result.isNotEmpty()) {
|
if (result != null && result.isNotEmpty()) {
|
||||||
taskJson = JSONObject(result)
|
taskJson = JSONObject(result)
|
||||||
|
|
||||||
val code = taskJson!!.getInt("code")
|
val code = taskJson?.getInt("code")
|
||||||
|
|
||||||
if (code == 1) {
|
if (code == 1) {
|
||||||
MockTools.exec("chmod 777 /data/data/com.android.grape/files/monitor")
|
MockTools.exec("chmod 777 /data/data/com.android.grape/files/monitor")
|
||||||
MockTools.exec("chmod 777 /data/data/com.android.grape/files/monitor/apks")
|
MockTools.exec("chmod 777 /data/data/com.android.grape/files/monitor/apks")
|
||||||
|
@ -783,7 +776,7 @@ object Util {
|
||||||
*/
|
*/
|
||||||
fun execTask(context: Context) {
|
fun execTask(context: Context) {
|
||||||
nRandom++
|
nRandom++
|
||||||
|
FileUtils.deletePlugin()
|
||||||
if (nRandom % 3 == 0) {
|
if (nRandom % 3 == 0) {
|
||||||
execReloginTask(context)
|
execReloginTask(context)
|
||||||
} else {
|
} else {
|
||||||
|
@ -919,13 +912,11 @@ object Util {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (it.has("recordId") && !it.isNull("recordId")) {
|
if (it.has("recordId") && !it.isNull("recordId")) {
|
||||||
recordId =
|
recordId = it.getLong("recordId")
|
||||||
it.getLong("recordId")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (it.has("preClickRecordId") && !it.isNull("preClickRecordId")) {
|
if (it.has("preClickRecordId") && !it.isNull("preClickRecordId")) {
|
||||||
preClickRecordId =
|
preClickRecordId = it.getLong("preClickRecordId")
|
||||||
it.getLong("preClickRecordId")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (it.has("device") && !it.isNull("device")) {
|
if (it.has("device") && !it.isNull("device")) {
|
||||||
|
@ -995,17 +986,14 @@ object Util {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (it.has("needReg") && !it.isNull("needReg")) {
|
if (it.has("needReg") && !it.isNull("needReg")) {
|
||||||
isNeedReg =
|
isNeedReg = it.getBoolean("needReg")
|
||||||
it.getBoolean("needReg")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (it.has("isExecScript") && !it.isNull("isExecScript")) {
|
if (it.has("isExecScript") && !it.isNull("isExecScript")) {
|
||||||
isCanAuto =
|
isCanAuto = it.getInt("isExecScript") > 0
|
||||||
it.getInt("isExecScript") > 0
|
|
||||||
|
|
||||||
if (it.has("ExecScriptZipURL") && !it.isNull("ExecScriptZipURL")) {
|
if (it.has("ExecScriptZipURL") && !it.isNull("ExecScriptZipURL")) {
|
||||||
canAutoLc =
|
canAutoLc = it.getString("ExecScriptZipURL")
|
||||||
it.getString("ExecScriptZipURL")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1069,6 +1057,8 @@ object Util {
|
||||||
try {
|
try {
|
||||||
taskJson?.let {
|
taskJson?.let {
|
||||||
val deviceJo = it.getJSONObject("device")
|
val deviceJo = it.getJSONObject("device")
|
||||||
|
LogUtils.e("deviceJo:$deviceJo")
|
||||||
|
LogUtils.e("deviceJo sensor:${deviceJo.optJSONArray("sensor")}")
|
||||||
val deviceParamJo: JSONObject = DeviceConvertUtil.MGConvert(deviceJo)
|
val deviceParamJo: JSONObject = DeviceConvertUtil.MGConvert(deviceJo)
|
||||||
if (it.has("isCollectURL")) {
|
if (it.has("isCollectURL")) {
|
||||||
deviceJo.put("isCollectURL", true)
|
deviceJo.put("isCollectURL", true)
|
||||||
|
@ -1133,13 +1123,9 @@ object Util {
|
||||||
val script_url = "http://39.103.73.250/tt/" + canAutoLc
|
val script_url = "http://39.103.73.250/tt/" + canAutoLc
|
||||||
isDownload = downloadFile(script_url, script_path)
|
isDownload = downloadFile(script_url, script_path)
|
||||||
if (!isDownload) {
|
if (!isDownload) {
|
||||||
Log.i(
|
Log.i(TAG, "execDownScript isDownload : $isDownload")
|
||||||
TAG,
|
|
||||||
"execDownScript isDownload : $isDownload"
|
|
||||||
)
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
unzipAPkSh(script_path, "/sdcard/script/")
|
unzipAPkSh(script_path, "/sdcard/script/")
|
||||||
delFileSh(script_path)
|
delFileSh(script_path)
|
||||||
}
|
}
|
||||||
|
@ -1153,52 +1139,37 @@ object Util {
|
||||||
|
|
||||||
fun execDownloadApp(context: Context): Boolean {
|
fun execDownloadApp(context: Context): Boolean {
|
||||||
try {
|
try {
|
||||||
var url = ""
|
var url = "http://39.103.73.250/tt/upload/ddj/$recordFileName"
|
||||||
|
|
||||||
url = if (videoProxy.startsWith("http://39.103.73.250")) {
|
|
||||||
videoProxy + "/ddj/" + recordFileName
|
|
||||||
} else {
|
|
||||||
// url = videoProxy + "/ddj/" + Util.getRecordPackageName() + ".apk";
|
|
||||||
videoProxy + "/ddj/" + recordFileName
|
|
||||||
}
|
|
||||||
url = "http://39.103.73.250/tt/upload/ddj/" + recordFileName
|
|
||||||
// if(getRecordPackageName().equals("com.zhiliaoapp.musically")) {
|
|
||||||
// url = "http://192.168.30.201:5000/static/com.zhiliaoapp.musically_24.7.5.xapk";
|
|
||||||
// }
|
|
||||||
var ret = false
|
var ret = false
|
||||||
ret = if (checkAppInstalled(
|
ret = if (checkAppInstalled(context, recordPackageName) || !CheckAppNeedUpgrade(context)) {
|
||||||
context,
|
|
||||||
recordPackageName
|
|
||||||
) || !CheckAppNeedUpgrade(context)
|
|
||||||
) {
|
|
||||||
true
|
true
|
||||||
} else {
|
} else {
|
||||||
// ret = downloadFile(url, Util.getRecordApkVerFileName(context));
|
downloadFile(url, "/sdcard/apks/$recordFileName")
|
||||||
downloadFile(url, "/sdcard/apks/" + recordFileName)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ret) {
|
if (ret) {
|
||||||
Log.i(TAG, "download apk succ")
|
Log.i(TAG, "download apk succ")
|
||||||
Log.i(TAG, "recordExtraFileName:" + recordExtraFileName)
|
Log.i(TAG, "recordExtraFileName:$recordExtraFileName")
|
||||||
if (recordExtraFileName != null && recordExtraFileName!!.length > 0) {
|
if (recordExtraFileName?.isNotEmpty() == true) {
|
||||||
val extraUrl = videoProxy + "/ddj/" + recordExtraFileName
|
val extraUrl = "$videoProxy/ddj/$recordExtraFileName"
|
||||||
|
|
||||||
ret = downloadFile(extraUrl, getRecordExtraFileName(context))
|
ret = downloadFile(extraUrl, getRecordExtraFileName(context))
|
||||||
}
|
}
|
||||||
if (isNeedRestored) {
|
if (isNeedRestored) {
|
||||||
println("IOSTQ:开始下载留存文件")
|
println("IOSTQ:开始下载留存文件")
|
||||||
if (taskJson!!.has("BackupFileUrl1") && taskJson!!.getString("BackupFileUrl1").length > 0) {
|
taskJson?.let {
|
||||||
var restored_zip =
|
if (it.has("BackupFileUrl1") && it.getString("BackupFileUrl1").isNotEmpty()) {
|
||||||
"http://192.168.1.111/tt/" + taskJson!!.getString("BackupFileUrl1")
|
var restored_zip = "http://192.168.1.111/tt/" + it.getString("BackupFileUrl1")
|
||||||
if (backUpServerIp != "") {
|
if (backUpServerIp.isNotEmpty()) {
|
||||||
restored_zip =
|
restored_zip = "http://" + backUpServerIp + "/tt/" + it.getString("BackupFileUrl1")
|
||||||
"http://" + backUpServerIp + "/tt/" + taskJson!!.getString("BackupFileUrl1")
|
|
||||||
}
|
}
|
||||||
ret = downloadFile(restored_zip, getRecordDataFileName(context))
|
ret = downloadFile(restored_zip, getRecordDataFileName(context))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (taskJson == null){
|
||||||
|
ret = false
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret
|
return ret
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
e.printStackTrace()
|
e.printStackTrace()
|
||||||
|
@ -1287,18 +1258,6 @@ object Util {
|
||||||
writer.write(message)
|
writer.write(message)
|
||||||
|
|
||||||
writer.close()
|
writer.close()
|
||||||
|
|
||||||
// FileOutputStream fos = new FileOutputStream(file);
|
|
||||||
// long sum = 0;
|
|
||||||
// int lenght = 0;
|
|
||||||
// fos.write(message.getBytes(StandardCharsets.UTF_8), 0, message.length());
|
|
||||||
// fos.flush();
|
|
||||||
// fos.close();
|
|
||||||
// String dstPath = "/data/data/"+ Util.getRecordPackageName() + "/" + Util.getRecordPackageName()+ "_device.txt";
|
|
||||||
// Util.copyFileSh(AppPath +"device.txt",dstPath);
|
|
||||||
|
|
||||||
//give777(dstPath);
|
|
||||||
// CmdUtils.chmodFilePermission(dstPath);
|
|
||||||
Log.d("文件写入", "成功")
|
Log.d("文件写入", "成功")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1492,12 +1451,6 @@ object Util {
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getBaseFilesDir(context: Context): String {
|
fun getBaseFilesDir(context: Context): String {
|
||||||
// File dir = context.getExternalFilesDir(null);
|
|
||||||
// if(dir == null) {
|
|
||||||
// return "/sdcard/Android/data/" + context.getPackageName() + "/files";
|
|
||||||
// }else{
|
|
||||||
// return dir.getAbsolutePath();
|
|
||||||
// }
|
|
||||||
return context.filesDir.absolutePath
|
return context.filesDir.absolutePath
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1539,13 +1492,11 @@ object Util {
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun execHookApp(context: Context) {
|
private fun execHookApp(context: Context) {
|
||||||
val intent = Intent(Intent.ACTION_MAIN)
|
val intent = Intent(Intent.ACTION_MAIN).apply {
|
||||||
|
|
||||||
if (intent != null) {
|
|
||||||
val cname = ComponentName(hookPackageName, hookAppMainClass)
|
val cname = ComponentName(hookPackageName, hookAppMainClass)
|
||||||
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||||
intent.setComponent(cname)
|
setComponent(cname)
|
||||||
context.startActivity(intent)
|
context.startActivity(this)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1587,12 +1538,12 @@ object Util {
|
||||||
|
|
||||||
|
|
||||||
fun doScript(context: Context, targetPackageName: String): Boolean {
|
fun doScript(context: Context, targetPackageName: String): Boolean {
|
||||||
execTargetApp(context, targetPackageName)
|
// execTargetApp(context, targetPackageName)
|
||||||
try {
|
// try {
|
||||||
Thread.sleep(3000L)
|
// Thread.sleep(3000L)
|
||||||
} catch (e: InterruptedException) {
|
// } catch (e: InterruptedException) {
|
||||||
e.printStackTrace()
|
// e.printStackTrace()
|
||||||
}
|
// }
|
||||||
Handler(Looper.getMainLooper()).postDelayed(Runnable { //开始执行脚本
|
Handler(Looper.getMainLooper()).postDelayed(Runnable { //开始执行脚本
|
||||||
AutoJobService.onEvent(context)
|
AutoJobService.onEvent(context)
|
||||||
}, 1)
|
}, 1)
|
||||||
|
@ -1848,7 +1799,7 @@ object Util {
|
||||||
try {
|
try {
|
||||||
val file = File(getRecordSdcardApkVerFileName(context))
|
val file = File(getRecordSdcardApkVerFileName(context))
|
||||||
var extraFile: File? = null
|
var extraFile: File? = null
|
||||||
if (recordExtraFileName != null && recordExtraFileName!!.length > 0) {
|
if (recordExtraFileName?.isNotEmpty() == true) {
|
||||||
extraFile = File(getRecordExtraFileName(context))
|
extraFile = File(getRecordExtraFileName(context))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1870,7 +1821,7 @@ object Util {
|
||||||
Log.i(TAG, "installRet:$installRet")
|
Log.i(TAG, "installRet:$installRet")
|
||||||
} else {
|
} else {
|
||||||
installRet = true
|
installRet = true
|
||||||
MockTools.exec("pm clear " + recordPackageName)
|
MockTools.exec("pm clear $recordPackageName")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1925,34 +1876,34 @@ object Util {
|
||||||
val zipFile = getRecordDataFileName(context)
|
val zipFile = getRecordDataFileName(context)
|
||||||
val reloginDataDir = getApkDataDir(
|
val reloginDataDir = getApkDataDir(
|
||||||
context,
|
context,
|
||||||
recordPackageName!!
|
recordPackageName?:return false
|
||||||
)
|
)
|
||||||
|
|
||||||
Log.i(
|
Log.i(
|
||||||
TAG,
|
TAG,
|
||||||
"recoverRecordData: dir=$reloginDataDir"
|
"recoverRecordData: dir=$reloginDataDir"
|
||||||
)
|
)
|
||||||
|
if (reloginDataDir == null){
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
// ZipUtils1.upZipFile(new File(zipFile), dataDir+"/");
|
|
||||||
unZipFileSh(zipFile, dataDir)
|
unZipFileSh(zipFile, dataDir)
|
||||||
|
|
||||||
val userAnGroup = getUserAndGroupSh(context)
|
val userAnGroup = getUserAndGroupSh(context)
|
||||||
Log.i(
|
Log.i(TAG, "recoverRecordData->userAndGroup:$userAnGroup")
|
||||||
TAG,
|
File(reloginDataDir).parentFile?.absolutePath?.let {
|
||||||
"recoverRecordData->userAndGroup:$userAnGroup"
|
|
||||||
)
|
|
||||||
|
|
||||||
copyFolderSh(
|
copyFolderSh(
|
||||||
dataDir + "/" + recordPackageName,
|
"$dataDir/$recordPackageName",
|
||||||
File(reloginDataDir).parentFile.absolutePath
|
it
|
||||||
)
|
)
|
||||||
|
}
|
||||||
|
|
||||||
delFilesSh(
|
delFilesSh(
|
||||||
dataDir,
|
dataDir,
|
||||||
recordPackageName
|
recordPackageName
|
||||||
)
|
)
|
||||||
|
|
||||||
chownSh(context, reloginDataDir, userAnGroup)
|
chownSh(reloginDataDir, userAnGroup)
|
||||||
|
|
||||||
return true
|
return true
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
|
@ -1999,10 +1950,7 @@ object Util {
|
||||||
}
|
}
|
||||||
|
|
||||||
fun copyFolderSh(oldPath: String, newPath: String): Boolean {
|
fun copyFolderSh(oldPath: String, newPath: String): Boolean {
|
||||||
Log.i(
|
Log.i(TAG, "start copyFolderSh : $oldPath ; $newPath")
|
||||||
TAG,
|
|
||||||
"start copyFolderSh : $oldPath ; $newPath"
|
|
||||||
)
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
val cmd = "cp -r -f $oldPath $newPath"
|
val cmd = "cp -r -f $oldPath $newPath"
|
||||||
|
@ -2016,10 +1964,7 @@ object Util {
|
||||||
}
|
}
|
||||||
|
|
||||||
fun copyFileSh(oldPath: String, newPath: String): Boolean {
|
fun copyFileSh(oldPath: String, newPath: String): Boolean {
|
||||||
Log.i(
|
Log.i(TAG, "start copyFileSh : $oldPath ; $newPath")
|
||||||
TAG,
|
|
||||||
"start copyFileSh : $oldPath ; $newPath"
|
|
||||||
)
|
|
||||||
try {
|
try {
|
||||||
val cmd = "cp -r -f $oldPath $newPath"
|
val cmd = "cp -r -f $oldPath $newPath"
|
||||||
MockTools.exec(cmd)
|
MockTools.exec(cmd)
|
||||||
|
@ -2214,7 +2159,7 @@ object Util {
|
||||||
fileOutputStream.write(buffer, 0, byteRead)
|
fileOutputStream.write(buffer, 0, byteRead)
|
||||||
}
|
}
|
||||||
|
|
||||||
chownSh(context, "/sdcard/Android/obb/" + recordPackageName + "/", userAndGroup)
|
chownSh("/sdcard/Android/obb/" + recordPackageName + "/", userAndGroup)
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
if (fileInputStream != null) {
|
if (fileInputStream != null) {
|
||||||
try {
|
try {
|
||||||
|
@ -2297,24 +2242,6 @@ object Util {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun hasRootPerssion(): Boolean {
|
|
||||||
var PrintWriter: PrintWriter? = null
|
|
||||||
var process: Process? = null
|
|
||||||
try {
|
|
||||||
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
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun returnResult(value: Int): Boolean {
|
private fun returnResult(value: Int): Boolean {
|
||||||
// 代表成功
|
// 代表成功
|
||||||
return if (value == 0) {
|
return if (value == 0) {
|
||||||
|
@ -2357,7 +2284,6 @@ object Util {
|
||||||
"start to clientUninstall : $packageName"
|
"start to clientUninstall : $packageName"
|
||||||
)
|
)
|
||||||
try {
|
try {
|
||||||
// String cmd = "LD_LIBRARY_PATH=/vendor/lib:/system/lib" + "|";
|
|
||||||
val cmd = "pm uninstall $packageName"
|
val cmd = "pm uninstall $packageName"
|
||||||
MockTools.exec(cmd)
|
MockTools.exec(cmd)
|
||||||
return true
|
return true
|
||||||
|
@ -2397,10 +2323,8 @@ object Util {
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setFinish(context: Context) {
|
fun setFinish(context: Context) {
|
||||||
// Log.i(TAG, "setFinish");
|
Log.i(TAG, "setFinish")
|
||||||
|
|
||||||
MonitorService.setRunning(false)
|
MonitorService.setRunning(false)
|
||||||
// killRecordProcess(context, "com.tunnelworkshop.postern")
|
|
||||||
killRecordProcess(context, AUTO_JSPACKAGENAME)
|
killRecordProcess(context, AUTO_JSPACKAGENAME)
|
||||||
Handler(Looper.getMainLooper()).postDelayed(Runnable {
|
Handler(Looper.getMainLooper()).postDelayed(Runnable {
|
||||||
MonitorService.onEvent(
|
MonitorService.onEvent(
|
||||||
|
@ -2587,7 +2511,7 @@ object Util {
|
||||||
if (taskInfo.baseActivity?.packageName == context.packageName) {
|
if (taskInfo.baseActivity?.packageName == context.packageName) {
|
||||||
// Log.i(TAG, "setTopApp exec");
|
// Log.i(TAG, "setTopApp exec");
|
||||||
activityManager.moveTaskToFront(taskInfo.id, 0)
|
activityManager.moveTaskToFront(taskInfo.id, 0)
|
||||||
checkFloatPermission(context)
|
// checkFloatPermission(context)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2740,62 +2664,46 @@ object Util {
|
||||||
* @param packageName 将备份数据的软件包的名称。
|
* @param packageName 将备份数据的软件包的名称。
|
||||||
* @return 如果备份成功,则创建的zip文件的绝对路径,如果该过程失败,则为null。
|
* @return 如果备份成功,则创建的zip文件的绝对路径,如果该过程失败,则为null。
|
||||||
*/
|
*/
|
||||||
fun backupDataFile(context: Context, packageName: String): String? {
|
fun backupDataFile(context: Context, packageName: String?): String? {
|
||||||
Log.i(TAG, "start backUpDataFile : $packageName")
|
Log.i(TAG, "start backUpDataFile : $packageName")
|
||||||
|
if (packageName == null){
|
||||||
|
return null
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
val zipDirName = getBaseFilesDir(context) + "/" + monitorDir + "/" + packageName
|
val zipDirName = getBaseFilesDir(context) + "/" + monitorDir + "/" + packageName
|
||||||
val zipFileName =
|
val zipFileName = getBaseFilesDir(context) + "/" + monitorDir + "/" + packageName + ".zip"
|
||||||
getBaseFilesDir(context) + "/" + monitorDir + "/" + packageName + ".zip"
|
Log.i(TAG, "backupDataFile-> zipDirName:$zipDirName ; zipFileName:$zipFileName")
|
||||||
Log.i(
|
|
||||||
TAG,
|
|
||||||
"backupDataFile-> zipDirName:$zipDirName ; zipFileName:$zipFileName"
|
|
||||||
)
|
|
||||||
val zipFile = File(zipFileName)
|
val zipFile = File(zipFileName)
|
||||||
forceMakeDir(File(getRecordDataDirName(context)))
|
forceMakeDir(File(getRecordDataDirName(context)))
|
||||||
if (!zipFile.exists()) {
|
if (!zipFile.exists()) {
|
||||||
val zipDir = File(zipDirName)
|
val zipDir = File(zipDirName)
|
||||||
forceMakeDir(zipDir)
|
forceMakeDir(zipDir)
|
||||||
//TODO:获取apk包所在的文件夹
|
|
||||||
val apkDataPath = context.packageManager.getApplicationInfo(packageName, 0).dataDir
|
val apkDataPath = context.packageManager.getApplicationInfo(packageName, 0).dataDir
|
||||||
Log.i(
|
Log.i(TAG, "backupDataFile->apkDataPath=$apkDataPath")
|
||||||
TAG,
|
|
||||||
"backupDataFile->apkDataPath=$apkDataPath"
|
|
||||||
)
|
|
||||||
|
|
||||||
listSh(context, apkDataPath)
|
listSh(context, apkDataPath)
|
||||||
|
|
||||||
val file = File(getRecordListTxtFileName(context))
|
val file = File(getRecordListTxtFileName(context))
|
||||||
if (file.exists()) {
|
if (file.exists()) {
|
||||||
val ss = getStringFromFile(context, file.absolutePath)
|
val ss = getStringFromFile(context, file.absolutePath)
|
||||||
|
if (ss.isNotEmpty()) {
|
||||||
if (ss != null && ss.length > 0) {
|
val arr = ss.split("\n".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
|
||||||
val arr =
|
|
||||||
ss.split("\n".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
|
|
||||||
|
|
||||||
for (line in arr) {
|
for (line in arr) {
|
||||||
Log.i(TAG, "line:$line")
|
Log.i(TAG, "line:$line")
|
||||||
|
|
||||||
val blankPos = line.lastIndexOf(" ")
|
val blankPos = line.lastIndexOf(" ")
|
||||||
val fn = line.substring(blankPos + 1)
|
val fn = line.substring(blankPos + 1)
|
||||||
copyFileSh(
|
copyFileSh("$apkDataPath/$fn", "$zipDirName/")
|
||||||
"$apkDataPath/$fn",
|
|
||||||
"$zipDirName/"
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
val uid = getUserAndGroupSh(context.applicationContext)
|
val uid = getUserAndGroupSh(context.applicationContext)
|
||||||
chownSh(context, getMonitorDir(context), uid)
|
chownSh(getMonitorDir(context), uid)
|
||||||
val copySucc = File(zipDirName).exists()
|
val copySucc = File(zipDirName).exists()
|
||||||
Log.i(
|
Log.i(TAG, "copyFolder($apkDataPath,$zipDirName) = $copySucc")
|
||||||
TAG,
|
|
||||||
"copyFolder($apkDataPath,$zipDirName) = $copySucc"
|
|
||||||
)
|
|
||||||
|
|
||||||
//TODO:将apk包所在的文件夹备份到DownLoad文件夹下
|
//TODO:将apk包所在的文件夹备份到DownLoad文件夹下
|
||||||
//TODO:将新生成的文件夹进行压缩
|
//TODO:将新生成的文件夹进行压缩
|
||||||
if (copySucc) {
|
if (copySucc) {
|
||||||
chownSh(context, zipDirName, getMainUserAndGroup(context))
|
chownSh(zipDirName, getMainUserAndGroup(context))
|
||||||
|
|
||||||
val afFile = File("$zipDirName/AFPOST.txt")
|
val afFile = File("$zipDirName/AFPOST.txt")
|
||||||
zipSh(zipDirName, zipFileName)
|
zipSh(zipDirName, zipFileName)
|
||||||
|
@ -2972,7 +2880,7 @@ object Util {
|
||||||
*/
|
*/
|
||||||
fun backUp(context: Context) {
|
fun backUp(context: Context) {
|
||||||
killRecordProcess(context)
|
killRecordProcess(context)
|
||||||
backUp(context, recordPackageName!!)
|
backUp(context, recordPackageName)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -3012,7 +2920,7 @@ object Util {
|
||||||
* @param上下文执行备份操作的上下文
|
* @param上下文执行备份操作的上下文
|
||||||
* @param packageName备份数据的软件包的名称
|
* @param packageName备份数据的软件包的名称
|
||||||
*/
|
*/
|
||||||
fun backUp(context: Context, packageName: String) {
|
fun backUp(context: Context, packageName: String?) {
|
||||||
backFileName = backupDataFile(context, packageName)
|
backFileName = backupDataFile(context, packageName)
|
||||||
if (isNeedBackup) {
|
if (isNeedBackup) {
|
||||||
// Util.backFileName1 = Util.backupDataFile1(context, packageName);
|
// Util.backFileName1 = Util.backupDataFile1(context, packageName);
|
||||||
|
|
|
@ -6,7 +6,14 @@
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
tools:context=".MainActivity">
|
tools:context=".MainActivity">
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/text"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
android:layout_marginTop="30dp"
|
||||||
|
android:layout_marginHorizontal="30dp"/>
|
||||||
<Button
|
<Button
|
||||||
android:id="@+id/start"
|
android:id="@+id/start"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
|
|
Loading…
Reference in New Issue