refactor(app): 优化代码结构和可读性
- 为类和方法添加注释,解释其功能和使用场景 -优化变量命名,使其更具描述性和一致性 - 重新组织代码结构,提高逻辑清晰度 -移除冗余代码和不必要的空行 - 统一代码格式和风格
This commit is contained in:
parent
a351355b49
commit
4a6348642d
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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 上下文执行任务的上下文。它习惯了
|
||||
* 访问系统资源和特定于应用程序的详细信息。
|
||||
* 初始化并构建请求参数:获取设备唯一 ID(ANDROID_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")
|
||||
|
|
Loading…
Reference in New Issue