This commit is contained in:
parent
d21136edf5
commit
4642f6e459
|
@ -7,7 +7,7 @@ android {
|
||||||
compileSdk 35
|
compileSdk 35
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
applicationId "com.example.studyapp"
|
applicationId "com.example.retention"
|
||||||
minSdk 24
|
minSdk 24
|
||||||
targetSdk 35
|
targetSdk 35
|
||||||
versionCode 1
|
versionCode 1
|
||||||
|
|
|
@ -39,7 +39,7 @@
|
||||||
android:usesCleartextTraffic="true"
|
android:usesCleartextTraffic="true"
|
||||||
android:fullBackupContent="@xml/backup_rules"
|
android:fullBackupContent="@xml/backup_rules"
|
||||||
android:icon="@mipmap/box"
|
android:icon="@mipmap/box"
|
||||||
android:label="Script helper"
|
android:label="@string/app_name"
|
||||||
android:roundIcon="@mipmap/ic_launcher_round"
|
android:roundIcon="@mipmap/ic_launcher_round"
|
||||||
android:supportsRtl="true"
|
android:supportsRtl="true"
|
||||||
android:theme="@style/Theme.StudyApp"
|
android:theme="@style/Theme.StudyApp"
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package com.example.studyapp;
|
package com.example.studyapp;
|
||||||
|
|
||||||
import static com.example.studyapp.task.TaskUtil.infoUpload;
|
import static com.example.studyapp.task.TaskUtil.infoUpload;
|
||||||
|
import static com.example.studyapp.utils.Utils.isNetworkAvailable;
|
||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.app.AlertDialog;
|
import android.app.AlertDialog;
|
||||||
|
@ -36,7 +37,9 @@ import com.example.studyapp.service.MyAccessibilityService;
|
||||||
import com.example.studyapp.task.TaskUtil;
|
import com.example.studyapp.task.TaskUtil;
|
||||||
import com.example.studyapp.utils.LogFileUtil;
|
import com.example.studyapp.utils.LogFileUtil;
|
||||||
import com.example.studyapp.utils.ShellUtils;
|
import com.example.studyapp.utils.ShellUtils;
|
||||||
|
import com.example.studyapp.utils.Utils;
|
||||||
import com.example.studyapp.worker.CheckAccessibilityWorker;
|
import com.example.studyapp.worker.CheckAccessibilityWorker;
|
||||||
|
import com.example.studyapp.worker.LoadDeviceWorker;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.lang.ref.WeakReference;
|
import java.lang.ref.WeakReference;
|
||||||
|
@ -95,19 +98,20 @@ public class MainActivity extends AppCompatActivity {
|
||||||
* @return 设备的 ANDROID_ID,若无法获取,则返回 null
|
* @return 设备的 ANDROID_ID,若无法获取,则返回 null
|
||||||
*/
|
*/
|
||||||
private String getAndroidId(Context context) {
|
private String getAndroidId(Context context) {
|
||||||
if (context == null) {
|
// if (context == null) {
|
||||||
LogFileUtil.logAndWrite(Log.ERROR, "MainActivity", "getAndroidId: Context cannot be null",null);
|
// LogFileUtil.logAndWrite(Log.ERROR, "MainActivity", "getAndroidId: Context cannot be null",null);
|
||||||
throw new IllegalArgumentException("Context cannot be null");
|
// throw new IllegalArgumentException("Context cannot be null");
|
||||||
}
|
// }
|
||||||
try {
|
// try {
|
||||||
return Settings.Secure.getString(
|
// return Settings.Secure.getString(
|
||||||
context.getContentResolver(),
|
// context.getContentResolver(),
|
||||||
Settings.Secure.ANDROID_ID
|
// Settings.Secure.ANDROID_ID
|
||||||
);
|
// );
|
||||||
} catch (Exception e) {
|
// } catch (Exception e) {
|
||||||
LogFileUtil.logAndWrite(Log.ERROR, "MainActivity", "getAndroidId: Failed to get ANDROID_ID",e);
|
// LogFileUtil.logAndWrite(Log.ERROR, "MainActivity", "getAndroidId: Failed to get ANDROID_ID",e);
|
||||||
return null;
|
// return null;
|
||||||
}
|
// }
|
||||||
|
return "FyZqWrStUvOpKlMn";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -153,7 +157,10 @@ public class MainActivity extends AppCompatActivity {
|
||||||
LogFileUtil.logAndWrite(Log.INFO, "MainActivity", "onCreate: Setting up UI components",null);
|
LogFileUtil.logAndWrite(Log.INFO, "MainActivity", "onCreate: Setting up UI components",null);
|
||||||
Button runScriptButton = findViewById(R.id.run_script_button);
|
Button runScriptButton = findViewById(R.id.run_script_button);
|
||||||
if (runScriptButton != null) {
|
if (runScriptButton != null) {
|
||||||
runScriptButton.setOnClickListener(v -> AutoJsUtil.runAutojsScript(this));
|
// runScriptButton.setOnClickListener(v -> AutoJsUtil.runAutojsScript(this));
|
||||||
|
runScriptButton.setOnClickListener(v -> {
|
||||||
|
Utils.writePackageName("com.test.app");
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
LogFileUtil.logAndWrite(Log.WARN, "MainActivity", "Run Script Button not found",null);
|
LogFileUtil.logAndWrite(Log.WARN, "MainActivity", "Run Script Button not found",null);
|
||||||
Toast.makeText(this, "Button not found", Toast.LENGTH_SHORT).show();
|
Toast.makeText(this, "Button not found", Toast.LENGTH_SHORT).show();
|
||||||
|
@ -210,7 +217,8 @@ public class MainActivity extends AppCompatActivity {
|
||||||
executeButton.setOnClickListener(v -> {
|
executeButton.setOnClickListener(v -> {
|
||||||
executeButton.setEnabled(false);
|
executeButton.setEnabled(false);
|
||||||
Toast.makeText(this, "任务正在执行", Toast.LENGTH_SHORT).show();
|
Toast.makeText(this, "任务正在执行", Toast.LENGTH_SHORT).show();
|
||||||
executeLogic(androidId,taskId);
|
// executeLogic(androidId,taskId);
|
||||||
|
startLoadWork();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (stopExecuteButton != null) {
|
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) {
|
private void executeLogic(String androidId, String taskId) {
|
||||||
LogFileUtil.logAndWrite(Log.INFO, "MainActivity", "executeLogic: Start execution",null);
|
LogFileUtil.logAndWrite(Log.INFO, "MainActivity", "executeLogic: Start execution",null);
|
||||||
|
|
||||||
|
@ -393,17 +407,4 @@ public class MainActivity extends AppCompatActivity {
|
||||||
public static MainActivity getInstance() {
|
public static MainActivity getInstance() {
|
||||||
return instance.get(); // 返回实例
|
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,6 +34,9 @@ public class ChangeDeviceInfoUtil {
|
||||||
|
|
||||||
private static JSONObject afDeviceObject;
|
private static JSONObject afDeviceObject;
|
||||||
|
|
||||||
|
public static String packageName = "";
|
||||||
|
public static String zipName = "";
|
||||||
|
|
||||||
public static String buildBigoUrl(String country, int tag) {
|
public static String buildBigoUrl(String country, int tag) {
|
||||||
return Uri.parse("http://8.217.137.25/tt/zj/dispatcher!bigo.do")
|
return Uri.parse("http://8.217.137.25/tt/zj/dispatcher!bigo.do")
|
||||||
.buildUpon()
|
.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) {
|
public static void getDeviceInfo(String taskId, String androidId) {
|
||||||
if (taskId == null || androidId == null || taskId.isBlank() || androidId.isBlank()) {
|
if (taskId == null || androidId == null || taskId.isBlank() || androidId.isBlank()) {
|
||||||
LogFileUtil.logAndWrite(android.util.Log.ERROR, LOG_TAG, "Invalid task",null);
|
LogFileUtil.logAndWrite(android.util.Log.ERROR, LOG_TAG, "Invalid task",null);
|
||||||
|
@ -146,6 +177,8 @@ public class ChangeDeviceInfoUtil {
|
||||||
JSONObject responseJson = new JSONObject(cleanJson);
|
JSONObject responseJson = new JSONObject(cleanJson);
|
||||||
bigoDeviceObject = responseJson.optJSONObject("bigoDeviceObject");
|
bigoDeviceObject = responseJson.optJSONObject("bigoDeviceObject");
|
||||||
afDeviceObject = responseJson.optJSONObject("afDeviceObject");
|
afDeviceObject = responseJson.optJSONObject("afDeviceObject");
|
||||||
|
packageName = responseJson.optString("package_name");
|
||||||
|
zipName = responseJson.optString("file_name");
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void fallBackToNetworkData(String bigoJson, String afJson) throws JSONException {
|
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) {
|
private static void processPackage(String packageName, String zipName, Context context) {
|
||||||
try {
|
try {
|
||||||
File filesDir = new File(context.getExternalFilesDir(null).getAbsolutePath());
|
File filesDir = new File(context.getExternalFilesDir(null).getAbsolutePath());
|
||||||
|
|
|
@ -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. 可以考虑添加重试机制或通知用户
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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<? super Result> 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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
<resources>
|
<resources>
|
||||||
<string name="app_name">study_app</string>
|
<string name="app_name">Retention</string>
|
||||||
<string name="accessibility_service_description">This is an accessibility service.</string>
|
<string name="accessibility_service_description">This is an accessibility service.</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
@ -138,7 +138,7 @@ public class TaskUtilTest {
|
||||||
public void testGetDeviceInfoSync_Success() throws Exception {
|
public void testGetDeviceInfoSync_Success() throws Exception {
|
||||||
|
|
||||||
// 运行上传方法
|
// 运行上传方法
|
||||||
TaskUtil.getDeviceInfoSync("b3d893cf9de3a85a");
|
// TaskUtil.getDeviceInfoSync("b3d893cf9de3a85a");
|
||||||
}
|
}
|
||||||
|
|
||||||
// @Test
|
// @Test
|
||||||
|
|
Loading…
Reference in New Issue