refactor(app): 优化代码结构和可读性

- 为类和方法添加注释,解释其功能和使用场景
-优化变量命名,使其更具描述性和一致性
- 重新组织代码结构,提高逻辑清晰度
-移除冗余代码和不必要的空行
- 统一代码格式和风格
This commit is contained in:
yjj38 2025-07-15 19:02:16 +08:00
parent a351355b49
commit 4a6348642d
7 changed files with 235 additions and 59 deletions

View File

@ -20,18 +20,52 @@ import com.android.grape.util.ScriptUtil
import com.android.grape.util.StoragePermissionHelper
import com.android.grape.util.Util.killRecordProcess
/**
* public class MainActivity extends AppCompatActivity
*/
class MainActivity : AppCompatActivity() {
/**
private MainViewModel viewModel = new ViewModelProvider(this).get(MainViewModel.class);
*/
private val viewModel by viewModels<MainViewModel>()
/**
* private ActivityMainBinding viewBinding;
*/
private lateinit var viewBinding: ActivityMainBinding
private lateinit var permissionHandler: NotificationPermissionHandler
private lateinit var socketServer: SocketServer
/**
* 基础设置调用 super.onCreate() enableEdgeToEdge() 启用全面屏支持
* 绑定视图使用 ViewBinding 加载布局
*
* 权限检查调用 checkPermission() 请求通知和存储权限
* 服务与监听注册脚本接收器设置按钮点击监听器以启动或停止监控服务
*
* Socket 服务器初始化创建并配置本地 Socket 服务器注释部分为通信逻辑
*/
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
init()
/**
viewBinding = ActivityMainBinding.inflate(layoutInflater)
使用 ActivityMainBinding 对当前 Activity 的布局文件进行绑定生成可访问 UI 元素的绑定对象
setContentView(viewBinding.root) 将绑定对象中的根视图设置为 Activity 的内容视图完成界面加载
*/
viewBinding = ActivityMainBinding.inflate(layoutInflater)
setContentView(viewBinding.root)
socketServer = SocketServer(8888)
/**
* 这段代码用于适配系统窗口如状态栏导航栏的内边距确保内容不被遮挡
* 设置窗口边距监听器通过 ViewCompat.setOnApplyWindowInsetsListener ID main 的根视图设置监听
* 获取系统栏边距 insets 中提取状态栏和导航栏的边距信息
* 设置视图内边距将视图的内边距设为系统栏的边距使内容避开系统栏区域
*/
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main)) { v, insets ->
val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom)

View File

