package com.example.retention.task; import android.content.Context; import android.util.Log; import com.example.retention.utils.LogFileUtil; import com.example.retention.utils.ShellUtils; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.reflect.TypeToken; import java.io.BufferedOutputStream; import java.io.FileInputStream; import java.io.InputStream; import java.io.OutputStream; import java.lang.reflect.Type; import java.util.Map; import java.util.concurrent.TimeUnit; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; import okhttp3.HttpUrl; import okhttp3.MediaType; import okhttp3.MultipartBody; import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.RequestBody; import okhttp3.Response; import okhttp3.ResponseBody; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; /** * @Time: 2025/6/16 11:11 * @Creator: 初屿贤 * @File: TaskUtil * @Project: study.App * @Description: */ public class TaskUtil { private static volatile DeviceInfo deviceInfo; private static volatile BigoInfo bigoDevice; private static volatile AfInfo afDevice; private static final String BASE_URL = "http://47.238.96.231:8112"; private static OkHttpClient okHttpClient = new OkHttpClient.Builder() .connectTimeout(30, TimeUnit.SECONDS) // 连接超时 .writeTimeout(60, TimeUnit.SECONDS) // 写入超时 (对上传很重要) .readTimeout(30, TimeUnit.SECONDS) // 读取超时 .build(); public static void postDeviceInfo(String androidId, String taskId,String packageName) { Log.i("TaskUtil", "postDeviceInfo called with androidId: " + androidId); if (okHttpClient == null) { LogFileUtil.logAndWrite(android.util.Log.ERROR, "TaskUtil", "HttpClient is not initialized", null); throw new IllegalStateException("HttpClient is not initialized"); } if (BASE_URL == null || BASE_URL.isEmpty()) { LogFileUtil.logAndWrite(android.util.Log.ERROR, "TaskUtil", "BASE_URL is not initialized", null); throw new IllegalStateException("BASE_URL is not initialized"); } Log.d("TaskUtil", "Creating payload for the request..."); Payload payload = new Payload(); payload.bigoDeviceObject = bigoDevice; payload.afDeviceObject = afDevice; payload.other = deviceInfo; Gson gson = new GsonBuilder().serializeNulls().create(); String jsonRequestBody = gson.toJson(payload); Log.d("TaskUtil", "Request payload: " + jsonRequestBody); if (packageName == null){ packageName = ""; } HttpUrl url = HttpUrl.parse(BASE_URL) .newBuilder() .addPathSegment("device_info_upload") .addQueryParameter("id", androidId) .addQueryParameter("taskId", taskId) .addQueryParameter("packageName", packageName) .build(); Log.d("TaskUtil", "Request URL: " + url.toString()); RequestBody body = RequestBody.create(MediaType.get("application/json; charset=utf-8"), jsonRequestBody); Log.d("TaskUtil", "Request body created"); Request request = new Request.Builder() .url(url) .post(body) .build(); Log.i("TaskUtil", "Starting network call..."); try { Response response = okHttpClient.newCall(request).execute(); try (ResponseBody responseBody = response.body()) { if (!response.isSuccessful()) { LogFileUtil.logAndWrite(android.util.Log.ERROR, "TaskUtil", "Request failed with status: " + response.code(), null); return; } if (responseBody != null) { String responseText = responseBody.string(); Log.i("TaskUtil", "Request succeeded. Response: " + responseText); } else { LogFileUtil.logAndWrite(android.util.Log.ERROR, "TaskUtil", "Response body is null", null); } } catch (IOException e) { LogFileUtil.logAndWrite(android.util.Log.ERROR, "TaskUtil", "Error while processing response: " + e.getMessage(), e); } } catch (IOException e) { LogFileUtil.logAndWrite(android.util.Log.ERROR, "TaskUtil", "Error during HTTP request: " + e.getMessage(), e); } } public static String getDeviceInfoSync(String androidId,String taskId) { Log.d("TaskUtil", "getDeviceInfoSync called with androidId: " + androidId); validate(); // 检查 BASE_URL 和 okHttpClient 的合法性 HttpUrl url = HttpUrl.parse(BASE_URL + "/device_info_download") .newBuilder() .addQueryParameter("androidId", androidId) .addQueryParameter("taskId",taskId) .build(); Log.d("TaskUtil", "Constructed URL for device info download: " + url.toString()); Request request = new Request.Builder() .url(url) .get() .build(); Log.d("TaskUtil", "Built HTTP request for device info download"); try (Response response = okHttpClient.newCall(request).execute()) { // 检查响应是否成功 if (!response.isSuccessful()) { String errorMessage = "Unexpected response: Code=" + response.code() + ", Message=" + response.message() + ", URL=" + url.toString(); LogFileUtil.logAndWrite(android.util.Log.ERROR, "TaskUtil", errorMessage, null); throw new IOException(errorMessage); } ResponseBody responseBody = response.body(); if (responseBody != null) { String responseString = responseBody.string(); Log.i("TaskUtil", "Received response: " + responseString); return responseString; } else { String errorMessage = "Response body is null: URL=" + url.toString(); LogFileUtil.logAndWrite(android.util.Log.ERROR, "TaskUtil", errorMessage, null); throw new IOException(errorMessage); } } catch (IOException e) { String errorMessage = "Error during HTTP request. URL=" + url.toString() + ", Android ID=" + androidId; LogFileUtil.logAndWrite(android.util.Log.ERROR, "TaskUtil", errorMessage, e); return null; // 或考虑在上层抛出异常 } } public static String getApkPath(Context context, String packageName) { if (packageName == null || packageName.trim().isEmpty()) { throw new IllegalArgumentException("Package name must not be null or empty"); } String result = ShellUtils.getPackagePath(context, packageName); Log.d("TAG", "getApkPath: "+result); return result; } public static void infoUpload(Context context, String androidId, String packAge) throws IOException { Log.i("TaskUtil", "infoUpload called with androidId: " + androidId + ", package: " + packAge); if (packAge == null || packAge.isEmpty()) { LogFileUtil.logAndWrite(android.util.Log.ERROR, "TaskUtil", "Package name is null or empty", null); throw new IllegalArgumentException("Package name cannot be null or empty"); } if (context == null) { LogFileUtil.logAndWrite(android.util.Log.ERROR, "TaskUtil", "Context is null", null); throw new IllegalArgumentException("Context cannot be null"); } if (androidId == null || androidId.isEmpty()) { Log.w("TaskUtil", "ANDROID_ID is null or empty"); return; } String apkSourceFile = getApkPath(context, packAge); Log.d("TaskUtil", "APK source directory: " + apkSourceFile); // File externalDir = context.getExternalFilesDir(null); File externalDir = context.getCacheDir(); if (externalDir == null) { LogFileUtil.logAndWrite(android.util.Log.ERROR, "TaskUtil", "External storage directory is unavailable", null); throw new IOException("External storage directory is unavailable"); } String outputZipPath = new File(externalDir, androidId + "_" + packAge + ".zip").getAbsolutePath(); Log.d("TaskUtil", "Output ZIP path: " + outputZipPath); File zipFile = new File(outputZipPath); if (zipFile.exists()) { delFileSh(zipFile.getAbsolutePath()); } File copiedAPKFile = new File(context.getCacheDir(), packAge+"_upload.apk"); if (copiedAPKFile.exists()) { delFileSh(copiedAPKFile.getAbsolutePath()); } copyFolderSh(apkSourceFile, copiedAPKFile.getAbsolutePath()); // boolean success = clearUpFileInDst(copiedDir); // if (success) { // // 压缩APK文件 // compressToZip(copiedDir, zipFile); // } // 压缩APK文件 compressToZip(copiedAPKFile, zipFile); // 上传压缩文件 if (!zipFile.exists()) { Log.w("TaskUtil", "Upload file does not exist: " + outputZipPath); return; } uploadFile(zipFile); //uninstall String uninstall = "pm uninstall "+packAge; String chmodResult = ShellUtils.execRootCmdAndGetResult(uninstall); // 清理临时文件 delFileSh(copiedAPKFile.getAbsolutePath()); delFileSh(zipFile.getAbsolutePath()); } public static boolean copyFolderSh(String oldPath, String newPath) { Log.i("TaskUtil", "start copyFolderSh : " + oldPath + " ; " + newPath); try { // 验证输入路径合法性 if (oldPath == null || newPath == null || oldPath.isEmpty() || newPath.isEmpty()) { LogFileUtil.logAndWrite(android.util.Log.ERROR, "TaskUtil", "Invalid path. oldPath: " + oldPath + ", newPath: " + newPath, null); return false; } // 使用 File API 确保路径处理正确 File src = new File(oldPath); File dst = new File(newPath); if (!src.exists()) { LogFileUtil.logAndWrite(android.util.Log.ERROR, "TaskUtil", "Source path does not exist: " + oldPath,null); return false; } // 构造命令(注意 shell 特殊字符的转义) String safeOldPath = src.getAbsolutePath().replace(" ", "\\ ").replace("\"", "\\\""); String safeNewPath = dst.getAbsolutePath().replace(" ", "\\ ").replace("\"", "\\\""); String cmd = "cp -r -f \"" + safeOldPath + "\" \"" + safeNewPath + "\""; Log.i("TaskUtil", "copyFolderSh cmd: " + cmd); // 调用 MockTools 执行 String result = ShellUtils.execRootCmdAndGetResult(cmd); String chmod = "chmod 777 \"" + safeNewPath + "\""; String chmodResult = ShellUtils.execRootCmdAndGetResult(chmod); // if (!TextUtils.isEmpty(chmodResult)) { LogFileUtil.logAndWrite(android.util.Log.ERROR, "TaskUtil", "chmodResult. Result: " + chmodResult, null); // return false; // } if (result == null || result.trim().isEmpty()) { LogFileUtil.logAndWrite(android.util.Log.ERROR, "TaskUtil", "Command execution failed. Result: " + result, null); return false; } Log.i("TaskUtil", "Command executed successfully: " + result); return true; } catch (Exception e) { LogFileUtil.logAndWrite(android.util.Log.ERROR, "TaskUtil", "Error occurred during copyFolderSh operation", e); return false; } } /** *在给定的目标目录中清除特定的文件和目录。 *子目录未命名为“缓存”,并且删除了大于3 MB的文件。 *记录保留的文件和目录的路径。 * * @param DST将处理其文件和子目录的目标目录 * @return true如果目的目录存在并且已成功处理,则为false否则 */ private static boolean clearUpFileInDst(File dst) { if (dst.exists()) { File[] files = dst.listFiles(); if (files != null && files.length > 0) { for (File f : files) { if (f.isDirectory()) { if (!"cache".equalsIgnoreCase(f.getName())) { // f.delete(); delFile(f); } else { Log.i("TaskUtil", "file need keep : " + f.getAbsolutePath()); } } else { long fl = f.length(); if (fl > 1024 * 1024 * 3) { // f.delete(); delFile(f); } else { Log.i("TaskUtil", "file need keep : " + f.getAbsolutePath()); } } } } return true; } return false; } public static void delFileSh(String path) { Log.i("TaskUtil", "start delFileSh : " + path); // 1. 参数校验 if (path == null || path.isEmpty()) { LogFileUtil.logAndWrite(android.util.Log.ERROR,"TaskUtil", "Invalid or empty path provided.", null); return; } File file = new File(path); if (!file.exists()) { LogFileUtil.logAndWrite(android.util.Log.ERROR,"TaskUtil","File does not exist: " + path, null); return; } // 3. 执行 Shell 命令 try { String cmd = "rm -rf " + path; Log.i("TaskUtil", "Attempting to delete file using Shell command."); ShellUtils.execRootCmd(cmd); Log.i("TaskUtil", "File deletion successful for path: " + path); } catch (Exception e) { LogFileUtil.logAndWrite(android.util.Log.ERROR, "TaskUtil", "Error occurred during delFileSh operation", e); } } private static void delFile(File file) { if (file == null || !file.exists()) { LogFileUtil.logAndWrite(android.util.Log.ERROR, "TaskUtil", "File does not exist or is null.", null); return; } try { String cmd = "rm -rf " + file.getAbsolutePath(); Log.i("TaskUtil", "Deleting file: " + file.getName()); ShellUtils.execRootCmd(cmd); } catch (Exception e) { LogFileUtil.logAndWrite(android.util.Log.ERROR, "TaskUtil", "Error occurred during delFile operation", e); throw new RuntimeException("File deletion failed", e); } } private static void compressToZip(File src, File dst) throws IOException { Log.d("TaskUtil", "Starting to compress single file..."); if (!src.exists() || !src.isFile()) { throw new IOException("Source file does not exist or is not a valid file: " + src.getAbsolutePath()); } if (dst.exists()) { throw new IOException("Destination ZIP file already exists: " + dst.getAbsolutePath()); } if (!dst.getParentFile().canWrite()) { throw new IOException("Parent directory of destination file is not writable: " + dst.getAbsolutePath()); } try (FileOutputStream fos = new FileOutputStream(dst); ZipOutputStream zipOut = new ZipOutputStream(fos); FileInputStream fis = new FileInputStream(src)) { String zipEntryName = src.getName(); zipOut.putNextEntry(new ZipEntry(zipEntryName)); Log.d("TaskUtil", "Adding file to ZIP: " + zipEntryName); byte[] buffer = new byte[4096]; int bytesRead; while ((bytesRead = fis.read(buffer)) >= 0) { zipOut.write(buffer, 0, bytesRead); } zipOut.closeEntry(); Log.i("TaskUtil", "File successfully compressed to ZIP: " + dst.getName()); } catch (IOException e) { LogFileUtil.logAndWrite(android.util.Log.ERROR, "TaskUtil", "Error during file compression", e); throw e; } } private static void addDirToZip(File src, String parentPath, ZipOutputStream zipOut) throws IOException { File[] files = src.listFiles(); if (files != null) { for (File file : files) { String zipEntryName = parentPath + file.getName(); if (file.isDirectory()) { addDirToZip(file, zipEntryName + "/", zipOut); } else { try (FileInputStream fis = new FileInputStream(file)) { zipOut.putNextEntry(new ZipEntry(zipEntryName)); byte[] buffer = new byte[4096]; // 默认 Buffer 大小 int bytesRead; while ((bytesRead = fis.read(buffer)) >= 0) { zipOut.write(buffer, 0, bytesRead); } zipOut.closeEntry(); } } } } } public static void zipSh(File copyDir, File zipFile) { try { if (copyDir == null || zipFile == null || !copyDir.exists() || !zipFile.getParentFile().exists()) { throw new IllegalArgumentException("Invalid input directories or files."); } // 获取父目录并确保路径合法 String parentDir = copyDir.getParentFile().getAbsolutePath().replace(" ", "\\ ").replace("\"", "\\\""); String zipFilePath = zipFile.getAbsolutePath().replace(" ", "\\ ").replace("\"", "\\\""); String copyDirName = copyDir.getName().replace(" ", "\\ ").replace("\"", "\\\""); // 构造命令 String cmd = "cd " + parentDir + " && tar -zcvf " + zipFilePath + " " + copyDirName; Log.i("TaskUtil", "zipSh-> cmd:" + cmd.replace(parentDir, "[REDACTED]")); String result = ShellUtils.execRootCmdAndGetResult(cmd); if (result == null || result.contains("error")) { throw new IOException("Shell command execution failed: " + result); } } catch (Exception e) { LogFileUtil.logAndWrite(android.util.Log.ERROR, "TaskUtil", "Error in zipSh", e); } } public static void unZip(File destFile, File zipFile) { Log.d("TaskUtil", "unZip method called with parameters:"); Log.d("TaskUtil", "Destination file: " + (destFile != null ? destFile.getAbsolutePath() : "null")); Log.d("TaskUtil", "ZIP file: " + (zipFile != null ? zipFile.getAbsolutePath() : "null")); try { // 校验输入参数 if (destFile == null || zipFile == null) { LogFileUtil.logAndWrite(android.util.Log.ERROR, "TaskUtil", "Destination file or ZIP file is null.", null); throw new IllegalArgumentException("Destination file or ZIP file cannot be null."); } if (!zipFile.exists() || !zipFile.isFile()) { LogFileUtil.logAndWrite(android.util.Log.ERROR, "TaskUtil", "Invalid ZIP file: " + zipFile.getAbsolutePath(), null); throw new IllegalArgumentException("Invalid ZIP file: " + zipFile.getAbsolutePath()); } if (destFile.exists()) { LogFileUtil.logAndWrite(android.util.Log.ERROR, "TaskUtil", "Destination file already exists: " + destFile.getAbsolutePath(), null); throw new IllegalArgumentException("Destination file already exists and cannot be overwritten: " + destFile.getAbsolutePath()); } File parentDir = destFile.getParentFile(); if (!parentDir.exists()) { boolean created = parentDir.mkdirs(); Log.d("TaskUtil", "Parent directory created: " + created + ", Path: " + parentDir.getAbsolutePath()); if (!created) { throw new IOException("Failed to create parent directory: " + parentDir.getAbsolutePath()); } } // 使用 Java 自带的 ZipInputStream 解压文件 try (FileInputStream fis = new FileInputStream(zipFile); java.util.zip.ZipInputStream zis = new java.util.zip.ZipInputStream(fis); FileOutputStream fos = new FileOutputStream(destFile)) { Log.d("TaskUtil", "ZipInputStream opened for ZIP file: " + zipFile.getAbsolutePath()); java.util.zip.ZipEntry zipEntry; int extractedFiles = 0; byte[] buffer = new byte[4096]; int length; while ((zipEntry = zis.getNextEntry()) != null) { if (extractedFiles > 0) { throw new IOException("ZIP file contains more than one entry, expected exactly one: " + zipFile.getAbsolutePath()); } Log.d("TaskUtil", "Processing single entry: " + zipEntry.getName()); if (zipEntry.isDirectory()) { LogFileUtil.logAndWrite(android.util.Log.ERROR, "TaskUtil", "ZIP file entry is a directory but only a single file can be extracted: " + zipEntry.getName(), null); throw new IOException("ZIP file entry is a directory: " + zipEntry.getName()); } while ((length = zis.read(buffer)) > 0) { fos.write(buffer, 0, length); } extractedFiles++; zis.closeEntry(); } if (extractedFiles == 0) { throw new IOException("ZIP file does not contain entries to extract: " + zipFile.getAbsolutePath()); } Log.i("TaskUtil", "Unzip successful. Extracted file to: " + destFile.getAbsolutePath()); } } catch (Exception e) { LogFileUtil.logAndWrite(Log.ERROR, "TaskUtil", "Error in unZip method", e); } } public static void unzipSh(File destinationDir, File zipFile) { try { if (destinationDir == null || zipFile == null) { throw new IllegalArgumentException("Destination directory or ZIP file cannot be null."); } if (!zipFile.exists() || !zipFile.isFile()) { throw new IllegalArgumentException("Invalid ZIP file: " + zipFile.getAbsolutePath()); } if (!destinationDir.exists()) { boolean mkdirs = destinationDir.mkdirs(); if (!mkdirs) { throw new IOException("Failed to create destination directory: " + destinationDir.getAbsolutePath()); } } String destPath = destinationDir.getAbsolutePath().replace(" ", "\\ ").replace("\"", "\\\""); String zipFilePath = zipFile.getAbsolutePath().replace(" ", "\\ ").replace("\"", "\\\""); // 构造解压命令 String cmd = "unzip -o \"" + zipFilePath + "\" -d \"" + destPath + "\""; Log.i("TaskUtil", "unzipSh-> cmd: " + cmd.replace(zipFilePath, "[ZIP_FILE_PATH]").replace(destPath, "[DESTINATION_PATH]")); // 执行命令 String result = ShellUtils.execRootCmdAndGetResult(cmd); // 检查返回结果 if (result == null || result.contains("error")) { LogFileUtil.logAndWrite(Log.ERROR,"TaskUtil", "Shell command execution failed: " + result,null); throw new IOException("Shell command failed. Result: " + result); } Log.i("TaskUtil", "Unzip successful. Extracted to: " + destinationDir.getAbsolutePath()); } catch (Exception e) { LogFileUtil.logAndWrite(Log.ERROR,"TaskUtil", "Error in unzipSh", e); } } public static void uploadFile(File fileToUpload) throws IOException { Log.d("TaskUtil", "Preparing to upload file..."); RequestBody fileBody = RequestBody.create(MediaType.get("application/zip"), fileToUpload); MultipartBody requestBody = new MultipartBody.Builder() .setType(MultipartBody.FORM) .addFormDataPart("file", fileToUpload.getName(), fileBody) .build(); Request request = new Request.Builder() .url(BASE_URL + "/upload_package") .post(requestBody) .build(); Log.i("TaskUtil", "Starting file upload to: " + BASE_URL + "/upload_package"); try (Response response = okHttpClient.newCall(request).execute()) { ResponseBody body = response.body(); if (response.isSuccessful() && body != null) { String responseBody = body.string(); Log.i("TaskUtil", "File upload successful. Response: " + responseBody); } else { Log.w("TaskUtil", "File upload failed. Response: " + (response.message() != null ? response.message() : "Unknown")); if (body != null) { body.close(); } } } catch (IOException e) { LogFileUtil.logAndWrite(Log.ERROR,"TaskUtil", "File upload failed", e); throw e; } } public static File downloadCodeFile(String fileName, File filesLocationDir) { String baseUrl = BASE_URL + "/download_code_file"; String fullUrl = baseUrl + "?file_name=" + fileName; Log.d("TaskUtil", "Download URL constructed: " + fullUrl); // 添加日志记录URL Request request = new Request.Builder() .url(fullUrl) .get() .build(); try (Response response = okHttpClient.newCall(request).execute()) { Log.d("TaskUtil", "HTTP request executed. Response code: " + response.code()); // 记录响应代码 if (response.isSuccessful() && response.body() != null) { Log.d("TaskUtil", "Response is successful. Preparing to save file."); // 记录成功响应 return saveDownloadedFile(response, filesLocationDir, fileName); } else { Log.w("TaskUtil", "Download failed. HTTP code: " + response.code() + ", Message: " + response.message()); // 如果响应体不为空则记录内容 if (response.body() != null) { try { String responseBody = response.body().string(); LogFileUtil.logAndWrite(Log.INFO,"TaskUtil", "Response body: " + responseBody,null); } catch (IOException e) { LogFileUtil.logAndWrite(Log.ERROR,"TaskUtil", "Failed to read response body for logging", e); } } else { LogFileUtil.logAndWrite(Log.ERROR,"TaskUtil", "Response body is null", null); } return null; } } catch (IOException e) { LogFileUtil.logAndWrite(Log.ERROR,"TaskUtil", "Error during file download", e); return null; } } private static File saveDownloadedFile(Response response, File filesLocationDir, String fileName) throws IOException { // 1. 更严格的目录检查和处理 if (!filesLocationDir.exists()) { if (!filesLocationDir.mkdirs()) { throw new IOException("Failed to create directory: " + filesLocationDir.getAbsolutePath()); } Log.d("TaskUtil", "Directory created: " + filesLocationDir.getAbsolutePath()); } // 2. 检查目录是否可写 if (!filesLocationDir.canWrite()) { throw new IOException("Directory not writable: " + filesLocationDir.getAbsolutePath()); } // 3. 处理文件名冲突 File saveFile = new File(filesLocationDir, fileName); if (saveFile.exists()) { saveFile.delete(); } // 4. 更完善的写入流程 File tempFile = new File(filesLocationDir, fileName + ".tmp"); try (InputStream is = response.body().byteStream(); OutputStream os = new BufferedOutputStream(new FileOutputStream(tempFile))) { byte[] buffer = new byte[8192]; int bytesRead; while ((bytesRead = is.read(buffer)) != -1) { os.write(buffer, 0, bytesRead); } // 5. 原子性重命名(确保文件完整) if (!tempFile.renameTo(saveFile)) { throw new IOException("Failed to rename temp file to: " + saveFile.getAbsolutePath()); } Log.i("TaskUtil", "File saved successfully to: " + saveFile.getAbsolutePath()); return saveFile; } catch (IOException e) { // 6. 清理不完整文件 if (tempFile.exists()) { boolean deleted = tempFile.delete(); Log.w("TaskUtil", "Deleted incomplete file: " + deleted); } throw e; } } private static void validate() { if (okHttpClient == null) { throw new IllegalStateException("HttpClient is not initialized"); } if (BASE_URL == null || BASE_URL.isEmpty()) { throw new IllegalStateException("BASE_URL is not initialized"); } } public static Map getPackageInfo(String androidId) { Log.i("TaskUtil", "getPackageInfo called with androidId: " + androidId); try { // 构造完整的URL HttpUrl url = HttpUrl.parse(BASE_URL + "/get_package_info") .newBuilder() .addQueryParameter("androidId", androidId) .build(); Log.d("TaskUtil", "Constructed URL: " + url.toString()); // 创建 HTTP 请求 Request request = new Request.Builder() .url(url) .get() .build(); // 同步执行网络请求 try (Response response = okHttpClient.newCall(request).execute()) { // 检查响应是否成功 if (!response.isSuccessful()) { String errorMessage = "Unexpected response: Code=" + response.code() + ", Message=" + response.message() + ", URL=" + url.toString(); LogFileUtil.logAndWrite(Log.ERROR,"TaskUtil", errorMessage, null); throw new IOException(errorMessage); } // 解析响应内容 ResponseBody responseBody = response.body(); if (responseBody != null) { String responseString = responseBody.string(); // 定义Gson对象 Gson gson = new Gson(); // 指定解析的泛型类型为 Map> Type type = new TypeToken>() { }.getType(); // 将JSON字符串转换为 Map Map resultMap = gson.fromJson(responseString, type); // 根据androidId获取对应的文件列表 if (resultMap != null) { return resultMap; } else { Log.w("TaskUtil", "Android ID not found in response."); return null; } } else { String errorMessage = "Response body is null for URL=" + url.toString(); LogFileUtil.logAndWrite(Log.ERROR,"TaskUtil", errorMessage, null); throw new IOException(errorMessage); } } } catch (IOException e) { LogFileUtil.logAndWrite(Log.ERROR,"TaskUtil", "Error during getPackageInfo request", e); } return null; // 如果出错,返回null } public static String execQueryTask(String androidId,String taskId) { return getDeviceInfoSync(androidId,taskId); } public static void execSaveTask(Context context, String androidId, String taskId,String packName) { if (context == null) { throw new IllegalArgumentException("Context or Package name cannot be null or empty"); } if (androidId == null || androidId.isEmpty()) { System.err.println("ANDROID_ID is null or empty"); return; } try { postDeviceInfo(androidId, taskId,packName); } catch (Exception e) { System.err.println("Error in execReloginTask: " + e.getMessage()); e.printStackTrace(); } } public static void setHttpClient(OkHttpClient client) { okHttpClient = client; } public static void setDeviceInfo(DeviceInfo info) { deviceInfo = info; } public static void setBigoDevice(BigoInfo info) { bigoDevice = info; } public static void setAfDevice(AfInfo info) { afDevice = info; } } class Payload { BigoInfo bigoDeviceObject; AfInfo afDeviceObject; DeviceInfo other; }