接口初步对接,正在调试数据处理方法...
This commit is contained in:
		| @@ -1,8 +1,8 @@ | |||||||
| #Created by .winboll/winboll_app_build.gradle | #Created by .winboll/winboll_app_build.gradle | ||||||
| #Thu Jun 05 01:50:42 GMT 2025 | #Thu Jun 05 03:57:29 GMT 2025 | ||||||
| stageCount=7 | stageCount=7 | ||||||
| libraryProject=libappbase | libraryProject=libappbase | ||||||
| baseVersion=15.8 | baseVersion=15.8 | ||||||
| publishVersion=15.8.6 | publishVersion=15.8.6 | ||||||
| buildCount=38 | buildCount=58 | ||||||
| baseBetaVersion=15.8.7 | baseBetaVersion=15.8.7 | ||||||
|   | |||||||
| @@ -24,5 +24,8 @@ dependencies { | |||||||
|     api fileTree(dir: 'libs', include: ['*.jar']) |     api fileTree(dir: 'libs', include: ['*.jar']) | ||||||
|     // 网络连接类库 |     // 网络连接类库 | ||||||
|     api 'com.squareup.okhttp3:okhttp:4.4.1' |     api 'com.squareup.okhttp3:okhttp:4.4.1' | ||||||
|      |     api 'com.fasterxml.jackson.core:jackson-databind:2.15.2' | ||||||
|  |     // 添加Gson依赖 | ||||||
|  |     api 'com.google.code.gson:gson:2.10.1' | ||||||
|  |  | ||||||
| } | } | ||||||
|   | |||||||
| @@ -1,8 +1,8 @@ | |||||||
| #Created by .winboll/winboll_app_build.gradle | #Created by .winboll/winboll_app_build.gradle | ||||||
| #Thu Jun 05 01:50:42 GMT 2025 | #Thu Jun 05 03:57:29 GMT 2025 | ||||||
| stageCount=7 | stageCount=7 | ||||||
| libraryProject=libappbase | libraryProject=libappbase | ||||||
| baseVersion=15.8 | baseVersion=15.8 | ||||||
| publishVersion=15.8.6 | publishVersion=15.8.6 | ||||||
| buildCount=38 | buildCount=58 | ||||||
| baseBetaVersion=15.8.7 | baseBetaVersion=15.8.7 | ||||||
|   | |||||||
| @@ -3,16 +3,18 @@ package cc.winboll.studio.libappbase.activities; | |||||||
| import android.app.Activity; | import android.app.Activity; | ||||||
| import android.os.Bundle; | import android.os.Bundle; | ||||||
| import android.view.View; | import android.view.View; | ||||||
|  | import android.widget.RadioButton; | ||||||
|  | import cc.winboll.studio.libappbase.BuildConfig; | ||||||
| import cc.winboll.studio.libappbase.LogUtils; | import cc.winboll.studio.libappbase.LogUtils; | ||||||
| import cc.winboll.studio.libappbase.LogView; | import cc.winboll.studio.libappbase.LogView; | ||||||
| import cc.winboll.studio.libappbase.R; | import cc.winboll.studio.libappbase.R; | ||||||
|  | import cc.winboll.studio.libappbase.models.UserInfoModel; | ||||||
| import cc.winboll.studio.libappbase.utils.RSAUtils; | import cc.winboll.studio.libappbase.utils.RSAUtils; | ||||||
|  | import cc.winboll.studio.libappbase.utils.YunUtils; | ||||||
| import cc.winboll.studio.libappbase.winboll.IWinBoLLActivity; | import cc.winboll.studio.libappbase.winboll.IWinBoLLActivity; | ||||||
| import java.security.KeyPair; | import java.security.KeyPair; | ||||||
| import java.security.PrivateKey; | import java.security.PrivateKey; | ||||||
| import java.security.PublicKey; | import java.security.PublicKey; | ||||||
| import cc.winboll.studio.libappbase.utils.YunUtils; |  | ||||||
| import java.nio.charset.StandardCharsets; |  | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * @Author ZhanGSKen<zhangsken@188.com> |  * @Author ZhanGSKen<zhangsken@188.com> | ||||||
| @@ -23,8 +25,14 @@ public class LogonActivity extends Activity implements IWinBoLLActivity { | |||||||
|  |  | ||||||
|     public static final String TAG = "LogonActivity"; |     public static final String TAG = "LogonActivity"; | ||||||
|  |  | ||||||
|  |     public static final String DEBUG_HOST = "http://10.8.0.250:456"; | ||||||
|  |     public static final String YUN_HOST = "https://yun.winboll.cc"; | ||||||
|  |      | ||||||
|  |     String mHost = ""; | ||||||
|  |     RadioButton mrbYunHost; | ||||||
|  |     RadioButton mrbDebugHost; | ||||||
|     LogView mLogView; |     LogView mLogView; | ||||||
|  |      | ||||||
|     @Override |     @Override | ||||||
|     public Activity getActivity() { |     public Activity getActivity() { | ||||||
|         return this; |         return this; | ||||||
| @@ -42,6 +50,25 @@ public class LogonActivity extends Activity implements IWinBoLLActivity { | |||||||
|         mLogView = findViewById(R.id.logview); |         mLogView = findViewById(R.id.logview); | ||||||
|         mLogView.start(); |         mLogView.start(); | ||||||
|  |  | ||||||
|  |         mHost = BuildConfig.DEBUG ? DEBUG_HOST: YUN_HOST; | ||||||
|  |         if (BuildConfig.DEBUG) { | ||||||
|  |             mrbYunHost = findViewById(R.id.rb_yunhost); | ||||||
|  |             mrbDebugHost = findViewById(R.id.rb_debughost); | ||||||
|  |             mrbYunHost.setChecked(!BuildConfig.DEBUG); | ||||||
|  |             mrbDebugHost.setChecked(BuildConfig.DEBUG); | ||||||
|  |         } else { | ||||||
|  |             findViewById(R.id.ll_hostbar).setVisibility(View.GONE); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |      | ||||||
|  |     public void onSwitchHost(View view) { | ||||||
|  |         if (view.getId() == R.id.rb_yunhost) { | ||||||
|  |             mrbDebugHost.setChecked(false); | ||||||
|  |             mHost = YUN_HOST; | ||||||
|  |         } else if (view.getId() == R.id.rb_debughost) { | ||||||
|  |             mrbYunHost.setChecked(false); | ||||||
|  |             mHost = DEBUG_HOST; | ||||||
|  |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     @Override |     @Override | ||||||
| @@ -52,9 +79,13 @@ public class LogonActivity extends Activity implements IWinBoLLActivity { | |||||||
|  |  | ||||||
|     public void onTestLogin(View view) { |     public void onTestLogin(View view) { | ||||||
|         LogUtils.d(TAG, "onTestLogin"); |         LogUtils.d(TAG, "onTestLogin"); | ||||||
|         YunUtils yunUtils = YunUtils.getInstance(this); |         final YunUtils yunUtils = YunUtils.getInstance(this); | ||||||
|         yunUtils.login(); |          | ||||||
|         yunUtils.checkLoginStatus(); |         UserInfoModel userInfoModel = new UserInfoModel(); | ||||||
|  |         userInfoModel.setUsername("jian"); | ||||||
|  |         userInfoModel.setPassword("kkiio"); | ||||||
|  |         userInfoModel.setToken("aaa111"); | ||||||
|  |         yunUtils.login(mHost, userInfoModel); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     public void onTestRSA(View view) { |     public void onTestRSA(View view) { | ||||||
| @@ -113,4 +144,6 @@ public class LogonActivity extends Activity implements IWinBoLLActivity { | |||||||
|             LogUtils.d(TAG, e, Thread.currentThread().getStackTrace()); |             LogUtils.d(TAG, e, Thread.currentThread().getStackTrace()); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |      | ||||||
|  |  | ||||||
| } | } | ||||||
|   | |||||||
| @@ -0,0 +1,38 @@ | |||||||
|  | package cc.winboll.studio.libappbase.models; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * @Author ZhanGSKen<zhangsken@188.com> | ||||||
|  |  * @Date 2025/06/05 11:26 | ||||||
|  |  */ | ||||||
|  | import com.fasterxml.jackson.annotation.JsonProperty; | ||||||
|  |  | ||||||
|  | public class ResponseData { | ||||||
|  |     @JsonProperty("status") | ||||||
|  |     private String status; | ||||||
|  |     @JsonProperty("message") | ||||||
|  |     private String message; | ||||||
|  |  | ||||||
|  |     // ❌ 原代码只有带参构造函数,缺少无参构造函数 | ||||||
|  |     // public ResponseData(String status, String message) { | ||||||
|  |     //     this.status = status; | ||||||
|  |     //     this.message = message; | ||||||
|  |     // } | ||||||
|  |  | ||||||
|  |     // ✅ 添加无参构造函数(Jackson 反序列化必需) | ||||||
|  |     public ResponseData() { | ||||||
|  |         // 空实现 | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     // 保留带参构造函数(可选,用于手动创建实例) | ||||||
|  |     public ResponseData(String status, String message) { | ||||||
|  |         this.status = status; | ||||||
|  |         this.message = message; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     // Getter 和 Setter | ||||||
|  |     public String getStatus() { return status; } | ||||||
|  |     public void setStatus(String status) { this.status = status; } | ||||||
|  |     public String getMessage() { return message; } | ||||||
|  |     public void setMessage(String message) { this.message = message; } | ||||||
|  | } | ||||||
|  |  | ||||||
| @@ -4,17 +4,21 @@ package cc.winboll.studio.libappbase.models; | |||||||
|  * @Author ZhanGSKen<zhangsken@188.com> |  * @Author ZhanGSKen<zhangsken@188.com> | ||||||
|  * @Date 2025/06/04 19:14 |  * @Date 2025/06/04 19:14 | ||||||
|  */ |  */ | ||||||
| import cc.winboll.studio.libappbase.BaseBean; |  | ||||||
| import android.util.JsonWriter; |  | ||||||
| import android.util.JsonReader; | import android.util.JsonReader; | ||||||
|  | import android.util.JsonWriter; | ||||||
|  | import cc.winboll.studio.libappbase.BaseBean; | ||||||
|  | import com.fasterxml.jackson.annotation.JsonProperty; | ||||||
| import java.io.IOException; | import java.io.IOException; | ||||||
|  |  | ||||||
| public class UserInfoModel extends BaseBean { | public class UserInfoModel extends BaseBean { | ||||||
|  |  | ||||||
|     public static final String TAG = "UserInfoModel"; |     public static final String TAG = "UserInfoModel"; | ||||||
|  |  | ||||||
|  |     @JsonProperty("username") | ||||||
|     String username; |     String username; | ||||||
|  |     @JsonProperty("password") | ||||||
|     String password; |     String password; | ||||||
|  |     @JsonProperty("token") | ||||||
|     String token; |     String token; | ||||||
|  |  | ||||||
|     public UserInfoModel() { |     public UserInfoModel() { | ||||||
|   | |||||||
| @@ -0,0 +1,46 @@ | |||||||
|  | package cc.winboll.studio.libappbase.utils; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * @Author ZhanGSKen<zhangsken@188.com> | ||||||
|  |  * @Date 2025/06/05 11:09 | ||||||
|  |  */ | ||||||
|  | import cc.winboll.studio.libappbase.LogUtils; | ||||||
|  | import cc.winboll.studio.libappbase.models.ResponseData; | ||||||
|  | import com.fasterxml.jackson.databind.ObjectMapper; | ||||||
|  | import java.net.URLDecoder; | ||||||
|  |  | ||||||
|  | public class JsonFormatter { | ||||||
|  |     public static final String TAG = "JsonFormatter"; | ||||||
|  |      | ||||||
|  |     /** | ||||||
|  |      * 将包含 Unicode 转义的 JSON 字符串转为可读中文 | ||||||
|  |      * @param jsonStr 原始 JSON 字符串(如:{"status":"error","message":"\u672a\u63a5\u6536\u5230 JSON \u6570\u636e"}) | ||||||
|  |      * @return 格式化后的中文消息字符串 | ||||||
|  |      */ | ||||||
|  |     public static String formatUnicodeToChinese(String jsonStr) { | ||||||
|  |         try { | ||||||
|  |             // 1. 使用 Jackson 解析 JSON 到对象 | ||||||
|  |             ObjectMapper mapper = new ObjectMapper(); | ||||||
|  |             ResponseData data = mapper.readValue(jsonStr, ResponseData.class); | ||||||
|  |  | ||||||
|  |             // 2. 解码 Unicode 转义字符(如 \u672a 转为中文) | ||||||
|  |             String decodedMessage = URLDecoder.decode(data.getMessage(), "UTF-8"); | ||||||
|  |  | ||||||
|  |             // 3. 重新构建 JSON(可选:如需保留 JSON 格式) | ||||||
|  |             return "{\"status\":\"" + data.getStatus() + "\",\"message\":\"" + decodedMessage + "\"}"; | ||||||
|  |  | ||||||
|  |         } catch (Exception e) { | ||||||
|  |             LogUtils.d(TAG, e, Thread.currentThread().getStackTrace()); | ||||||
|  |             return jsonStr; // 解析失败时返回原始字符串 | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     // 示例用法 | ||||||
|  |     /*public static void main(String[] args) { | ||||||
|  |         String rawJson = "{\"status\":\"error\",\"message\":\"\\u672a\\u63a5\\u6536\\u5230 JSON \\u6570\\u636e\"}"; | ||||||
|  |         String formattedJson = formatUnicodeToChinese(rawJson); | ||||||
|  |         System.out.println("格式化前:" + rawJson); | ||||||
|  |         System.out.println("格式化后:" + formattedJson); | ||||||
|  |     }*/ | ||||||
|  | } | ||||||
|  |  | ||||||
| @@ -6,6 +6,7 @@ package cc.winboll.studio.libappbase.utils; | |||||||
|  * @Describe RSA加密工具 |  * @Describe RSA加密工具 | ||||||
|  */ |  */ | ||||||
| import android.content.Context; | import android.content.Context; | ||||||
|  | import android.util.Base64; | ||||||
| import cc.winboll.studio.libappbase.LogUtils; | import cc.winboll.studio.libappbase.LogUtils; | ||||||
| import java.io.File; | import java.io.File; | ||||||
| import java.io.FileInputStream; | import java.io.FileInputStream; | ||||||
| @@ -196,5 +197,26 @@ public class RSAUtils { | |||||||
|         byte[] decryptedBytes = cipher.doFinal(encryptedData); |         byte[] decryptedBytes = cipher.doFinal(encryptedData); | ||||||
|         return new String(decryptedBytes, "UTF-8"); |         return new String(decryptedBytes, "UTF-8"); | ||||||
|     } |     } | ||||||
|  |     /** | ||||||
|  |      * 将 HTTP 传输的 Base64 字符串还原为加密字节数组(Java 7 兼容) | ||||||
|  |      * @param httpString Base64 字符串(非 null) | ||||||
|  |      * @return 加密字节数组 | ||||||
|  |      * @throws IllegalArgumentException 解码失败时抛出 | ||||||
|  |      */ | ||||||
|  |     public byte[] httpStringToEncryptBytes(String httpString) { | ||||||
|  |         Objects.requireNonNull(httpString, "HTTP 字符串不可为空"); | ||||||
|  |  | ||||||
|  |         // 计算缺失的填充符数量(Java 7 不支持 repeat(),手动拼接) | ||||||
|  |         int pad = httpString.length() % 4; | ||||||
|  |         StringBuilder paddedString = new StringBuilder(httpString); | ||||||
|  |         if (pad != 0) { | ||||||
|  |             for (int i = 0; i < pad; i++) { | ||||||
|  |                 paddedString.append('='); // 补全 '=' | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         // 使用 Base64 解码(Android 原生 Base64 类兼容 Java 7) | ||||||
|  |         return Base64.decode(paddedString.toString(), Base64.URL_SAFE); | ||||||
|  |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -6,14 +6,25 @@ package cc.winboll.studio.libappbase.utils; | |||||||
|  * @Describe 应用登录与接口工具 |  * @Describe 应用登录与接口工具 | ||||||
|  */ |  */ | ||||||
| import android.content.Context; | import android.content.Context; | ||||||
|  | import android.os.Handler; | ||||||
|  | import android.os.Looper; | ||||||
| import cc.winboll.studio.libappbase.LogUtils; | import cc.winboll.studio.libappbase.LogUtils; | ||||||
| import cc.winboll.studio.libappbase.models.APPModel; |  | ||||||
| import cc.winboll.studio.libappbase.models.UserInfoModel; | import cc.winboll.studio.libappbase.models.UserInfoModel; | ||||||
|  | import com.google.gson.Gson; | ||||||
| import java.io.File; | import java.io.File; | ||||||
|  | import java.io.IOException; | ||||||
|  | import java.nio.charset.StandardCharsets; | ||||||
| import java.security.KeyPair; | import java.security.KeyPair; | ||||||
| import java.security.PrivateKey; | import java.security.PrivateKey; | ||||||
| import java.security.PublicKey; | import java.security.PublicKey; | ||||||
| import java.nio.charset.StandardCharsets; | import java.util.concurrent.TimeUnit; | ||||||
|  | import okhttp3.Call; | ||||||
|  | import okhttp3.Callback; | ||||||
|  | import okhttp3.MediaType; | ||||||
|  | import okhttp3.OkHttpClient; | ||||||
|  | import okhttp3.Request; | ||||||
|  | import okhttp3.RequestBody; | ||||||
|  | import okhttp3.Response; | ||||||
|  |  | ||||||
| public class YunUtils { | public class YunUtils { | ||||||
|     public static final String TAG = "YunUtils"; |     public static final String TAG = "YunUtils"; | ||||||
| @@ -25,6 +36,12 @@ public class YunUtils { | |||||||
|     String mDataFolderPath = ""; |     String mDataFolderPath = ""; | ||||||
|     String mUserInfoModelPath = ""; |     String mUserInfoModelPath = ""; | ||||||
|  |  | ||||||
|  |     private static final int CONNECT_TIMEOUT = 15; // 连接超时时间(秒) | ||||||
|  |     private static final int READ_TIMEOUT = 20;    // 读取超时时间(秒) | ||||||
|  |     private static volatile YunUtils instance; | ||||||
|  |     private OkHttpClient okHttpClient; | ||||||
|  |     private Handler mainHandler; // 主线程 Handler | ||||||
|  |  | ||||||
|     // 私有构造方法,防止外部实例化 |     // 私有构造方法,防止外部实例化 | ||||||
|     private YunUtils(Context context) { |     private YunUtils(Context context) { | ||||||
|         LogUtils.d(TAG, "YunUtils"); |         LogUtils.d(TAG, "YunUtils"); | ||||||
| @@ -36,6 +53,11 @@ public class YunUtils { | |||||||
|         } |         } | ||||||
|         mUserInfoModelPath = mDataFolderPath + File.separator + "UserInfoModel.rsajson"; |         mUserInfoModelPath = mDataFolderPath + File.separator + "UserInfoModel.rsajson"; | ||||||
|  |  | ||||||
|  |         okHttpClient = new OkHttpClient.Builder() | ||||||
|  |             .connectTimeout(CONNECT_TIMEOUT, TimeUnit.SECONDS) | ||||||
|  |             .readTimeout(READ_TIMEOUT, TimeUnit.SECONDS) | ||||||
|  |             .build(); | ||||||
|  |         mainHandler = new Handler(Looper.getMainLooper()); // 获取主线程 Looper | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     // 公共静态方法,返回唯一实例 |     // 公共静态方法,返回唯一实例 | ||||||
| @@ -47,16 +69,6 @@ public class YunUtils { | |||||||
|         return INSTANCE; |         return INSTANCE; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     public void login() { |  | ||||||
|         String token = getHostToken(null); |  | ||||||
|         LogUtils.d(TAG, String.format("login token is %s", token)); |  | ||||||
|         saveLocalToken(token); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     public void logout() { |  | ||||||
|  |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     public void checkLoginStatus() { |     public void checkLoginStatus() { | ||||||
|         String token = getLocalToken(); |         String token = getLocalToken(); | ||||||
|         LogUtils.d(TAG, String.format("checkLoginStatus token is %s", token)); |         LogUtils.d(TAG, String.format("checkLoginStatus token is %s", token)); | ||||||
| @@ -67,12 +79,53 @@ public class YunUtils { | |||||||
|         return (userInfoModel == null) ?"": userInfoModel.getToken(); |         return (userInfoModel == null) ?"": userInfoModel.getToken(); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     String getHostToken(UserInfoModel userInfoModel) { |     public void login(String host, UserInfoModel userInfoModel) { | ||||||
|         String token = "uuyyhh"; |         LogUtils.d(TAG, "login"); | ||||||
|         return token; |  | ||||||
|  |         // 发送 POST 请求 | ||||||
|  |         String apiUrl = host + "/login/index.php"; | ||||||
|  |         // 序列化对象为JSON | ||||||
|  |         Gson gson = new Gson(); | ||||||
|  |         String jsonData = gson.toJson(userInfoModel); // 自动生成标准JSON | ||||||
|  |         //String jsonData = userInfoModel.toString(); | ||||||
|  |         LogUtils.d(TAG, "要发送的数据 : " + jsonData); | ||||||
|  |  | ||||||
|  |         sendPostRequest(apiUrl, jsonData, new OnResponseListener() { | ||||||
|  |                 // 成功回调(主线程) | ||||||
|  |                 @Override | ||||||
|  |                 public void onSuccess(String responseBody) { | ||||||
|  |                     LogUtils.d(TAG, "onSuccess"); | ||||||
|  |                     try { | ||||||
|  |                         String formattedJson = JsonFormatter.formatUnicodeToChinese(responseBody); | ||||||
|  |                         LogUtils.d(TAG, formattedJson); | ||||||
|  |                         return; | ||||||
|  |                     } catch (Exception e) { | ||||||
|  |                         LogUtils.d(TAG, e, Thread.currentThread().getStackTrace()); | ||||||
|  |                     } | ||||||
|  |                      | ||||||
|  |                     try { | ||||||
|  |                         UserInfoModel userInfoModel = UserInfoModel.parseStringToBean(responseBody, UserInfoModel.class); | ||||||
|  |                         if (userInfoModel != null) { | ||||||
|  |                             LogUtils.d(TAG, "收到网站 UserInfoModel"); | ||||||
|  |                             String token = userInfoModel.getToken(); | ||||||
|  |                             saveLocalToken(token); | ||||||
|  |                             checkLoginStatus(); | ||||||
|  |                         } | ||||||
|  |                     } catch (IOException e) { | ||||||
|  |                         LogUtils.d(TAG, e, Thread.currentThread().getStackTrace()); | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |  | ||||||
|  |                 // 失败回调(主线程) | ||||||
|  |                 @Override | ||||||
|  |                 public void onFailure(String errorMsg) { | ||||||
|  |                     LogUtils.d(TAG, errorMsg); | ||||||
|  |                     // 处理错误 | ||||||
|  |                 } | ||||||
|  |             }); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     void saveLocalToken(String token) { |     public void saveLocalToken(String token) { | ||||||
|         UserInfoModel userInfoModel = new UserInfoModel(); |         UserInfoModel userInfoModel = new UserInfoModel(); | ||||||
|         userInfoModel.setToken(token); |         userInfoModel.setToken(token); | ||||||
|         saveUserInfoModel(userInfoModel); |         saveUserInfoModel(userInfoModel); | ||||||
| @@ -136,4 +189,88 @@ public class YunUtils { | |||||||
|             LogUtils.d(TAG, "加密/解密失败: " + e.getMessage()); |             LogUtils.d(TAG, "加密/解密失败: " + e.getMessage()); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     // 发送 POST 请求(JSON 数据) | ||||||
|  |     public void sendPostRequest(String url, String data, OnResponseListener listener) { | ||||||
|  |         RequestBody requestBody = RequestBody.create( | ||||||
|  |             MediaType.parse("application/json; charset=utf-8"), // 关键头信息 | ||||||
|  |             data.getBytes(StandardCharsets.UTF_8) | ||||||
|  |         ); | ||||||
|  |  | ||||||
|  |         Request request = new Request.Builder() | ||||||
|  |             .url(url) | ||||||
|  |             .post(requestBody) | ||||||
|  |             .addHeader("Content-Type", "application/json") // 显式添加头 | ||||||
|  |             .build(); | ||||||
|  |  | ||||||
|  |         executeRequest(request, listener); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     // 发送 GET 请求 | ||||||
|  |     public void sendGetRequest(String url, OnResponseListener listener) { | ||||||
|  |         Request request = new Request.Builder() | ||||||
|  |             .url(url) | ||||||
|  |             .get() | ||||||
|  |             .build(); | ||||||
|  |         executeRequest(request, listener); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     // 执行请求(子线程处理) | ||||||
|  |     private void executeRequest(final Request request, final OnResponseListener listener) { | ||||||
|  |         okHttpClient.newCall(request).enqueue(new Callback() { | ||||||
|  |                 // 响应成功(子线程) | ||||||
|  |                 @Override | ||||||
|  |                 public void onResponse(Call call, Response response) throws IOException { | ||||||
|  |                     try { | ||||||
|  |                         if (!response.isSuccessful()) { | ||||||
|  |                             postFailure(listener, "响应码错误:" + response.code()); | ||||||
|  |                             return; | ||||||
|  |                         } | ||||||
|  |                         String responseBody = response.body().string(); | ||||||
|  |                         postSuccess(listener, responseBody); | ||||||
|  |                     } catch (Exception e) { | ||||||
|  |                         postFailure(listener, "解析失败:" + e.getMessage()); | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |  | ||||||
|  |                 // 响应失败(子线程) | ||||||
|  |                 @Override | ||||||
|  |                 public void onFailure(Call call, IOException e) { | ||||||
|  |                     postFailure(listener, "网络失败:" + e.getMessage()); | ||||||
|  |                 } | ||||||
|  |  | ||||||
|  |                 // 主线程回调(使用 Handler) | ||||||
|  |                 private void postSuccess(final OnResponseListener listener, final String msg) { | ||||||
|  |                     mainHandler.post(new Runnable() { | ||||||
|  |                             @Override | ||||||
|  |                             public void run() { | ||||||
|  |                                 listener.onSuccess(msg); | ||||||
|  |                             } | ||||||
|  |                         }); | ||||||
|  |                 } | ||||||
|  |  | ||||||
|  |                 private void postFailure(final OnResponseListener listener, final String msg) { | ||||||
|  |                     mainHandler.post(new Runnable() { | ||||||
|  |                             @Override | ||||||
|  |                             public void run() { | ||||||
|  |                                 listener.onFailure(msg); | ||||||
|  |                             } | ||||||
|  |                         }); | ||||||
|  |                 } | ||||||
|  |             }); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public interface OnResponseListener { | ||||||
|  |         /** | ||||||
|  |          * 成功响应(主线程回调) | ||||||
|  |          * @param responseBody 响应体字符串 | ||||||
|  |          */ | ||||||
|  |         void onSuccess(String responseBody); | ||||||
|  |  | ||||||
|  |         /** | ||||||
|  |          * 失败回调(包含错误信息) | ||||||
|  |          * @param errorMsg 错误描述 | ||||||
|  |          */ | ||||||
|  |         void onFailure(String errorMsg); | ||||||
|  |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -6,6 +6,31 @@ | |||||||
| 	android:layout_width="match_parent" | 	android:layout_width="match_parent" | ||||||
| 	android:layout_height="match_parent"> | 	android:layout_height="match_parent"> | ||||||
|  |  | ||||||
|  |     <LinearLayout | ||||||
|  |         android:orientation="horizontal" | ||||||
|  |         android:layout_width="match_parent" | ||||||
|  |         android:layout_height="wrap_content" | ||||||
|  |         android:layout_gravity="right" | ||||||
|  |         android:gravity="right" | ||||||
|  |         android:padding="10dp" | ||||||
|  |         android:id="@+id/ll_hostbar"> | ||||||
|  |  | ||||||
|  |         <RadioButton | ||||||
|  |             android:layout_width="wrap_content" | ||||||
|  |             android:layout_height="wrap_content" | ||||||
|  |             android:text="10.8.0.250:456" | ||||||
|  |             android:id="@+id/rb_debughost" | ||||||
|  |             android:onClick="onSwitchHost"/> | ||||||
|  |  | ||||||
|  |         <RadioButton | ||||||
|  |             android:layout_width="wrap_content" | ||||||
|  |             android:layout_height="wrap_content" | ||||||
|  |             android:text="yun.winboll.cc" | ||||||
|  |             android:id="@+id/rb_yunhost" | ||||||
|  |             android:onClick="onSwitchHost"/> | ||||||
|  |  | ||||||
|  | 	</LinearLayout> | ||||||
|  |      | ||||||
| 	<LinearLayout | 	<LinearLayout | ||||||
| 		android:orientation="horizontal" | 		android:orientation="horizontal" | ||||||
| 		android:layout_width="match_parent" | 		android:layout_width="match_parent" | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 ZhanGSKen
					ZhanGSKen