@ -3,10 +3,31 @@ package com.android.grape
import android.app.Application
import com.blankj.utilcode.util.LogUtils
/**
* Android应用的主入口MainApplication类其功能如下
* 单例实例通过伴生对象的instance属性实现全局访问点
* 初始化日志记录在onCreate()中启用日志写入文件功能
* 环境初始化initEvn()方法设置本地库路径确保JNI等组件能正确加载
*/
class MainApplication : Application() {
/**
private static MainApplication instance;
public static MainApplication getInstance() {
return instance;
}
*/
companion object {
lateinit var instance: MainApplication
}
/**
* 调用父类方法super.onCreate() 确保系统完成基础初始化
* 设置全局实例instance = this 将当前实例赋值给伴生对象中的 instance
* 启用日志写入文件通过 LogUtils 开启日志记录到文件功能
* 初始化环境配置调用 initEvn() 设置本地库路径
*/
override fun onCreate() {
super.onCreate()
instance = this

View File

@ -8,9 +8,25 @@ import com.android.grape.service.MyAccessibilityService
import com.android.grape.work.CheckAccessibilityWorker
import java.util.concurrent.TimeUnit
/**
* 继承 ViewModel用于在 Activity/Fragment 生命周期中保留 UI 相关数据
* 检查无障碍服务状态调用 CheckAccessibilityWorker.isAccessibilityServiceEnabled() 检查 MyAccessibilityService 是否启用
* 定时检测机制若未启用则通过 WorkManager 提交一个每 15 分钟执行一次的周期性任务持续检查用户是否开启该服务
*/
class MainViewModel : ViewModel() {
/**
* 这段代码用于检查无障碍服务是否启用若未启用则定时检测
* 检查服务状态调用 CheckAccessibilityWorker.isAccessibilityServiceEnabled() 判断 MyAccessibilityService 是否已开启
* 未启用则提交定时任务若未启用使用 WorkManager 提交一个每 15 分钟执行一次的后台任务 CheckAccessibilityWorker用于持续检查用户是否启用了该服务
*/
fun checkAccessibilityService() {
/**
* boolean accessibilityServiceEnabled = CheckAccessibilityWorker.isAccessibilityServiceEnabled(
* MainApplication.getInstance(),
* MyAccessibilityService.class
* );
*/
val accessibilityServiceEnabled = CheckAccessibilityWorker.isAccessibilityServiceEnabled(
MainApplication.instance,
MyAccessibilityService::class.java

View File

@ -8,10 +8,19 @@ import com.android.grape.util.ClashUtil
import com.android.grape.util.MockTools
import com.android.grape.util.Util
/**
* 监听任务
这段 Kotlin 代码定义了 MonitorService 继承自 JobIntentService用于执行异步后台任务
onHandleWork 入口方法防止重复执行调用核心逻辑 exec()
伴生对象Companion Object 提供静态方法 onEvent 启动服务任务setRunning 控制任务状态
*/
class MonitorService : JobIntentService() {
/**
* 这段代码是 MonitorService 中的 onHandleWork 方法用于处理后台任务
* 日志记录打印当前任务开始执行的日志信息
* 防止重复执行通过 running 标志判断是否已在运行若未运行则将其设为 true 并执行 exec() 方法
*/
override fun onHandleWork(intent: Intent) {
Log.i(TAG, "onHandleWork ... $running")
if (!running) {
@ -20,6 +29,14 @@ class MonitorService : JobIntentService() {
}
}
/**
* 这段代码定义了 exec() 方法用于执行核心监控任务
* 设置 APK 权限通过 chmod 777 修改 APK 文件权限
* 切换 VPN 代理调用 ClashUtil.switchProxyGroup 切换代理组为直连
* 判断任务类型
* 如果 clickTime > 0触发回调任务 SendCallbackJobService.onEvent
* 否则执行默认任务 Util.execTask
*/
protected fun exec() {
try {
val apkRoot = "chmod 777 $packageCodePath"
@ -40,12 +57,37 @@ class MonitorService : JobIntentService() {
}
}
/**
* private static final String TAG = "IOSTQ:MonitorService";
* private static final int JOB_ID = 101;
*
* private static boolean running = false;
*
* public static void onEvent(Context context) {
* Intent intent = new Intent(context, MonitorService.class);
* enqueueWork(context, MonitorService.class, JOB_ID, intent);
* }
*
* public static void setRunning(boolean runningV) {
* running = runningV;
* }
*/
companion object {
private const val TAG = "IOSTQ:MonitorService"
private const val jobId = 101
private var running = false
/**
* 这段代码定义了一个静态方法 onEvent用于启动一个后台任务
* 封装 Intent创建一个用于启动 MonitorService Intent
* 提交异步任务通过 enqueueWork() 将该服务作为后台任务入队由系统调度执行
*
* public static void onEvent(Context context) {
* Intent intent = new Intent(context, MonitorService.class);
* enqueueWork(context, MonitorService.class, jobId, intent);
* }
*/
fun onEvent(context: Context) {
enqueueWork(
context,

View File

@ -18,6 +18,16 @@ import java.io.File
import java.util.concurrent.TimeUnit
class SendCallbackJobService : JobIntentService() {
/**
* 日志记录打印任务开始执行的日志
* 判断安装状态通过 Util.isInstallRet() 判断是否需要发送安装结果
* 发送备份数据调用 SendBackup() 发送备份信息
* 根据状态选择操作
* 若需恢复则调用 sendReloginEvent()
* 否则调用 sendLogEvent() 发送日志事件
* 结束任务调用 Util.setFinish() 标记任务完成
*/
override fun onHandleWork(intent: Intent) {
LogUtils.i(TAG, "onHandleWork")
@ -271,6 +281,11 @@ class SendCallbackJobService : JobIntentService() {
return result
}
/**
* class PostRet {
* int succ = 0;
* }
*/
internal class PostRet {
var succ: Int = 0
}
@ -280,6 +295,10 @@ class SendCallbackJobService : JobIntentService() {
private const val jobId = 700
/**
* 封装 Intent创建一个用于启动 SendCallbackJobService Intent
* 提交异步任务通过 enqueueWork() 将该服务作为后台任务入队由系统调度执行
*/
fun onEvent(context: Context) {
enqueueWork(
context,

View File

@ -44,6 +44,28 @@ object ScriptUtil {
}
}
/**
* public static void registerScriptResultReceiver() {
* if (scriptResultReceiver == null) {
* scriptResultReceiver = new ScriptReceiver();
* try {
* IntentFilter filter = new IntentFilter(AUTOJS_SCRIPT_FINISHED_ACTION);
* ContextCompat.registerReceiver(
* MainApplication.getInstance(),
* scriptResultReceiver,
* filter,
* ContextCompat.RECEIVER_EXPORTED
* );
* LogUtils.d("广播接收器成功注册", null);
* } catch (Exception e) {
* LogUtils.e("Failed to register receiver", e);
* scriptResultReceiver = null;
* }
* } else {
* LogUtils.d("广播接收器已注册,无需重复注册");
* }
* }
*/
fun registerScriptResultReceiver() {
if (scriptResultReceiver == null) {
scriptResultReceiver = ScriptReceiver()

View File

@ -676,11 +676,11 @@ object Util {
/**
* 通过将请求发送到具有必要参数的指定URL来执行Relogin任务
* 此方法初始化必要组件构造请求参数提出邮政请求
* 并处理响应以确定下一步
*
* @param上下文呼叫组件的上下文用于检索资源和系统级服务
构建请求参数获取设备唯一 ID拼接请求 URL
发送 POST 请求调用 MyPost.postData 向服务器提交请求
处理响应结果
成功时设置权限解析 JSON 数据并设置 clickTime
失败或异常时调用 setFinish 结束任务
*/
fun execReloginTask(context: Context) {
init()
@ -693,7 +693,8 @@ object Util {
val valid = false
println("IOSTQ:execReloginTask->url:$url?$params")
try {
val result: String? = MyPost.postData(" ".toByteArray(charset = Charsets.UTF_8),
val result: String? = MyPost.postData(
" ".toByteArray(charset = Charsets.UTF_8),
"$url?$params"
)
LogUtils.e("IOSTQ:execReloginTask->result:$result")
@ -724,22 +725,23 @@ object Util {
}
/**
* 通过启动必要的配置执行安装任务
* 将请求发送到带有某些参数的指定服务器URL
* 并处理响应以执行后续操作
*
* @param 上下文执行任务的上下文它习惯了
* 访问系统资源和特定于应用程序的详细信息
* 初始化并构建请求参数获取设备唯一 IDANDROID_ID拼接请求 URL
* 发送 POST 请求通过 MyPost.postData 向服务器提交安装请求
* 处理响应结果
* 成功时解析 JSON 数据设置权限并触发 clickTime 1 表示需执行点击操作
* 失败或异常时调用 setFinish 结束任务
*/
fun execInstallTask(context: Context) {
init()
val url = "http://39.103.73.250/tt/ddj/preRequest!requestInstall.do"
val ANDROID_ID = Settings.System.getString(context.contentResolver, Settings.System.ANDROID_ID)
val ANDROID_ID =
Settings.System.getString(context.contentResolver, Settings.System.ANDROID_ID)
val params = "platform=Android&tag=119&uuid=$ANDROID_ID"
printStr("IOSTQ:request result : $url?$params")
try {
val result: String? = MyPost.postData(" ".toByteArray(charset = Charsets.UTF_8),
val result: String? = MyPost.postData(
" ".toByteArray(charset = Charsets.UTF_8),
"$url?$params"
)
@ -1141,7 +1143,11 @@ object Util {
try {
var url = "http://39.103.73.250/tt/upload/ddj/$recordFileName"
var ret = false
ret = if (checkAppInstalled(context, recordPackageName) || !CheckAppNeedUpgrade(context)) {
ret = if (checkAppInstalled(
context,
recordPackageName
) || !CheckAppNeedUpgrade(context)
) {
true
} else {
downloadFile(url, "/sdcard/apks/$recordFileName")
@ -1157,10 +1163,14 @@ object Util {
if (isNeedRestored) {
println("IOSTQ:开始下载留存文件")
taskJson?.let {
if (it.has("BackupFileUrl1") && it.getString("BackupFileUrl1").isNotEmpty()) {
var restored_zip = "http://192.168.1.111/tt/" + it.getString("BackupFileUrl1")
if (it.has("BackupFileUrl1") && it.getString("BackupFileUrl1")
.isNotEmpty()
) {
var restored_zip =
"http://192.168.1.111/tt/" + it.getString("BackupFileUrl1")
if (backUpServerIp.isNotEmpty()) {
restored_zip = "http://" + backUpServerIp + "/tt/" + it.getString("BackupFileUrl1")
restored_zip =
"http://" + backUpServerIp + "/tt/" + it.getString("BackupFileUrl1")
}
ret = downloadFile(restored_zip, getRecordDataFileName(context))
}
@ -1831,7 +1841,8 @@ object Util {
fun isBackground(context: Context): Boolean {
val activityManager: ActivityManager =
context.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
val appProcesses: List<ActivityManager.RunningAppProcessInfo> = activityManager.getRunningAppProcesses()
val appProcesses: List<ActivityManager.RunningAppProcessInfo> =
activityManager.getRunningAppProcesses()
var isBackground = true
var processName = "empty"
for (appProcess in appProcesses) {
@ -2505,7 +2516,8 @@ object Util {
context.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
//获得当前运行的task(任务)
val taskInfoList: List<ActivityManager.RunningTaskInfo> = activityManager.getRunningTasks(100)
val taskInfoList: List<ActivityManager.RunningTaskInfo> =
activityManager.getRunningTasks(100)
for (taskInfo in taskInfoList) {
//找到本应用的 task并将它切换到前台
if (taskInfo.baseActivity?.packageName == context.packageName) {
@ -2671,7 +2683,8 @@ object Util {
}
try {
val zipDirName = getBaseFilesDir(context) + "/" + monitorDir + "/" + packageName
val zipFileName = getBaseFilesDir(context) + "/" + monitorDir + "/" + packageName + ".zip"
val zipFileName =
getBaseFilesDir(context) + "/" + monitorDir + "/" + packageName + ".zip"
Log.i(TAG, "backupDataFile-> zipDirName:$zipDirName ; zipFileName:$zipFileName")
val zipFile = File(zipFileName)
forceMakeDir(File(getRecordDataDirName(context)))
@ -2686,7 +2699,8 @@ object Util {
if (file.exists()) {
val ss = getStringFromFile(context, file.absolutePath)
if (ss.isNotEmpty()) {
val arr = ss.split("\n".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
val arr =
ss.split("\n".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
for (line in arr) {
Log.i(TAG, "line:$line")
val blankPos = line.lastIndexOf(" ")
@ -2883,11 +2897,19 @@ object Util {
backUp(context, recordPackageName)
}
/**
* 停止与给定软件包名称关联的申请过程
* public static void killRecordProcess(Context context, String packageName) {
* Log.i(TAG, "start killRecordProcess :" + packageName);
*
* @param上下文调用该方法的上下文
* @param packageName 将强制终止的应用程序的软件包名称
* try {
* String cmd = "am force-stop " + packageName;
* Log.i(TAG, "killRecordProcess-> cmd:" + cmd);
* MockTools.exec(cmd);
* } catch (Exception e) {
* e.printStackTrace();
* }
* }
*/
fun killRecordProcess(context: Context?, packageName: String?) {
Log.i(TAG, "start killRecordProcess :$packageName")