This commit is contained in:
parent
d21136edf5
commit
4642f6e459
|
@ -7,7 +7,7 @@ android {
|
|||
compileSdk 35
|
||||
|
||||
defaultConfig {
|
||||
applicationId "com.example.studyapp"
|
||||
applicationId "com.example.retention"
|
||||
minSdk 24
|
||||
targetSdk 35
|
||||
versionCode 1
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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>
|
||||
<string name="app_name">study_app</string>
|
||||
<string name="app_name">Retention</string>
|
||||
<string name="accessibility_service_description">This is an accessibility service.</string>
|
||||
</resources>
|
||||
|
|
|
@ -138,7 +138,7 @@ public class TaskUtilTest {
|
|||
public void testGetDeviceInfoSync_Success() throws Exception {
|
||||
|
||||
// 运行上传方法
|
||||
TaskUtil.getDeviceInfoSync("b3d893cf9de3a85a");
|
||||
// TaskUtil.getDeviceInfoSync("b3d893cf9de3a85a");
|
||||
}
|
||||
|
||||
// @Test
|
||||
|
|
Loading…
Reference in New Issue