From 645c4b076ad20008bc75960fb62d86fa6679fc08 Mon Sep 17 00:00:00 2001 From: yjj38 Date: Thu, 3 Jul 2025 17:06:17 +0800 Subject: [PATCH] =?UTF-8?q?refactor(proxy):=20=E9=87=8D=E6=9E=84=E4=BB=A3?= =?UTF-8?q?=E7=90=86=E5=B7=A5=E5=85=B7=E7=B1=BB=E5=B9=B6=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E5=9C=B0=E7=90=86=E4=BD=8D=E7=BD=AE=E4=BF=A1=E6=81=AF=E8=8E=B7?= =?UTF-8?q?=E5=8F=96=E5=8A=9F=E8=83=BD-=20=E7=A7=BB=E9=99=A4=E4=BA=86=20Cl?= =?UTF-8?q?ashUtil=20=E4=B8=AD=E7=9A=84=20checkCountryIsUS=20=E6=96=B9?= =?UTF-8?q?=E6=B3=95=20-=20=E5=9C=A8=20IpUtil=20=E4=B8=AD=E6=B7=BB?= =?UTF-8?q?=E5=8A=A0=E4=BA=86=20fetchGeoInfo=20=E6=96=B9=E6=B3=95=EF=BC=8C?= =?UTF-8?q?=E7=94=A8=E4=BA=8E=E8=8E=B7=E5=8F=96=E5=9C=B0=E7=90=86=E4=BD=8D?= =?UTF-8?q?=E7=BD=AE=E4=BF=A1=E6=81=AF=20-=20=E6=9B=B4=E6=96=B0=E4=BA=86?= =?UTF-8?q?=20MainActivity=20=E4=B8=AD=E7=9A=84=E4=BB=A3=E7=90=86=E5=90=AF?= =?UTF-8?q?=E5=8A=A8=E9=80=BB=E8=BE=91=20-=20=E4=BF=AE=E6=94=B9=E4=BA=86?= =?UTF-8?q?=20TaskUtil=20=E4=B8=AD=E7=9A=84=E8=AE=BE=E5=A4=87=E4=BF=A1?= =?UTF-8?q?=E6=81=AF=E4=B8=8A=E4=BC=A0=E9=80=BB=E8=BE=91=EF=BC=8C=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0=E4=BA=86=20IP=E4=BF=A1=E6=81=AF=E5=8F=82=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/example/studyapp/MainActivity.java | 632 +++++++++--------- .../com/example/studyapp/proxy/ClashUtil.java | 49 -- .../com/example/studyapp/task/TaskUtil.java | 19 +- .../com/example/studyapp/utils/IpUtil.java | 35 + .../example/studyapp/task/TaskUtilTest.java | 4 +- 5 files changed, 355 insertions(+), 384 deletions(-) diff --git a/app/src/main/java/com/example/studyapp/MainActivity.java b/app/src/main/java/com/example/studyapp/MainActivity.java index 9e70c64..443b8f9 100644 --- a/app/src/main/java/com/example/studyapp/MainActivity.java +++ b/app/src/main/java/com/example/studyapp/MainActivity.java @@ -35,6 +35,7 @@ import com.example.studyapp.device.ChangeDeviceInfoUtil; import com.example.studyapp.proxy.ClashUtil; import com.example.studyapp.service.MyAccessibilityService; import com.example.studyapp.task.TaskUtil; +import com.example.studyapp.utils.IpUtil; import com.example.studyapp.utils.LogFileUtil; import com.example.studyapp.worker.CheckAccessibilityWorker; @@ -47,53 +48,53 @@ import java.util.concurrent.TimeUnit; public class MainActivity extends AppCompatActivity { - private static WeakReference instance; + private static WeakReference 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; - public static ExecutorService executorService; + public static ExecutorService executorService; - // 假设我们从配置文件中提取出了以下 name 项数据(仅为部分示例数据) - private final String[] proxyNames = { - "mr", "sr", "bq", "ml", "ht", "ga", "mk", "by", "pr", "hr", "hu", - "in", "gt", "at", "kh", "bn", "mg", "kr", "ca", "gh", "ma", "md", - "je", "pa", "ba", "mm", "ir", "gy", "mt", "ae", "es", "ng", "ls", - "ag", "pk", "bd", "kn", "mw", "ve", "hk", "cv", "hn", "tm", "us", - "cz", "ly", "gb", "kz", "it", "bh", "sn", "fi", "co", "sx", "bm", - "fj", "cw", "st", "bw", "fr", "bb", "tg", "ci", "gd", "ne", "bj", - "nz", "rs", "do", "cl", "lb", "nl", "re", "aw", "ug", "sv", "ar", - "jo", "bg", "jp", "rw", "py", "mn", "ec", "uz", "ro", "cu", "gu", - "xk", "sy", "so", "zm", "tz", "ni", "sc", "my", "gf", "na", "zw", - "la", "et", "ao", "ua", "om", "np", "mx", "mz", "dm", "ye", "gi", - "cr", "cm", "ph", "am", "th", "ch", "br", "sd", "ie", "bo", "bs", - "tc", "vg", "pe", "sa", "dk", "tn", "ee", "jm", "lc", "pt", "qa", - "ge", "ps" - }; + // 假设我们从配置文件中提取出了以下 name 项数据(仅为部分示例数据) + private final String[] proxyNames = { + "mr", "sr", "bq", "ml", "ht", "ga", "mk", "by", "pr", "hr", "hu", + "in", "gt", "at", "kh", "bn", "mg", "kr", "ca", "gh", "ma", "md", + "je", "pa", "ba", "mm", "ir", "gy", "mt", "ae", "es", "ng", "ls", + "ag", "pk", "bd", "kn", "mw", "ve", "hk", "cv", "hn", "tm", "us", + "cz", "ly", "gb", "kz", "it", "bh", "sn", "fi", "co", "sx", "bm", + "fj", "cw", "st", "bw", "fr", "bb", "tg", "ci", "gd", "ne", "bj", + "nz", "rs", "do", "cl", "lb", "nl", "re", "aw", "ug", "sv", "ar", + "jo", "bg", "jp", "rw", "py", "mn", "ec", "uz", "ro", "cu", "gu", + "xk", "sy", "so", "zm", "tz", "ni", "sc", "my", "gf", "na", "zw", + "la", "et", "ao", "ua", "om", "np", "mx", "mz", "dm", "ye", "gi", + "cr", "cm", "ph", "am", "th", "ch", "br", "sd", "ie", "bo", "bs", + "tc", "vg", "pe", "sa", "dk", "tn", "ee", "jm", "lc", "pt", "qa", + "ge", "ps" + }; - public static volatile String scriptResult; + public static volatile String scriptResult; - // 初始化 ExecutorService - private void initializeExecutorService() { - if (executorService == null || executorService.isShutdown()) { - executorService = new ThreadPoolExecutor( - 1, // 核心线程数 - 1, // 最大线程数 - 0L, TimeUnit.MILLISECONDS, - new LinkedBlockingQueue<>(50), // 阻塞队列 - new ThreadPoolExecutor.AbortPolicy() // 拒绝策略 - ); - } + // 初始化 ExecutorService + private void initializeExecutorService() { + if (executorService == null || executorService.isShutdown()) { + executorService = new ThreadPoolExecutor( + 1, // 核心线程数 + 1, // 最大线程数 + 0L, TimeUnit.MILLISECONDS, + new LinkedBlockingQueue<>(50), // 阻塞队列 + new ThreadPoolExecutor.AbortPolicy() // 拒绝策略 + ); } + } - /** - * 获取 Android 设备的 ANDROID_ID - * - * @param context 应用上下文 - * @return 设备的 ANDROID_ID,若无法获取,则返回 null - */ - private String getAndroidId(Context context) { + /** + * 获取 Android 设备的 ANDROID_ID + * + * @param context 应用上下文 + * @return 设备的 ANDROID_ID,若无法获取,则返回 null + */ + private String getAndroidId(Context context) { // if (context == null) { // LogFileUtil.logAndWrite(Log.ERROR, "MainActivity", "getAndroidId: Context cannot be null",null); // throw new IllegalArgumentException("Context cannot be null"); @@ -107,89 +108,89 @@ public class MainActivity extends AppCompatActivity { // LogFileUtil.logAndWrite(Log.ERROR, "MainActivity", "getAndroidId: Failed to get ANDROID_ID",e); // return null; // } - return "FyZqWrStUvOpKlMn"; + return "FyZqWrStUvOpKlMn"; + } + + + private static final int REQUEST_CODE_PERMISSIONS = 100; + + @Override + protected void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + LogFileUtil.initialize(this); + setContentView(R.layout.activity_main); + instance = new WeakReference<>(this); + + LogFileUtil.logAndWrite(Log.INFO, "MainActivity", "onCreate: Initializing application", null); + initializeExecutorService(); + System.setProperty("java.library.path", this.getApplicationInfo().nativeLibraryDir); + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.R) { + if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) + != PackageManager.PERMISSION_GRANTED) { + ActivityCompat.requestPermissions( + this, + new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, + REQUEST_CODE_STORAGE_PERMISSION + ); + } + } else { + if (!Environment.isExternalStorageManager()) { + Intent intent = new Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION); + intent.setData(Uri.parse("package:" + getPackageName())); + startActivityForResult(intent, ALLOW_ALL_FILES_ACCESS_PERMISSION_CODE); + } + } + if (!isNetworkAvailable(this)) { + Toast.makeText(this, "Network is not available", Toast.LENGTH_SHORT).show(); + LogFileUtil.logAndWrite(Log.ERROR, "MainActivity", "Network not available, closing app.", null); + finish(); } + LogFileUtil.logAndWrite(Log.INFO, "MainActivity", "onCreate: Setting up work manager", null); + PeriodicWorkRequest workRequest = new PeriodicWorkRequest.Builder(CheckAccessibilityWorker.class, 15, TimeUnit.MINUTES) + .build(); + WorkManager.getInstance(this).enqueue(workRequest); - private static final int REQUEST_CODE_PERMISSIONS = 100; - - @Override - protected void onCreate(@Nullable Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - LogFileUtil.initialize(this); - setContentView(R.layout.activity_main); - instance = new WeakReference<>(this); - - LogFileUtil.logAndWrite(Log.INFO, "MainActivity", "onCreate: Initializing application", null); + LogFileUtil.logAndWrite(Log.INFO, "MainActivity", "onCreate: Setting up UI components", null); + Button runScriptButton = findViewById(R.id.run_script_button); + if (runScriptButton != null) { + runScriptButton.setOnClickListener(v -> { initializeExecutorService(); - System.setProperty("java.library.path", this.getApplicationInfo().nativeLibraryDir); - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.R) { - if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) - != PackageManager.PERMISSION_GRANTED) { - ActivityCompat.requestPermissions( - this, - new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, - REQUEST_CODE_STORAGE_PERMISSION - ); - } - } else { - if (!Environment.isExternalStorageManager()) { - Intent intent = new Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION); - intent.setData(Uri.parse("package:" + getPackageName())); - startActivityForResult(intent, ALLOW_ALL_FILES_ACCESS_PERMISSION_CODE); - } - } - if (!isNetworkAvailable(this)) { - Toast.makeText(this, "Network is not available", Toast.LENGTH_SHORT).show(); - LogFileUtil.logAndWrite(Log.ERROR, "MainActivity", "Network not available, closing app.", null); - finish(); - } - LogFileUtil.logAndWrite(Log.INFO, "MainActivity", "onCreate: Setting up work manager", null); - PeriodicWorkRequest workRequest = new PeriodicWorkRequest.Builder(CheckAccessibilityWorker.class, 15, TimeUnit.MINUTES) - .build(); - WorkManager.getInstance(this).enqueue(workRequest); - - LogFileUtil.logAndWrite(Log.INFO, "MainActivity", "onCreate: Setting up UI components", null); - Button runScriptButton = findViewById(R.id.run_script_button); - if (runScriptButton != null) { - runScriptButton.setOnClickListener(v -> { - initializeExecutorService(); - - executorService.submit(() -> { - try { - TaskUtil.infoUpload(MainActivity.this, getAndroidId(MainActivity.this), "wsj.reader_sp"); - } catch (Exception e) { - e.printStackTrace(); - } - }); - }); + executorService.submit(() -> { + try { + TaskUtil.infoUpload(MainActivity.this, getAndroidId(MainActivity.this), "wsj.reader_sp"); + } catch (Exception e) { + e.printStackTrace(); + } + }); + }); // runScriptButton.setOnClickListener(v -> AutoJsUtil.runAutojsScript(this)); - } else { - LogFileUtil.logAndWrite(Log.WARN, "MainActivity", "Run Script Button not found", null); - Toast.makeText(this, "Button not found", Toast.LENGTH_SHORT).show(); - } + } else { + LogFileUtil.logAndWrite(Log.WARN, "MainActivity", "Run Script Button not found", null); + Toast.makeText(this, "Button not found", Toast.LENGTH_SHORT).show(); + } - Button connectButton = findViewById(R.id.connectVpnButton); - if (connectButton != null) { - connectButton.setOnClickListener(v -> startProxyVpn(this)); - } else { - Toast.makeText(this, "Connect button not found", Toast.LENGTH_SHORT).show(); - } + Button connectButton = findViewById(R.id.connectVpnButton); + if (connectButton != null) { + connectButton.setOnClickListener(v -> startProxyVpn(this)); + } else { + Toast.makeText(this, "Connect button not found", Toast.LENGTH_SHORT).show(); + } - Button disconnectButton = findViewById(R.id.disconnectVpnButton); - if (disconnectButton != null) { - disconnectButton.setOnClickListener(v -> ClashUtil.stopProxy(this)); - } else { - Toast.makeText(this, "Disconnect button not found", Toast.LENGTH_SHORT).show(); - } + Button disconnectButton = findViewById(R.id.disconnectVpnButton); + if (disconnectButton != null) { + disconnectButton.setOnClickListener(v -> ClashUtil.stopProxy(this)); + } else { + Toast.makeText(this, "Disconnect button not found", Toast.LENGTH_SHORT).show(); + } - Button switchVpnButton = findViewById(R.id.switchVpnButton); - if (switchVpnButton != null) { - switchVpnButton.setOnClickListener(v -> ClashUtil.switchProxyGroup("GLOBAL", "us", "http://127.0.0.1:6170")); - } else { - Toast.makeText(this, "Disconnect button not found", Toast.LENGTH_SHORT).show(); - } + Button switchVpnButton = findViewById(R.id.switchVpnButton); + if (switchVpnButton != null) { + switchVpnButton.setOnClickListener(v -> ClashUtil.switchProxyGroup("GLOBAL", "us", "http://127.0.0.1:6170")); + } else { + Toast.makeText(this, "Disconnect button not found", Toast.LENGTH_SHORT).show(); + } // Button modifyDeviceInfoButton = findViewById(R.id.modifyDeviceInfoButton); // if (modifyDeviceInfoButton != null) { @@ -198,101 +199,101 @@ public class MainActivity extends AppCompatActivity { // Toast.makeText(this, "modifyDeviceInfo button not found", Toast.LENGTH_SHORT).show(); // } - Button resetDeviceInfoButton = findViewById(R.id.resetDeviceInfoButton); - if (resetDeviceInfoButton != null) { - resetDeviceInfoButton.setOnClickListener(v -> ChangeDeviceInfoUtil.resetChangedDeviceInfo(getPackageName(), this)); - } else { - Toast.makeText(this, "resetDeviceInfo button not found", Toast.LENGTH_SHORT).show(); - } + Button resetDeviceInfoButton = findViewById(R.id.resetDeviceInfoButton); + if (resetDeviceInfoButton != null) { + resetDeviceInfoButton.setOnClickListener(v -> ChangeDeviceInfoUtil.resetChangedDeviceInfo(getPackageName(), this)); + } else { + Toast.makeText(this, "resetDeviceInfo button not found", Toast.LENGTH_SHORT).show(); + } - // 初始化 ChangeDeviceInfoUtil - String androidId = getAndroidId(this); - String taskId = UUID.randomUUID().toString(); + // 初始化 ChangeDeviceInfoUtil + String androidId = getAndroidId(this); + String taskId = UUID.randomUUID().toString(); // ChangeDeviceInfoUtil.getAddDeviceInfo("US", 2); - // 获取输入框和按钮 - Button executeButton = findViewById(R.id.execute_button); - Button stopExecuteButton = findViewById(R.id.stop_execute_button); + // 获取输入框和按钮 + Button executeButton = findViewById(R.id.execute_button); + Button stopExecuteButton = findViewById(R.id.stop_execute_button); - // 设置按钮的点击事件 - if (executeButton != null) { - executeButton.setOnClickListener(v -> { - executeButton.setEnabled(false); - Toast.makeText(this, "任务正在执行", Toast.LENGTH_SHORT).show(); - executeLogic(androidId, taskId); - }); - } - if (stopExecuteButton != null) { - stopExecuteButton.setOnClickListener(v -> { - if (executorService != null && !executorService.isShutdown()) { - executorService.shutdownNow(); - ClashUtil.stopProxy(this); - AutoJsUtil.stopAutojsScript(this); - executeButton.setEnabled(true); - } - }); - } else { - Toast.makeText(this, "Stop button not found", Toast.LENGTH_SHORT).show(); + // 设置按钮的点击事件 + if (executeButton != null) { + executeButton.setOnClickListener(v -> { + executeButton.setEnabled(false); + Toast.makeText(this, "任务正在执行", Toast.LENGTH_SHORT).show(); + executeLogic(androidId, taskId); + }); + } + if (stopExecuteButton != null) { + stopExecuteButton.setOnClickListener(v -> { + if (executorService != null && !executorService.isShutdown()) { + executorService.shutdownNow(); + ClashUtil.stopProxy(this); + AutoJsUtil.stopAutojsScript(this); + executeButton.setEnabled(true); } + }); + } else { + Toast.makeText(this, "Stop button not found", Toast.LENGTH_SHORT).show(); + } + } + + private void executeLogic(String androidId, String taskId) { + LogFileUtil.logAndWrite(Log.INFO, "MainActivity", "executeLogic: Start execution", null); + + if (!isNetworkAvailable(this)) { + LogFileUtil.logAndWrite(Log.ERROR, "MainActivity", "executeLogic: Network is not available!", null); + Toast.makeText(this, "网络不可用,请检查网络连接", Toast.LENGTH_SHORT).show(); + return; } - private void executeLogic(String androidId, String taskId) { - LogFileUtil.logAndWrite(Log.INFO, "MainActivity", "executeLogic: Start execution", null); + LogFileUtil.logAndWrite(Log.INFO, "MainActivity", "executeLogic: Submitting job to executor", null); + initializeExecutorService(); - if (!isNetworkAvailable(this)) { - LogFileUtil.logAndWrite(Log.ERROR, "MainActivity", "executeLogic: Network is not available!", null); - Toast.makeText(this, "网络不可用,请检查网络连接", Toast.LENGTH_SHORT).show(); - return; - } - - LogFileUtil.logAndWrite(Log.INFO, "MainActivity", "executeLogic: Submitting job to executor", null); - initializeExecutorService(); - - executorService.submit(() -> { - try { - ChangeDeviceInfoUtil.getAddDeviceInfo("US", 2, (bigoDevice, afDevice) -> { - if (startProxyVpn(MainActivity.this)){ - ChangeDeviceInfoUtil.changeDeviceInfo(getPackageName(), MainActivity.this, bigoDevice, afDevice); - AutoJsUtil.runAutojsScript(this); - } - }); - AutoJsUtil.registerScriptResultReceiver(this); - - while (isRunning) { - if (!isRunning) break; - try { - LogFileUtil.logAndWrite(Log.INFO, "MainActivity", "executeSingleLogic: Running AutoJs script", null); - String currentScriptResult = scriptResultQueue.take(); - ChangeDeviceInfoUtil.getAddDeviceInfo("US", 2, (bigoDevice, afDevice) -> { - try { - if (startProxyVpn(MainActivity.this)){ - ChangeDeviceInfoUtil.changeDeviceInfo(getPackageName(), MainActivity.this, bigoDevice, afDevice); - AutoJsUtil.runAutojsScript(this); - if (currentScriptResult != null && !TextUtils.isEmpty(currentScriptResult)) { - TaskUtil.execSaveTask(this, androidId, taskId, currentScriptResult); - infoUpload(this, androidId, currentScriptResult); - } - } - } catch (Exception e) { - LogFileUtil.logAndWrite(Log.ERROR, "MainActivity", "changeDeviceInfo erro", e); - } - }); - LogFileUtil.logAndWrite(android.util.Log.DEBUG, "MainActivity", "----发送result------;" + currentScriptResult, null); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - LogFileUtil.logAndWrite(Log.ERROR, "MainActivity", "loop: Thread interrupted while waiting", e); - } catch(Exception e) { - LogFileUtil.logAndWrite(Log.ERROR, "MainActivity", "loop erro", e); - } - } - } catch (Exception e) { - LogFileUtil.logAndWrite(Log.ERROR, "MainActivity", "start executeLogic: Unexpected task error.", e); - } + executorService.submit(() -> { + try { + ChangeDeviceInfoUtil.getAddDeviceInfo("US", 2, (bigoDevice, afDevice) -> { + startProxyVpn(MainActivity.this); + ChangeDeviceInfoUtil.changeDeviceInfo(getPackageName(), MainActivity.this, bigoDevice, afDevice); + AutoJsUtil.runAutojsScript(this); }); - } + AutoJsUtil.registerScriptResultReceiver(this); - public static final LinkedBlockingQueue scriptResultQueue = new LinkedBlockingQueue<>(1); - private volatile boolean isRunning = true; // 主线程运行状态 - public static final Object taskLock = new Object(); // 任务逻辑锁 + while (isRunning) { + if (!isRunning) { + break; + } + try { + LogFileUtil.logAndWrite(Log.INFO, "MainActivity", "executeSingleLogic: Running AutoJs script", null); + String currentScriptResult = scriptResultQueue.take(); + ChangeDeviceInfoUtil.getAddDeviceInfo("US", 2, (bigoDevice, afDevice) -> { + try { + startProxyVpn(MainActivity.this); + ChangeDeviceInfoUtil.changeDeviceInfo(getPackageName(), MainActivity.this, bigoDevice, afDevice); + AutoJsUtil.runAutojsScript(this); + if (currentScriptResult != null && !TextUtils.isEmpty(currentScriptResult)) { + TaskUtil.execSaveTask(this, androidId, taskId, currentScriptResult, IpUtil.fetchGeoInfo()); + infoUpload(this, androidId, currentScriptResult); + } + } catch (Exception e) { + LogFileUtil.logAndWrite(Log.ERROR, "MainActivity", "changeDeviceInfo erro", e); + } + }); + LogFileUtil.logAndWrite(android.util.Log.DEBUG, "MainActivity", "----发送result------;" + currentScriptResult, null); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + LogFileUtil.logAndWrite(Log.ERROR, "MainActivity", "loop: Thread interrupted while waiting", e); + } catch (Exception e) { + LogFileUtil.logAndWrite(Log.ERROR, "MainActivity", "loop erro", e); + } + } + } catch (Exception e) { + LogFileUtil.logAndWrite(Log.ERROR, "MainActivity", "start executeLogic: Unexpected task error.", e); + } + }); + } + + public static final LinkedBlockingQueue scriptResultQueue = new LinkedBlockingQueue<>(1); + private volatile boolean isRunning = true; // 主线程运行状态 + public static final Object taskLock = new Object(); // 任务逻辑锁 // public void executeSingleLogic() { //// LogFileUtil.logAndWrite(Log.INFO, "MainActivity", "executeSingleLogic: Proxy not active, starting VPN",null); @@ -300,138 +301,133 @@ public class MainActivity extends AppCompatActivity { // LogFileUtil.logAndWrite(Log.INFO, "MainActivity", "executeSingleLogic: Changing device info",null); // ChangeDeviceInfoUtil.changeDeviceInfo(getPackageName(), this); - /// / LogFileUtil.logAndWrite(Log.INFO, "MainActivity", "executeSingleLogic: Running AutoJs script",null); - /// - /// @return + /// / LogFileUtil.logAndWrite(Log.INFO, "MainActivity", "executeSingleLogic: Running AutoJs script",null); + /// + /// @return // AutoJsUtil.runAutojsScript(this); // } - private boolean startProxyVpn(Context context) { - if (!isNetworkAvailable(context)) { - Toast.makeText(context, "Network is not available", Toast.LENGTH_SHORT).show(); - LogFileUtil.logAndWrite(Log.ERROR, "MainActivity", "startProxyVpn: Network is not available.", null); - return false; - } - - if (!(context instanceof Activity)) { - Toast.makeText(context, "Context must be an Activity", Toast.LENGTH_SHORT).show(); - LogFileUtil.logAndWrite(Log.ERROR, "MainActivity", "startProxyVpn: Context is not an Activity.", null); - return false; - } - - try { - ClashUtil.startProxy(context); // 在主线程中调用 - ClashUtil.switchProxyGroup("GLOBAL", "us", "http://127.0.0.1:6170"); - return ClashUtil.checkCountryIsUS(); - } catch (Exception e) { - LogFileUtil.logAndWrite(Log.ERROR, "MainActivity", "startProxyVpn: Failed to start VPN", e); - Toast.makeText(context, "Failed to start VPN: " + (e.getMessage() != null ? e.getMessage() : "Unknown error"), Toast.LENGTH_SHORT).show(); - } - return false; + private void startProxyVpn(Context context) { + if (!isNetworkAvailable(context)) { + Toast.makeText(context, "Network is not available", Toast.LENGTH_SHORT).show(); + LogFileUtil.logAndWrite(Log.ERROR, "MainActivity", "startProxyVpn: Network is not available.", null); } - @Override - public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { - super.onRequestPermissionsResult(requestCode, permissions, grantResults); - if (requestCode == REQUEST_CODE_STORAGE_PERMISSION) { - if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { - Toast.makeText(this, "Storage Permissions granted", Toast.LENGTH_SHORT).show(); - } else { - // 提示权限被拒绝,同时允许用户重新授予权限 - showPermissionExplanationDialog(); - } - } - if (requestCode == REQUEST_CODE_PERMISSIONS) { - boolean allGranted = true; - for (int result : grantResults) { - if (result != PackageManager.PERMISSION_GRANTED) { - allGranted = false; - break; - } - } - - if (allGranted) { - // 所有权限已授予 - startMyForegroundService(); - } else { - Toast.makeText(this, "未授予必要权限,请检查设置", Toast.LENGTH_SHORT).show(); - } - } + if (!(context instanceof Activity)) { + Toast.makeText(context, "Context must be an Activity", Toast.LENGTH_SHORT).show(); + LogFileUtil.logAndWrite(Log.ERROR, "MainActivity", "startProxyVpn: Context is not an Activity.", null); } - - private void startMyForegroundService() { - Intent serviceIntent = new Intent(this, MyAccessibilityService.class); - ContextCompat.startForegroundService(this, serviceIntent); + try { + ClashUtil.startProxy(context); // 在主线程中调用 + ClashUtil.switchProxyGroup("GLOBAL", "us", "http://127.0.0.1:6170"); + } catch (Exception e) { + LogFileUtil.logAndWrite(Log.ERROR, "MainActivity", "startProxyVpn: Failed to start VPN", e); + Toast.makeText(context, "Failed to start VPN: " + (e.getMessage() != null ? e.getMessage() : "Unknown error"), Toast.LENGTH_SHORT).show(); } + } - - @Override - protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { - super.onActivityResult(requestCode, resultCode, data); - - switch (requestCode) { - case ALLOW_ALL_FILES_ACCESS_PERMISSION_CODE: - handleStoragePermissionResult(resultCode); - break; - default: - break; + @Override + public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults); + if (requestCode == REQUEST_CODE_STORAGE_PERMISSION) { + if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { + Toast.makeText(this, "Storage Permissions granted", Toast.LENGTH_SHORT).show(); + } else { + // 提示权限被拒绝,同时允许用户重新授予权限 + showPermissionExplanationDialog(); + } + } + if (requestCode == REQUEST_CODE_PERMISSIONS) { + boolean allGranted = true; + for (int result : grantResults) { + if (result != PackageManager.PERMISSION_GRANTED) { + allGranted = false; + break; } - } + } - private void handleStoragePermissionResult(int resultCode) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R && Environment.isExternalStorageManager()) { - Toast.makeText(this, "Storage Permissions granted", Toast.LENGTH_SHORT).show(); - } else { - Toast.makeText(this, "请授予所有文件管理权限", Toast.LENGTH_SHORT).show(); - finish(); - } + if (allGranted) { + // 所有权限已授予 + startMyForegroundService(); + } else { + Toast.makeText(this, "未授予必要权限,请检查设置", Toast.LENGTH_SHORT).show(); + } } + } - private void showPermissionExplanationDialog() { - AlertDialog.Builder builder = new AlertDialog.Builder(this); - builder.setTitle("Permission Required") - .setMessage("Storage Permission is required for the app to function. Please enable it in Settings.") - .setPositiveButton("Go to Settings", (dialog, which) -> { - Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS); - Uri uri = Uri.fromParts("package", getPackageName(), null); - intent.setData(uri); - startActivity(intent); - }) - .setNegativeButton("Cancel", (dialog, which) -> finish()) - .show(); - } + private void startMyForegroundService() { + Intent serviceIntent = new Intent(this, MyAccessibilityService.class); + ContextCompat.startForegroundService(this, serviceIntent); + } - @Override - protected void onDestroy() { - LogFileUtil.logAndWrite(Log.INFO, "MainActivity", "onDestroy: Cleaning up resources", null); - super.onDestroy(); - instance.clear(); - if (AutoJsUtil.scriptResultReceiver != null) { - unregisterReceiver(AutoJsUtil.scriptResultReceiver); - AutoJsUtil.scriptResultReceiver = null; - } - if (executorService != null) { - executorService.shutdown(); - } - isRunning = false; - synchronized (taskLock) { - taskLock.notifyAll(); - } - } - public static MainActivity getInstance() { - return instance.get(); // 返回实例 - } + @Override + protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { + super.onActivityResult(requestCode, resultCode, data); - private boolean isNetworkAvailable(Context context) { - ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); - if (connectivityManager != null) { - Network network = connectivityManager.getActiveNetwork(); - if (network != null) { - NetworkCapabilities capabilities = connectivityManager.getNetworkCapabilities(network); - return capabilities != null && capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) - && capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED); - } - } - return false; + switch (requestCode) { + case ALLOW_ALL_FILES_ACCESS_PERMISSION_CODE: + handleStoragePermissionResult(resultCode); + break; + default: + break; } + } + + private void handleStoragePermissionResult(int resultCode) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R && Environment.isExternalStorageManager()) { + Toast.makeText(this, "Storage Permissions granted", Toast.LENGTH_SHORT).show(); + } else { + Toast.makeText(this, "请授予所有文件管理权限", Toast.LENGTH_SHORT).show(); + finish(); + } + } + + private void showPermissionExplanationDialog() { + AlertDialog.Builder builder = new AlertDialog.Builder(this); + builder.setTitle("Permission Required") + .setMessage("Storage Permission is required for the app to function. Please enable it in Settings.") + .setPositiveButton("Go to Settings", (dialog, which) -> { + Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS); + Uri uri = Uri.fromParts("package", getPackageName(), null); + intent.setData(uri); + startActivity(intent); + }) + .setNegativeButton("Cancel", (dialog, which) -> finish()) + .show(); + } + + @Override + protected void onDestroy() { + LogFileUtil.logAndWrite(Log.INFO, "MainActivity", "onDestroy: Cleaning up resources", null); + super.onDestroy(); + instance.clear(); + if (AutoJsUtil.scriptResultReceiver != null) { + unregisterReceiver(AutoJsUtil.scriptResultReceiver); + AutoJsUtil.scriptResultReceiver = null; + } + if (executorService != null) { + executorService.shutdown(); + } + isRunning = false; + synchronized (taskLock) { + taskLock.notifyAll(); + } + } + + public static MainActivity getInstance() { + return instance.get(); // 返回实例 + } + + private boolean isNetworkAvailable(Context context) { + ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); + if (connectivityManager != null) { + Network network = connectivityManager.getActiveNetwork(); + if (network != null) { + NetworkCapabilities capabilities = connectivityManager.getNetworkCapabilities(network); + return capabilities != null && capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) + && capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED); + } + } + return false; + } } diff --git a/app/src/main/java/com/example/studyapp/proxy/ClashUtil.java b/app/src/main/java/com/example/studyapp/proxy/ClashUtil.java index 1bdbba6..18cec66 100644 --- a/app/src/main/java/com/example/studyapp/proxy/ClashUtil.java +++ b/app/src/main/java/com/example/studyapp/proxy/ClashUtil.java @@ -133,53 +133,4 @@ public class ClashUtil { } } - public static boolean checkCountryIsUS() { - Request request = new Request.Builder() - .url("http://ipinfo.io/json") - .build(); - OkHttpClient client = new OkHttpClient(); - try (Response response = client.newCall(request).execute()) { // Synchronous call - if (!response.isSuccessful()) { - // Server returned an error - Log.e("ClashUtil", "OkHttp request unsuccessful: " + response.code()); - // Consider how to handle this error synchronously. - // Maybe throw an exception or return a specific error indicator. - return false; // Or throw new IOException("Request failed with code " + response.code()); - } - - try (ResponseBody responseBody = response.body()) { - if (responseBody == null) { - Log.e("ClashUtil", "Response body is null"); - return false; // Or throw new IOException("Response body is null"); - } - - String jsonData = responseBody.string(); - JSONObject jsonObject = new JSONObject(jsonData); - String country = jsonObject.optString("country"); - boolean isUS = "US".equalsIgnoreCase(country); - - if (isUS) { - Log.i("ClashUtil", "Country is US. Full data: " + jsonData); - } else { - Log.i("ClashUtil", "Country is NOT US. It is: " + (country.isEmpty() ? "未知" : country) + ". Full data: " + jsonData); - } - return isUS; - - } catch (JSONException e) { - Log.e("ClashUtil", "JSON parsing error: ", e); - // Consider re-throwing or returning an error indicator - return false; - } catch (IOException e) { - Log.e("ClashUtil", "IOException reading response body: ", e); - // Consider re-throwing or returning an error indicator - return false; - } - } catch (IOException e) { - // Network request failed - Log.e("ClashUtil", "OkHttp request failed: ", e); - // Consider re-throwing or returning an error indicator - return false; - } - } - } diff --git a/app/src/main/java/com/example/studyapp/task/TaskUtil.java b/app/src/main/java/com/example/studyapp/task/TaskUtil.java index bd3c927..36ab098 100644 --- a/app/src/main/java/com/example/studyapp/task/TaskUtil.java +++ b/app/src/main/java/com/example/studyapp/task/TaskUtil.java @@ -1,18 +1,12 @@ package com.example.studyapp.task; -import static androidx.core.content.PackageManagerCompat.LOG_TAG; - import android.content.Context; -import android.os.Environment; -import android.text.TextUtils; import android.util.Log; import com.example.studyapp.utils.FileUtils; import com.example.studyapp.utils.LogFileUtil; import com.example.studyapp.utils.ShellUtils; import com.example.studyapp.utils.ZipUtils; -import com.google.android.gms.common.util.CollectionUtils; -import com.google.android.gms.common.util.MapUtils; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.reflect.TypeToken; @@ -21,15 +15,10 @@ import java.io.FileInputStream; import java.io.InputStream; import java.io.OutputStream; import java.lang.reflect.Type; -import java.util.List; import java.util.Map; -import java.util.UUID; -import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.TimeUnit; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; -import okhttp3.Call; -import okhttp3.Callback; import okhttp3.HttpUrl; import okhttp3.MediaType; import okhttp3.MultipartBody; @@ -38,7 +27,6 @@ import okhttp3.Request; import okhttp3.RequestBody; import okhttp3.Response; import okhttp3.ResponseBody; -import org.jetbrains.annotations.NotNull; import java.io.File; import java.io.FileOutputStream; @@ -65,7 +53,7 @@ public class TaskUtil { .readTimeout(30, TimeUnit.SECONDS) // 读取超时 .build(); - public static void postDeviceInfo(String androidId, String taskId,String packageName) { + public static void postDeviceInfo(String androidId, String taskId,String packageName, String ipInfo) { Log.i("TaskUtil", "postDeviceInfo called with androidId: " + androidId); if (okHttpClient == null) { @@ -99,6 +87,7 @@ public class TaskUtil { .addQueryParameter("id", androidId) .addQueryParameter("taskId", taskId) .addQueryParameter("packageName", packageName) + .addQueryParameter("deviceIp",ipInfo) .build(); Log.d("TaskUtil", "Request URL: " + url.toString()); @@ -783,7 +772,7 @@ public class TaskUtil { return getDeviceInfoSync(androidId,taskId); } - public static void execSaveTask(Context context, String androidId, String taskId,String packName) { + public static void execSaveTask(Context context, String androidId, String taskId,String packName, String ipInfo) { if (context == null) { throw new IllegalArgumentException("Context or Package name cannot be null or empty"); } @@ -794,7 +783,7 @@ public class TaskUtil { } try { - postDeviceInfo(androidId, taskId,packName); + postDeviceInfo(androidId, taskId,packName,ipInfo); } catch (Exception e) { System.err.println("Error in execReloginTask: " + e.getMessage()); e.printStackTrace(); diff --git a/app/src/main/java/com/example/studyapp/utils/IpUtil.java b/app/src/main/java/com/example/studyapp/utils/IpUtil.java index 6b6b639..28c70e6 100644 --- a/app/src/main/java/com/example/studyapp/utils/IpUtil.java +++ b/app/src/main/java/com/example/studyapp/utils/IpUtil.java @@ -2,8 +2,14 @@ package com.example.studyapp.utils; import android.text.TextUtils; +import android.util.Log; +import java.io.IOException; import java.net.InetAddress; import java.net.UnknownHostException; +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.Response; +import okhttp3.ResponseBody; import org.json.JSONObject; import java.util.concurrent.CompletableFuture; @@ -46,6 +52,35 @@ public class IpUtil { } } + public static String fetchGeoInfo() { + Request request = new Request.Builder() + .url("https://ipv4.geojs.io/v1/ip/geo.json") + .build(); + + OkHttpClient client = new OkHttpClient(); + + try (Response response = client.newCall(request).execute()) { + if (!response.isSuccessful()) { + Log.e("ClashUtil", "OkHttp request unsuccessful: " + response.code()); + return null; + } + + ResponseBody responseBody = response.body(); + if (responseBody == null) { + Log.e("ClashUtil", "Response body is null"); + return null; + } + + String jsonData = responseBody.string(); + Log.i("ClashUtil", "Geo info: " + jsonData); + return jsonData; + + } catch (IOException e) { + Log.e("ClashUtil", "OkHttp request failed: ", e); + return null; + } + } + public static String checkClientIp(String excludeCountry) { try { diff --git a/app/src/test/java/com/example/studyapp/task/TaskUtilTest.java b/app/src/test/java/com/example/studyapp/task/TaskUtilTest.java index 617ab0b..62ec62f 100644 --- a/app/src/test/java/com/example/studyapp/task/TaskUtilTest.java +++ b/app/src/test/java/com/example/studyapp/task/TaskUtilTest.java @@ -131,14 +131,14 @@ public class TaskUtilTest { // 运行上传方法 String taskId = "asddasdasd"; - TaskUtil.postDeviceInfo("b3d893cf9de3a85a", taskId, "com.example.studyapp"); + //TaskUtil.postDeviceInfo("b3d893cf9de3a85a", taskId, "com.example.studyapp", ipInfo); } @Test public void testGetDeviceInfoSync_Success() throws Exception { // 运行上传方法 - TaskUtil.getDeviceInfoSync("b3d893cf9de3a85a"); + //TaskUtil.getDeviceInfoSync("b3d893cf9de3a85a"); } // @Test