diff --git a/app/build.gradle b/app/build.gradle index 06fd15f..2810eec 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -7,7 +7,7 @@ android { compileSdk 35 defaultConfig { - applicationId "com.example.studyapp" + applicationId "com.example.retention" minSdk 24 targetSdk 35 versionCode 1 diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index c371e32..1913d8f 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -39,7 +39,7 @@ android:usesCleartextTraffic="true" android:fullBackupContent="@xml/backup_rules" android:icon="@mipmap/box" - android:label="Script helper" + android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/Theme.StudyApp" diff --git a/app/src/main/java/com/example/studyapp/MainActivity.java b/app/src/main/java/com/example/studyapp/MainActivity.java index 67e653c..32d6a95 100644 --- a/app/src/main/java/com/example/studyapp/MainActivity.java +++ b/app/src/main/java/com/example/studyapp/MainActivity.java @@ -1,6 +1,7 @@ package com.example.studyapp; import static com.example.studyapp.task.TaskUtil.infoUpload; +import static com.example.studyapp.utils.Utils.isNetworkAvailable; import android.app.Activity; import android.app.AlertDialog; @@ -36,7 +37,9 @@ import com.example.studyapp.service.MyAccessibilityService; import com.example.studyapp.task.TaskUtil; import com.example.studyapp.utils.LogFileUtil; import com.example.studyapp.utils.ShellUtils; +import com.example.studyapp.utils.Utils; import com.example.studyapp.worker.CheckAccessibilityWorker; +import com.example.studyapp.worker.LoadDeviceWorker; import java.io.File; import java.lang.ref.WeakReference; @@ -95,19 +98,20 @@ public class MainActivity extends AppCompatActivity { * @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"); - } - try { - return Settings.Secure.getString( - context.getContentResolver(), - Settings.Secure.ANDROID_ID - ); - } catch (Exception e) { - LogFileUtil.logAndWrite(Log.ERROR, "MainActivity", "getAndroidId: Failed to get ANDROID_ID",e); - return null; - } +// if (context == null) { +// LogFileUtil.logAndWrite(Log.ERROR, "MainActivity", "getAndroidId: Context cannot be null",null); +// throw new IllegalArgumentException("Context cannot be null"); +// } +// try { +// return Settings.Secure.getString( +// context.getContentResolver(), +// Settings.Secure.ANDROID_ID +// ); +// } catch (Exception e) { +// LogFileUtil.logAndWrite(Log.ERROR, "MainActivity", "getAndroidId: Failed to get ANDROID_ID",e); +// return null; +// } + return "FyZqWrStUvOpKlMn"; } @@ -153,7 +157,10 @@ public class MainActivity extends AppCompatActivity { 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 -> AutoJsUtil.runAutojsScript(this)); +// runScriptButton.setOnClickListener(v -> AutoJsUtil.runAutojsScript(this)); + runScriptButton.setOnClickListener(v -> { + Utils.writePackageName("com.test.app"); + }); } else { LogFileUtil.logAndWrite(Log.WARN, "MainActivity", "Run Script Button not found",null); Toast.makeText(this, "Button not found", Toast.LENGTH_SHORT).show(); @@ -210,7 +217,8 @@ public class MainActivity extends AppCompatActivity { executeButton.setOnClickListener(v -> { executeButton.setEnabled(false); Toast.makeText(this, "任务正在执行", Toast.LENGTH_SHORT).show(); - executeLogic(androidId,taskId); +// executeLogic(androidId,taskId); + startLoadWork(); }); } if (stopExecuteButton != null) { @@ -227,6 +235,12 @@ public class MainActivity extends AppCompatActivity { } } + private void startLoadWork(){ + PeriodicWorkRequest workRequest = new PeriodicWorkRequest.Builder(LoadDeviceWorker.class, 15, TimeUnit.MINUTES) + .setInitialDelay(0, TimeUnit.SECONDS).build(); + WorkManager.getInstance(this).enqueue(workRequest); + } + private void executeLogic(String androidId, String taskId) { LogFileUtil.logAndWrite(Log.INFO, "MainActivity", "executeLogic: Start execution",null); @@ -393,17 +407,4 @@ public class MainActivity extends AppCompatActivity { 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/device/ChangeDeviceInfoUtil.java b/app/src/main/java/com/example/studyapp/device/ChangeDeviceInfoUtil.java index d3a6866..fc71374 100644 --- a/app/src/main/java/com/example/studyapp/device/ChangeDeviceInfoUtil.java +++ b/app/src/main/java/com/example/studyapp/device/ChangeDeviceInfoUtil.java @@ -34,6 +34,9 @@ public class ChangeDeviceInfoUtil { private static JSONObject afDeviceObject; + public static String packageName = ""; + public static String zipName = ""; + public static String buildBigoUrl(String country, int tag) { return Uri.parse("http://8.217.137.25/tt/zj/dispatcher!bigo.do") .buildUpon() @@ -75,6 +78,34 @@ public class ChangeDeviceInfoUtil { }); } + public static boolean getDeviceInfoSync(String taskId, String androidId){ + String response = ""; + try{ + response = executeQuerySafely(androidId, taskId); + } catch (Exception e) { + e.printStackTrace(); + } + if (response == null || response.isBlank()) { + LogFileUtil.logAndWrite(android.util.Log.ERROR, LOG_TAG, "Error occurred during query", null); + return false; + } + + if (isValidResponse(response)) { + try { + synchronized (ChangeDeviceInfoUtil.class) { // 防止并发访问 + parseAndSetDeviceObjects(response); + } + return true; + } catch (JSONException e) { + LogFileUtil.logAndWrite(android.util.Log.ERROR, LOG_TAG, "Error parsing JSON", e); + return false; + } + } else { + LogFileUtil.logAndWrite(android.util.Log.ERROR, LOG_TAG, "Error occurred during query",null); + return false; + } + } + public static void getDeviceInfo(String taskId, String androidId) { if (taskId == null || androidId == null || taskId.isBlank() || androidId.isBlank()) { LogFileUtil.logAndWrite(android.util.Log.ERROR, LOG_TAG, "Invalid task",null); @@ -146,6 +177,8 @@ public class ChangeDeviceInfoUtil { JSONObject responseJson = new JSONObject(cleanJson); bigoDeviceObject = responseJson.optJSONObject("bigoDeviceObject"); afDeviceObject = responseJson.optJSONObject("afDeviceObject"); + packageName = responseJson.optString("package_name"); + zipName = responseJson.optString("file_name"); } private static void fallBackToNetworkData(String bigoJson, String afJson) throws JSONException { @@ -171,6 +204,15 @@ public class ChangeDeviceInfoUtil { } } + public static void processPackageInfoWithDeviceInfo(String packageName,String zipName, Context context, String androidId, String taskId) { + if (!isAppInstalled(packageName)) { + processPackage(packageName, zipName, context); + TaskUtil.postDeviceInfo(androidId, taskId, packageName); + } else { + LogFileUtil.logAndWrite(android.util.Log.WARN, LOG_TAG, "Package not installed: " + packageName, null); + } + } + private static void processPackage(String packageName, String zipName, Context context) { try { File filesDir = new File(context.getExternalFilesDir(null).getAbsolutePath()); diff --git a/app/src/main/java/com/example/studyapp/utils/Utils.java b/app/src/main/java/com/example/studyapp/utils/Utils.java new file mode 100644 index 0000000..1c76ad5 --- /dev/null +++ b/app/src/main/java/com/example/studyapp/utils/Utils.java @@ -0,0 +1,52 @@ +package com.example.studyapp.utils; + +import android.content.Context; +import android.net.ConnectivityManager; +import android.net.Network; +import android.net.NetworkCapabilities; +import android.os.Environment; +import android.util.Log; + +import java.io.BufferedOutputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.nio.charset.StandardCharsets; + +public class Utils { + + public static 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; + } + + public static void writePackageName(String packageName){ + File file = new File(Environment.getExternalStorageDirectory(), + "script/packagesname.txt"); + File parentDir = file.getParentFile(); + if (parentDir != null && !parentDir.exists()) { + boolean dirsCreated = parentDir.mkdirs(); + if (!dirsCreated) { + Log.e("FileWrite", "Failed to create directories: " + parentDir); + return; + } + } + Log.d("TAG", "writePackageName: "+packageName); + try (BufferedOutputStream bos = new BufferedOutputStream( + new FileOutputStream(file))) { + bos.write(packageName.getBytes(StandardCharsets.UTF_8)); + bos.flush(); // 确保数据写入磁盘 + } catch (IOException e) { + Log.e("FileWrite", "Failed to write package name: " + packageName, e); + // 6. 可以考虑添加重试机制或通知用户 + } + } +} diff --git a/app/src/main/java/com/example/studyapp/worker/LoadDeviceWorker.java b/app/src/main/java/com/example/studyapp/worker/LoadDeviceWorker.java new file mode 100644 index 0000000..7fa3403 --- /dev/null +++ b/app/src/main/java/com/example/studyapp/worker/LoadDeviceWorker.java @@ -0,0 +1,89 @@ +package com.example.studyapp.worker; + +import static com.example.studyapp.utils.Utils.isNetworkAvailable; + +import android.app.Activity; +import android.content.Context; +import android.os.Environment; +import android.os.Handler; +import android.os.Looper; +import android.text.TextUtils; +import android.util.Log; +import android.widget.Toast; + +import androidx.annotation.NonNull; +import androidx.work.CoroutineWorker; +import androidx.work.WorkerParameters; + +import com.example.studyapp.autoJS.AutoJsUtil; +import com.example.studyapp.device.ChangeDeviceInfoUtil; +import com.example.studyapp.proxy.ClashUtil; +import com.example.studyapp.task.TaskUtil; +import com.example.studyapp.utils.LogFileUtil; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.io.BufferedOutputStream; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.util.Map; +import java.util.UUID; + +import kotlin.coroutines.Continuation; + +public class LoadDeviceWorker extends CoroutineWorker { + private String androidId = "FyZqWrStUvOpKlMn"; + public LoadDeviceWorker(@NonNull Context context, @NonNull WorkerParameters workerParams) { + super(context, workerParams); + } + + @Override + public @Nullable Object doWork(@NotNull Continuation continuation) { + String taskId = UUID.randomUUID().toString(); + boolean result = ChangeDeviceInfoUtil.getDeviceInfoSync(taskId, androidId); + String packageName = ChangeDeviceInfoUtil.packageName; + String zipName = ChangeDeviceInfoUtil.zipName; + if (result && !TextUtils.isEmpty(packageName) && !TextUtils.isEmpty(zipName)){ + ChangeDeviceInfoUtil.processPackageInfoWithDeviceInfo(packageName,zipName, getApplicationContext(), androidId, taskId); + executeSingleLogic(getApplicationContext()); + } + return Result.success(); + } + + public void executeSingleLogic(Context context) { + LogFileUtil.logAndWrite(Log.INFO, "MainActivity", "executeSingleLogic: Proxy not active, starting VPN",null); + new Handler(Looper.getMainLooper()).post(() -> { + startProxyVpn(context); + }); + LogFileUtil.logAndWrite(Log.INFO, "MainActivity", "executeSingleLogic: Changing device info",null); + ChangeDeviceInfoUtil.changeDeviceInfo(context.getPackageName(), context); + LogFileUtil.logAndWrite(Log.INFO, "MainActivity", "executeSingleLogic: Running AutoJs script",null); + AutoJsUtil.runAutojsScript(context); + } + + 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); + return; + } + + 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; + } + + 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(); + } + } +} diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index ec172df..640061f 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1,4 +1,4 @@ - study_app + Retention This is an accessibility service. 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..9422a5e 100644 --- a/app/src/test/java/com/example/studyapp/task/TaskUtilTest.java +++ b/app/src/test/java/com/example/studyapp/task/TaskUtilTest.java @@ -138,7 +138,7 @@ public class TaskUtilTest { public void testGetDeviceInfoSync_Success() throws Exception { // 运行上传方法 - TaskUtil.getDeviceInfoSync("b3d893cf9de3a85a"); +// TaskUtil.getDeviceInfoSync("b3d893cf9de3a85a"); } // @Test