From 1250e0150b9470b511f9500690e5a59ada875070 Mon Sep 17 00:00:00 2001 From: Administrator Date: Tue, 29 Jul 2025 16:47:47 +0800 Subject: [PATCH] aflog data --- .../java/com/android/grape/MainActivity.kt | 3 + .../grape/job/SendCallbackJobService.kt | 8 +- .../com/android/grape/util/BackupUtils.kt | 7 +- .../java/com/android/grape/util/FileUtils.kt | 150 ++++++++++++++---- .../java/com/android/grape/util/JsonUtils.kt | 1 - .../java/com/android/grape/util/TaskUtils.kt | 11 +- 6 files changed, 140 insertions(+), 40 deletions(-) diff --git a/app/src/main/java/com/android/grape/MainActivity.kt b/app/src/main/java/com/android/grape/MainActivity.kt index bd01445..aa3a686 100644 --- a/app/src/main/java/com/android/grape/MainActivity.kt +++ b/app/src/main/java/com/android/grape/MainActivity.kt @@ -3,6 +3,7 @@ package com.android.grape import android.content.Intent import android.os.Build import android.os.Bundle +import android.util.Log import android.widget.Toast import androidx.activity.enableEdgeToEdge import androidx.activity.viewModels @@ -14,12 +15,14 @@ import com.android.grape.databinding.ActivityMainBinding import com.android.grape.job.MonitorService import com.android.grape.util.BackupUtils.killRecordProcess import com.android.grape.util.ClashUtil +import com.android.grape.util.FileUtils import com.android.grape.util.MockTools import com.android.grape.util.NotificationPermissionHandler import com.android.grape.util.ScriptUtils.registerScriptResultReceiver import com.android.grape.util.ScriptUtils.unregisterScriptResultReceiver import com.android.grape.util.ShellUtil import com.android.grape.util.StoragePermissionHelper +import com.android.grape.util.TaskUtils /** * public class MainActivity extends AppCompatActivity diff --git a/app/src/main/java/com/android/grape/job/SendCallbackJobService.kt b/app/src/main/java/com/android/grape/job/SendCallbackJobService.kt index 677b52e..c3a5e7e 100644 --- a/app/src/main/java/com/android/grape/job/SendCallbackJobService.kt +++ b/app/src/main/java/com/android/grape/job/SendCallbackJobService.kt @@ -2,6 +2,7 @@ package com.android.grape.job import android.content.Context import android.content.Intent +import android.os.Environment import android.os.Handler import android.os.Looper import androidx.core.app.JobIntentService @@ -24,11 +25,13 @@ import com.android.grape.data.AppState.lastUpdateTime import com.android.grape.data.AppState.logBuffer import com.android.grape.data.AppState.preClickRecordId import com.android.grape.data.AppState.recordId +import com.android.grape.data.AppState.recordPackageName import com.android.grape.data.AppState.reloginRecordId import com.android.grape.net.AfClient.postData import com.android.grape.util.AppUtils.getAppAfVer import com.android.grape.util.DeviceUtils.getMainUserAndGroup import com.android.grape.util.InstallUtils.isInstallRet +import com.android.grape.util.MockTools import com.android.grape.util.MyPost import com.android.grape.util.ShellUtils.chownSh import com.android.grape.util.ShellUtils.delFileSh @@ -68,6 +71,7 @@ class SendCallbackJobService : JobIntentService() { } else { sendLogEvent() } + MockTools.exec("rm -rf ${Environment.getExternalStorageDirectory()}/script/${recordPackageName}/afLog.txt") } setFinish(this@SendCallbackJobService) } @@ -116,7 +120,7 @@ class SendCallbackJobService : JobIntentService() { // logInfoJo.put("setConfLog", Util.getParamsJson()); paramsJo.put("logInfo", logInfoJo) var params: String? = null - params = paramsJo?.toString() ?: "error" + params = paramsJo.toString() var nRetryCount = 0 do { @@ -179,7 +183,7 @@ class SendCallbackJobService : JobIntentService() { paramsJo.put("backUpFiles", backupResult) } var params: String? = null - params = paramsJo?.toString() ?: "error" + params = paramsJo.toString() var nRetryCount = 0 do { diff --git a/app/src/main/java/com/android/grape/util/BackupUtils.kt b/app/src/main/java/com/android/grape/util/BackupUtils.kt index 6b2b009..2b8adef 100644 --- a/app/src/main/java/com/android/grape/util/BackupUtils.kt +++ b/app/src/main/java/com/android/grape/util/BackupUtils.kt @@ -90,14 +90,11 @@ object BackupUtils { getBaseFilesDir(context) + "/" + monitorDir + "/" + apkDir + "/" + context.packageName + ".txt" ) chownSh(getMonitorDir(context), uid) - val copySucc = File(zipDirName).exists() + val copySucc = FileUtils.copyFolderSh(apkDataPath,zipDirName) Log.i("BackupUtils", "copyFolder($apkDataPath,$zipDirName) = $copySucc") - - //TODO:将apk包所在的文件夹备份到DownLoad文件夹下 - //TODO:将新生成的文件夹进行压缩 if (copySucc) { + FileUtils.writeAfLog() chownSh(zipDirName, getMainUserAndGroup(context)) - val afFile = File("$zipDirName/AFPOST.txt") zipSh(zipDirName, zipFileName) delFileSh(zipDirName) diff --git a/app/src/main/java/com/android/grape/util/FileUtils.kt b/app/src/main/java/com/android/grape/util/FileUtils.kt index 88df888..efbbeb5 100644 --- a/app/src/main/java/com/android/grape/util/FileUtils.kt +++ b/app/src/main/java/com/android/grape/util/FileUtils.kt @@ -279,11 +279,12 @@ object FileUtils { ) try { val zipDir = File(zipDirName) - val zipFile = File(zipFileName) - var cmd = "cd " + (zipDir.parentFile?.absolutePath ?: "") + "|" - cmd += "tar -zcvf " + zipFile.name + " " + zipDir.name - Log.i("FileUtils", "zipSh-> cmd:$cmd") - MockTools.exec(cmd) +// val zipFile = File(zipFileName) +//// var cmd = "cd " + (zipDir.parentFile?.absolutePath ?: "") + "|" +//// cmd += "tar -zcvf " + zipFile.name + " " + zipDir.name + val cmdString = "tar -zcvf $zipFileName -C ${zipDir.parentFile?.absolutePath ?: ""} ${zipDir.name}" + Log.i("FileUtils", "zipSh-> cmd:$cmdString") + MockTools.exec(cmdString) } catch (e: Exception) { e.printStackTrace() } @@ -379,30 +380,7 @@ object FileUtils { * @return 返回内容 */ fun getString(filePath: String, filename: String): String { - var inputStream: FileInputStream? = null - try { - inputStream = FileInputStream(File(filePath + filename)) - } catch (e: FileNotFoundException) { - e.printStackTrace() - } - var inputStreamReader: InputStreamReader? = null - try { - inputStreamReader = InputStreamReader(inputStream, "UTF-8") - } catch (e1: UnsupportedEncodingException) { - e1.printStackTrace() - } - val reader = BufferedReader(inputStreamReader) - val sb = StringBuffer("") - var line: String? - try { - while ((reader.readLine().also { line = it }) != null) { - sb.append(line) - sb.append("\n") - } - } catch (e: IOException) { - e.printStackTrace() - } - return sb.toString() + return File(filePath, filename).takeIf { it.exists() }?.readText() ?: "" } /** @@ -598,6 +576,36 @@ object FileUtils { } } + fun writeAfLog() { + val filePath = "/data/data/${recordPackageName}/log.txt" + ShellUtils.execRootCmdAndGetResult("chmod 777 $filePath") + val afLog = ShellUtil.execRootCmdAndGetResult("cat $filePath") + val file = File( + Environment.getExternalStorageDirectory(), + "script/${recordPackageName}/afLog.txt" + ) + val parentDir = file.getParentFile() + if (parentDir != null && !parentDir.exists()) { + val dirsCreated = parentDir.mkdirs() + if (!dirsCreated) { + Log.e("FileWrite", "Failed to create directories: $parentDir") + return + } + } + LogUtils.d("FileUtils", "afLog: $afLog", null) + try { + BufferedOutputStream( + FileOutputStream(file) + ).use { bos -> + bos.write(afLog.toByteArray(StandardCharsets.UTF_8)) + bos.flush() // 确保数据写入磁盘 + } + } catch (e: IOException) { + Log.e("FileWrite", "Failed to write afLog: $afLog", e) + // 6. 可以考虑添加重试机制或通知用户 + } + } + fun writeDevice(packageName: String, device: String) { LogUtils.d("FileUtils", "writeDevice: $device") val base64Content: String = @@ -607,7 +615,6 @@ object FileUtils { val cmd = "sh -c 'printf %s '\''" + base64Content + "'\'' > " + filePath + "'" val result = ShellUtils.execRootCmdAndGetResult(cmd) ShellUtils.execRootCmdAndGetResult("chmod 777 $filePath") - LogUtils.d("FileUtils", "writeDevice: $result") } fun runPlugin(packageName: String) { @@ -692,4 +699,87 @@ object FileUtils { return "" } + + + fun copyFolderSh(oldPath: String, newPath: String): Boolean { + Log.i("TaskUtil", "start copyFolderSh : $oldPath ; $newPath") + try { + // 使用 File API 确保路径处理正确 + val src = File(oldPath) + val dst = File(newPath) + +// if (!src.exists()) { +// LogUtils.d( +// Log.ERROR, +// "TaskUtil", +// "Source path does not exist: $oldPath", +// null +// ) +// return false +// } + + // 构造命令(注意 shell 特殊字符的转义) + val safeOldPath = src.absolutePath.replace(" ", "\\ ").replace("\"", "\\\"") + val safeNewPath = dst.absolutePath.replace(" ", "\\ ").replace("\"", "\\\"") + val cmd = "cp -r -f \"$safeOldPath\" \"$safeNewPath\"" + + Log.i("TaskUtil", "copyFolderSh cmd: $cmd") + + // 调用 MockTools 执行 + val result: String = ShellUtils.execRootCmdAndGetResult(cmd) + val chmod = "chmod 777 \"$safeNewPath\"" + val chmodResult: String? = ShellUtils.execRootCmdAndGetResult(chmod) + recursiveChmod777(dst) +// LogUtils.d( +// "TaskUtil", +// "chmodResult. Result: $chmodResult", +// null +// ) +// if ( result.trim { it <= ' ' }.isEmpty()) { +// LogUtils.d( +// "TaskUtil", +// "Command execution failed. Result: $result", +// null +// ) +// return false +// } + + Log.i("TaskUtil", "Command executed successfully: $result") + return true + } catch (e: java.lang.Exception) { + LogUtils.d( + Log.ERROR, + "TaskUtil", + "Error occurred during copyFolderSh operation", + e + ) + return false + } + } + + fun recursiveChmod777(dir: File?) { + if (dir == null || !dir.exists()) { + Log.e("Chmod", "目录不存在或为null") + return + } + + // 先修改当前目录权限 + val currentPath = dir.getAbsolutePath().replace(" ", "\\ ").replace("\"", "\\\"") + var chmodCmd = "chmod 777 \"$currentPath\"" + ShellUtils.execRootCmdAndGetResult(chmodCmd) + + // 递归处理子项 + val children = dir.listFiles() + if (children != null) { + for (child in children) { + if (child.isDirectory()) { + recursiveChmod777(child) // 递归处理子目录 + } else { + val filePath = child.getAbsolutePath().replace(" ", "\\ ").replace("\"", "\\\"") + chmodCmd = "chmod 777 \"$filePath\"" + ShellUtils.execRootCmdAndGetResult(chmodCmd) + } + } + } + } } diff --git a/app/src/main/java/com/android/grape/util/JsonUtils.kt b/app/src/main/java/com/android/grape/util/JsonUtils.kt index 67f07a8..2b49c5c 100644 --- a/app/src/main/java/com/android/grape/util/JsonUtils.kt +++ b/app/src/main/java/com/android/grape/util/JsonUtils.kt @@ -377,7 +377,6 @@ object JsonUtils { @Throws(Exception::class) fun execSetJson(context: Context) { try { - MockTools.exec("rm -rf /data/system/Logs.txt") JsonUtils.afterJson() if (JsonUtils.initParamsJson(context)) { execRecord(context) diff --git a/app/src/main/java/com/android/grape/util/TaskUtils.kt b/app/src/main/java/com/android/grape/util/TaskUtils.kt index 326d661..a2a2472 100644 --- a/app/src/main/java/com/android/grape/util/TaskUtils.kt +++ b/app/src/main/java/com/android/grape/util/TaskUtils.kt @@ -2,6 +2,7 @@ package com.android.grape.util import android.R.attr.name import android.content.Context +import android.os.Environment import android.os.Handler import android.os.Looper import android.provider.Settings @@ -45,6 +46,7 @@ import com.android.grape.job.UnInstallService import com.android.grape.manager.ConfigManager import com.android.grape.manager.ConfigManager.initDefaultAppJo import com.android.grape.manager.ConfigManager.initDefaultProxyJo +import com.android.grape.sai.Utils import com.android.grape.util.AppUtils.execTargetApp import com.android.grape.util.AppUtils.getApkPackageName import com.android.grape.util.AppUtils.setTopApp @@ -143,8 +145,13 @@ object TaskUtils { } fun getAfLog(): String { - //return Util.afLog; - return ServiceUtils.readFile("/data/system/Logs.txt") + File( + Environment.getExternalStorageDirectory(), + "script/${recordPackageName}/afLog.txt" + ) + val afLog = FileUtils.getString("${Environment.getExternalStorageDirectory()}/script/${recordPackageName}", "afLog.txt") + Log.d("TaskUtils", "getAfLog: $afLog") + return afLog }