Refactor `AutoJsUtil` and `MainActivity` for enhanced script handling and synchronization
Introduced synchronized locking for script execution flow in `MainActivity` and added a robust broadcast receiver registration process in `AutoJsUtil`. Enhanced logging, error handling, and script management utilities. Updated `AutoJsUtil` with better file validation and context-aware lifecycle methods for improved stability and clarity.
This commit is contained in:
parent
b6e312cf9e
commit
dc2fdd615e
|
@ -4,10 +4,10 @@
|
||||||
<selectionStates>
|
<selectionStates>
|
||||||
<SelectionState runConfigName="app">
|
<SelectionState runConfigName="app">
|
||||||
<option name="selectionMode" value="DROPDOWN" />
|
<option name="selectionMode" value="DROPDOWN" />
|
||||||
<DropdownSelection timestamp="2025-05-29T05:57:33.756287400Z">
|
<DropdownSelection timestamp="2025-06-12T11:18:56.273211900Z">
|
||||||
<Target type="DEFAULT_BOOT">
|
<Target type="DEFAULT_BOOT">
|
||||||
<handle>
|
<handle>
|
||||||
<DeviceId pluginId="Default" identifier="serial=8.217.74.194:1151;connection=7a73959e" />
|
<DeviceId pluginId="Default" identifier="serial=8.217.74.194:1137;connection=230c8044" />
|
||||||
</handle>
|
</handle>
|
||||||
</Target>
|
</Target>
|
||||||
</DropdownSelection>
|
</DropdownSelection>
|
||||||
|
|
|
@ -2,6 +2,7 @@ package com.example.studyapp;
|
||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.app.AlertDialog;
|
import android.app.AlertDialog;
|
||||||
|
import android.content.BroadcastReceiver;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
|
@ -32,6 +33,7 @@ import com.example.studyapp.device.ChangeDeviceInfoUtil;
|
||||||
|
|
||||||
import com.example.studyapp.utils.ClashUtil;
|
import com.example.studyapp.utils.ClashUtil;
|
||||||
import com.example.studyapp.worker.CheckAccessibilityWorker;
|
import com.example.studyapp.worker.CheckAccessibilityWorker;
|
||||||
|
import java.lang.ref.WeakReference;
|
||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.ExecutorService;
|
||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
import java.util.concurrent.Future;
|
import java.util.concurrent.Future;
|
||||||
|
@ -42,11 +44,13 @@ import java.util.concurrent.TimeoutException;
|
||||||
|
|
||||||
public class MainActivity extends AppCompatActivity {
|
public class MainActivity extends AppCompatActivity {
|
||||||
|
|
||||||
|
private static WeakReference<MainActivity> instance;
|
||||||
|
|
||||||
private static final int REQUEST_CODE_STORAGE_PERMISSION = 1;
|
private static final int REQUEST_CODE_STORAGE_PERMISSION = 1;
|
||||||
|
|
||||||
private static final int ALLOW_ALL_FILES_ACCESS_PERMISSION_CODE = 1001;
|
private static final int ALLOW_ALL_FILES_ACCESS_PERMISSION_CODE = 1001;
|
||||||
|
|
||||||
private ExecutorService executorService;
|
public ExecutorService executorService;
|
||||||
|
|
||||||
// 假设我们从配置文件中提取出了以下 name 项数据(仅为部分示例数据)
|
// 假设我们从配置文件中提取出了以下 name 项数据(仅为部分示例数据)
|
||||||
private final String[] proxyNames = {
|
private final String[] proxyNames = {
|
||||||
|
@ -82,6 +86,7 @@ public class MainActivity extends AppCompatActivity {
|
||||||
protected void onCreate(@Nullable Bundle savedInstanceState) {
|
protected void onCreate(@Nullable Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
setContentView(R.layout.activity_main);
|
setContentView(R.layout.activity_main);
|
||||||
|
instance = new WeakReference<>(this);
|
||||||
|
|
||||||
initializeExecutorService();
|
initializeExecutorService();
|
||||||
System.setProperty("java.library.path", this.getApplicationInfo().nativeLibraryDir);
|
System.setProperty("java.library.path", this.getApplicationInfo().nativeLibraryDir);
|
||||||
|
@ -217,12 +222,6 @@ public class MainActivity extends AppCompatActivity {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (number > proxyNames.length) {
|
|
||||||
Log.e("MainActivity", "executeLogic: Number exceeds proxyNames length: " + number);
|
|
||||||
Toast.makeText(this, "输入的数字超出代理名称范围", Toast.LENGTH_SHORT).show();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!isNetworkAvailable(this)) {
|
if (!isNetworkAvailable(this)) {
|
||||||
Log.e("MainActivity", "executeLogic: Network is not available!");
|
Log.e("MainActivity", "executeLogic: Network is not available!");
|
||||||
Toast.makeText(this, "网络不可用,请检查网络连接", Toast.LENGTH_SHORT).show();
|
Toast.makeText(this, "网络不可用,请检查网络连接", Toast.LENGTH_SHORT).show();
|
||||||
|
@ -230,21 +229,31 @@ public class MainActivity extends AppCompatActivity {
|
||||||
}
|
}
|
||||||
|
|
||||||
Log.i("MainActivity", "executeLogic: Submitting job to executor");
|
Log.i("MainActivity", "executeLogic: Submitting job to executor");
|
||||||
long startTime = System.currentTimeMillis(); // 开始计时
|
|
||||||
|
|
||||||
initializeExecutorService();
|
initializeExecutorService();
|
||||||
executorService.submit(() -> {
|
executorService.submit(() -> {
|
||||||
try {
|
try {
|
||||||
|
AutoJsUtil.flag = true;
|
||||||
for (int i = 0; i < number; i++) {
|
for (int i = 0; i < number; i++) {
|
||||||
|
synchronized (lock) {
|
||||||
|
// 等待 flag 设置为 false 时暂停
|
||||||
|
while (!AutoJsUtil.flag) {
|
||||||
|
lock.wait(); // 当前线程进入等待状态
|
||||||
|
}
|
||||||
|
// 执行实际逻辑
|
||||||
executeSingleLogic(i);
|
executeSingleLogic(i);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
Log.e("MainActivity", "executeLogic: Thread interrupted while waiting", e);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Log.e("MainActivity", "executeLogic: Unexpected task error.", e);
|
Log.e("MainActivity", "executeLogic: Unexpected task error.", e);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void executeSingleLogic(int i) {
|
public final static Object lock = new Object();
|
||||||
|
|
||||||
|
public void executeSingleLogic(int i) {
|
||||||
Log.i("MainActivity", "executeSingleLogic: Start execution for index " + i);
|
Log.i("MainActivity", "executeSingleLogic: Start execution for index " + i);
|
||||||
long startTime = System.currentTimeMillis(); // 开始计时
|
long startTime = System.currentTimeMillis(); // 开始计时
|
||||||
|
|
||||||
|
@ -344,6 +353,7 @@ public class MainActivity extends AppCompatActivity {
|
||||||
@Override
|
@Override
|
||||||
protected void onDestroy() {
|
protected void onDestroy() {
|
||||||
super.onDestroy();
|
super.onDestroy();
|
||||||
|
instance.clear();
|
||||||
if (AutoJsUtil.scriptResultReceiver != null) {
|
if (AutoJsUtil.scriptResultReceiver != null) {
|
||||||
unregisterReceiver(AutoJsUtil.scriptResultReceiver);
|
unregisterReceiver(AutoJsUtil.scriptResultReceiver);
|
||||||
}
|
}
|
||||||
|
@ -352,6 +362,10 @@ public class MainActivity extends AppCompatActivity {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static MainActivity getInstance() {
|
||||||
|
return instance.get(); // 返回实例
|
||||||
|
}
|
||||||
|
|
||||||
private boolean isNetworkAvailable(Context context) {
|
private boolean isNetworkAvailable(Context context) {
|
||||||
ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
|
ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
|
||||||
if (connectivityManager != null) {
|
if (connectivityManager != null) {
|
||||||
|
|
|
@ -2,12 +2,14 @@ package com.example.studyapp.autoJS;
|
||||||
|
|
||||||
import static androidx.core.content.ContextCompat.startActivity;
|
import static androidx.core.content.ContextCompat.startActivity;
|
||||||
|
|
||||||
|
import android.Manifest;
|
||||||
import android.content.ActivityNotFoundException;
|
import android.content.ActivityNotFoundException;
|
||||||
import android.content.BroadcastReceiver;
|
import android.content.BroadcastReceiver;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.IntentFilter;
|
import android.content.IntentFilter;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
|
import android.os.Build;
|
||||||
import android.os.Environment;
|
import android.os.Environment;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.os.Looper;
|
import android.os.Looper;
|
||||||
|
@ -31,12 +33,14 @@ import retrofit2.converter.gson.GsonConverterFactory;
|
||||||
public class AutoJsUtil {
|
public class AutoJsUtil {
|
||||||
|
|
||||||
public static BroadcastReceiver scriptResultReceiver;
|
public static BroadcastReceiver scriptResultReceiver;
|
||||||
|
public static volatile boolean flag;
|
||||||
|
|
||||||
public static void runAutojsScript(Context context,String url) {
|
public static void runAutojsScript(Context context,String url) {
|
||||||
// 检查脚本文件
|
// 检查脚本文件
|
||||||
File scriptFile = new File(Environment.getExternalStorageDirectory(), "script/main.js");
|
File scriptFile = new File(Environment.getExternalStorageDirectory(), "script/main.js");
|
||||||
if (!scriptFile.exists()) {
|
if (!scriptFile.exists()) {
|
||||||
runOnUiThread(() -> Toast.makeText(context, "Script file not found: " + scriptFile.getAbsolutePath(), Toast.LENGTH_SHORT).show());
|
runOnUiThread(() -> Toast.makeText(context, "脚本文件未找到: " + scriptFile.getAbsolutePath(), Toast.LENGTH_SHORT).show());
|
||||||
|
Log.e("AutoJsUtil", "脚本文件未找到, 路径: " + scriptFile.getAbsolutePath());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,40 +50,51 @@ public class AutoJsUtil {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 开始运行脚本
|
// 启动 AutoJs
|
||||||
Intent intent = new Intent();
|
Intent intent = new Intent();
|
||||||
intent.setClassName("org.autojs.autojs6", "org.autojs.autojs.external.open.RunIntentActivity");
|
intent.setClassName("org.autojs.autojs6", "org.autojs.autojs.external.open.RunIntentActivity");
|
||||||
intent.putExtra("path", scriptFile.getAbsolutePath());
|
intent.putExtra("path", scriptFile.getAbsolutePath());
|
||||||
intent.putExtra("url",url);
|
intent.putExtra("url", url);
|
||||||
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
registerScriptResultReceiver(context);
|
||||||
context.startActivity(intent);
|
context.startActivity(intent);
|
||||||
runOnUiThread(() -> Toast.makeText(context, "Running script: " + scriptFile.getAbsolutePath(), Toast.LENGTH_SHORT).show());
|
Log.i("AutoJsUtil", "脚本运行中:" + scriptFile.getAbsolutePath());
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
Log.e("AutoJsUtil", "运行脚本失败", e);
|
||||||
runOnUiThread(() -> Toast.makeText(context, "Failed to run script", Toast.LENGTH_SHORT).show());
|
runOnUiThread(() -> Toast.makeText(context, "运行脚本失败: " + e.getMessage(), Toast.LENGTH_SHORT).show());
|
||||||
}
|
}
|
||||||
|
// 注意:unregisterScriptResultReceiver 不应到此时立即调用
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void stopAutojsScript(Context context) {
|
public static void registerScriptResultReceiver(Context context) {
|
||||||
// 停止运行脚本
|
// 使用锁进行控制
|
||||||
Intent stopIntent = new Intent();
|
synchronized (MainActivity.lock) {
|
||||||
stopIntent.setClassName("org.autojs.autojs6", "org.autojs.autojs.external.open.StopServiceActivity");
|
if (scriptResultReceiver == null) {
|
||||||
stopIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
|
// 创建广播接收器
|
||||||
|
scriptResultReceiver = new BroadcastReceiver() {
|
||||||
// 检查目标活动是否存在
|
@Override
|
||||||
if (isActivityAvailable(context, "org.autojs.autojs6", "org.autojs.autojs.external.open.StopServiceActivity")) {
|
public void onReceive(Context context, Intent intent) {
|
||||||
|
String scriptResult = intent.getStringExtra("result");
|
||||||
|
if (scriptResult != null && !scriptResult.isEmpty()) {
|
||||||
|
Log.d("MainActivity", "Script result received");
|
||||||
|
synchronized (MainActivity.lock){
|
||||||
|
flag = true;
|
||||||
|
MainActivity.lock.notifyAll();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
// 注册广播接收器
|
||||||
try {
|
try {
|
||||||
context.startActivity(stopIntent); // 发送停止脚本的 Intent
|
IntentFilter filter = new IntentFilter(AUTOJS_SCRIPT_FINISHED_ACTION);
|
||||||
Toast.makeText(context, "脚本停止管理已发送", Toast.LENGTH_SHORT).show();
|
Context appContext = context.getApplicationContext();
|
||||||
|
ContextCompat.registerReceiver(appContext, scriptResultReceiver, filter, ContextCompat.RECEIVER_EXPORTED);
|
||||||
|
flag = false;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Toast.makeText(context, "无法发送停止命令,请检查 AutoJs 配置", Toast.LENGTH_SHORT).show();
|
Log.e("MainActivity", "Failed to register receiver", e);
|
||||||
Log.e("AutoJsUtil", "Error occurred when trying to stop AutoJs script", e);
|
}
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
Toast.makeText(context, "目标活动未找到:请确认 AutoJs 配置", Toast.LENGTH_LONG).show();
|
|
||||||
Log.e("AutoJsUtil", "Activity not found: org.autojs.autojs.external.open.StopServiceActivity");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -105,62 +120,42 @@ public class AutoJsUtil {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void registerScriptResultReceiver(Context context) {
|
private static final String AUTOJS_SCRIPT_FINISHED_ACTION = "org.autojs.SCRIPT_FINISHED";
|
||||||
// 创建广播接收器
|
private static final String SCRIPT_RESULT_KEY = "result";
|
||||||
scriptResultReceiver = new BroadcastReceiver() {
|
private static final Object lock = new Object();
|
||||||
@Override
|
|
||||||
public void onReceive(Context context, Intent intent) {
|
|
||||||
// 获取脚本运行结果(假设结果通过 "result" 键返回)
|
public static void unregisterScriptResultReceiver(Context context) {
|
||||||
String scriptResult = intent.getStringExtra("result");
|
synchronized (lock) {
|
||||||
if (scriptResult != null && !scriptResult.isEmpty()) {
|
if (scriptResultReceiver != null) {
|
||||||
// 处理结果并发送给服务端
|
context.getApplicationContext().unregisterReceiver(scriptResultReceiver);
|
||||||
sendResultToServer(scriptResult,context);
|
scriptResultReceiver = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
// 注册接收器(假设 Auto.js 广播动作为 "org.autojs.SCRIPT_FINISHED")
|
|
||||||
IntentFilter filter = new IntentFilter("org.autojs.SCRIPT_FINISHED");
|
|
||||||
|
|
||||||
// 使用 ContextCompat.registerReceiver 注册,并设置为 RECEIVER_EXPORTED
|
|
||||||
ContextCompat.registerReceiver(
|
|
||||||
context, // 当前上下文
|
|
||||||
scriptResultReceiver, // 自定义的 BroadcastReceiver
|
|
||||||
filter, // IntentFilter
|
|
||||||
ContextCompat.RECEIVER_EXPORTED // 设置为非导出广播接收器
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void sendResultToServer(String scriptResult,Context context) {
|
public static void stopAutojsScript(Context context) {
|
||||||
// 使用 Retrofit 或 HttpURLConnection 实现服务端 API 调用
|
// 停止运行脚本的 Intent
|
||||||
Toast.makeText(context, "Sending result to server: " + scriptResult, Toast.LENGTH_SHORT).show();
|
Intent stopIntent = new Intent();
|
||||||
|
stopIntent.setClassName("org.autojs.autojs6", "org.autojs.autojs.external.open.StopServiceActivity");
|
||||||
|
stopIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
|
||||||
|
|
||||||
// 示例:用 Retrofit 设置服务端请求
|
// 检查目标活动是否存在
|
||||||
// 创建 Retrofit 的实例
|
boolean activityAvailable = isActivityAvailable(context, "org.autojs.autojs6", "org.autojs.autojs.external.open.StopServiceActivity");
|
||||||
Retrofit retrofit = new Retrofit.Builder()
|
Log.d("AutoJsUtil", "是否找到目标活动: " + activityAvailable);
|
||||||
.baseUrl("https://your-server-url.com/") // 替换为服务端 API 地址
|
|
||||||
.addConverterFactory(GsonConverterFactory.create())
|
|
||||||
.build();
|
|
||||||
|
|
||||||
// 定义 API 接口
|
if (activityAvailable) {
|
||||||
CloudPhoneManageService api = retrofit.create(CloudPhoneManageService.class);
|
try {
|
||||||
|
context.startActivity(stopIntent); // 尝试发送停止脚本的 Intent
|
||||||
// 构建请求体并发送请求
|
Toast.makeText(context, "脚本停止命令已发送", Toast.LENGTH_SHORT).show();
|
||||||
Call<Void> call = api.sendScriptResult(new ScriptResultRequest(scriptResult)); // 假设参数是 com.example.studyapp.request.ScriptResultRequest 对象
|
} catch (Exception e) {
|
||||||
call.enqueue(new Callback<Void>() {
|
Toast.makeText(context, "无法发送停止命令,请检查 AutoJs 配置", Toast.LENGTH_SHORT).show();
|
||||||
@Override
|
Log.e("AutoJsUtil", "发送停止命令时发生错误", e);
|
||||||
public void onResponse(Call<Void> call, Response<Void> response) {
|
}
|
||||||
if (response.isSuccessful()) {
|
|
||||||
Toast.makeText(context, "Result sent successfully", Toast.LENGTH_SHORT).show();
|
|
||||||
} else {
|
} else {
|
||||||
Toast.makeText(context, "Failed to send result: " + response.code(), Toast.LENGTH_SHORT).show();
|
Toast.makeText(context, "目标活动未找到或已更改,请检查 AutoJs 配置", Toast.LENGTH_LONG).show();
|
||||||
|
Log.e("AutoJsUtil", "目标活动未找到: org.autojs.autojs.external.open.StopServiceActivity");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onFailure(Call<Void> call, Throwable t) {
|
|
||||||
Toast.makeText(context, "Error sending result: " + t.getMessage(), Toast.LENGTH_SHORT).show();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue