Browse Source

change network util

main
MTing 2 weeks ago
parent
commit
39d3520350
  1. 3
      .idea/.gitignore
  2. 6
      .idea/AndroidProjectSystem.xml
  3. 10
      .idea/migrations.xml
  4. 10
      .idea/misc.xml
  5. 17
      .idea/runConfigurations.xml
  6. 130
      app/src/main/java/com/ouxuan/oxface/MainActivity.java
  7. 6
      app/src/main/java/com/ouxuan/oxface/network/NetworkManager.java
  8. 17
      app/src/main/java/com/ouxuan/oxface/network/api/PadApiService.java
  9. 168
      app/src/main/java/com/ouxuan/oxface/network/debug/NetworkDebugLogger.java
  10. 66
      app/src/main/java/com/ouxuan/oxface/network/interceptor/NetworkDebugInterceptor.java
  11. 43
      app/src/main/java/com/ouxuan/oxface/network/utils/NetworkUtils.java
  12. 3
      gradle/wrapper/gradle-wrapper.properties

3
.idea/.gitignore

@ -0,0 +1,3 @@
# Default ignored files
/shelf/
/workspace.xml

6
.idea/AndroidProjectSystem.xml

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="AndroidProjectSystem">
<option name="providerId" value="com.android.tools.idea.GradleProjectSystem" />
</component>
</project>

10
.idea/migrations.xml

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectMigrations">
<option name="MigrateToGradleLocalJavaHome">
<set>
<option value="$PROJECT_DIR$" />
</set>
</option>
</component>
</project>

10
.idea/misc.xml

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="ProjectRootManager">
<output url="file://$PROJECT_DIR$/build/classes" />
</component>
<component name="ProjectType">
<option name="id" value="Android" />
</component>
</project>

17
.idea/runConfigurations.xml

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="RunConfigurationProducerService">
<option name="ignoredProducers">
<set>
<option value="com.intellij.execution.junit.AbstractAllInDirectoryConfigurationProducer" />
<option value="com.intellij.execution.junit.AllInPackageConfigurationProducer" />
<option value="com.intellij.execution.junit.PatternConfigurationProducer" />
<option value="com.intellij.execution.junit.TestInClassConfigurationProducer" />
<option value="com.intellij.execution.junit.UniqueIdConfigurationProducer" />
<option value="com.intellij.execution.junit.testDiscovery.JUnitTestDiscoveryConfigurationProducer" />
<option value="org.jetbrains.kotlin.idea.junit.KotlinJUnitRunConfigurationProducer" />
<option value="org.jetbrains.kotlin.idea.junit.KotlinPatternConfigurationProducer" />
</set>
</option>
</component>
</project>

130
app/src/main/java/com/ouxuan/oxface/MainActivity.java

@ -197,8 +197,13 @@ public class MainActivity extends AppCompatActivity {
@Override
public void onError(int errorCode, String errorMessage) {
// 登录失败显示错误信息
android.util.Log.e("MainActivity", "Login error - Code: " + errorCode + ", Message: " + errorMessage);
// 登录失败打印详细错误日志并显示错误信息
android.util.Log.e("MainActivity", "=== 登录接口请求异常 ===");
android.util.Log.e("MainActivity", "Error Code: " + errorCode);
android.util.Log.e("MainActivity", "Error Message: " + errorMessage);
android.util.Log.e("MainActivity", "===========================");
// 显示Toast错误信息
showToast("登录失败: " + errorMessage);
}
@ -207,13 +212,6 @@ public class MainActivity extends AppCompatActivity {
// 请求完成
}
});
// 如果需要保留原来的测试登录逻辑可以保留下面的代码
// if (username.equals("admin") && password.equals("123456")) {
// showLoginSuccessDialog();
// } else {
// showToast("用户名或密码错误");
// }
}
/**
@ -467,50 +465,75 @@ public class MainActivity extends AppCompatActivity {
loadingAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinner.setAdapter(loadingAdapter);
// 调用API获取Pad列表
NetworkUtils.getPadList(new NetworkCallback<PadApiService.PadListResponse>() {
@Override
public void onStart() {
// 加载开始
}
// 调用API获取Pad列表传入登录时获取的stadium_iddevice_id和token
if (currentLoginData != null) {
int stadiumId = currentLoginData.getStadiumId();
String token = currentLoginData.getToken();
String deviceId = "ANDROID_" + android.provider.Settings.Secure.getString(
getContentResolver(), android.provider.Settings.Secure.ANDROID_ID);
@Override
public void onSuccess(PadApiService.PadListResponse data) {
// 加载成功更新下拉框数据
java.util.List<PadApiService.PadInfo> padList = data.getPadList();
java.util.List<String> padNames = new java.util.ArrayList<>();
padNames.add("请选择设备"); // 默认选项
if (padList != null && !padList.isEmpty()) {
for (PadApiService.PadInfo padInfo : padList) {
padNames.add(padInfo.getPadName() + " (" + padInfo.getStatus() + ")");
}
} else {
padNames.add("暂无可用设备");
android.util.Log.d("MainActivity", "Loading pad list with stadium_id: " + stadiumId +
", device_id: " + deviceId + ", token: " + (token != null ? "present" : "null"));
NetworkUtils.getPadList(stadiumId, deviceId, token, new NetworkCallback<PadApiService.PadListResponse>() {
@Override
public void onStart() {
// 加载开始
}
// 更新Spinner数据
ArrayAdapter<String> adapter = new ArrayAdapter<>(MainActivity.this,
android.R.layout.simple_spinner_item, padNames);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinner.setAdapter(adapter);
@Override
public void onSuccess(PadApiService.PadListResponse data) {
// 加载成功更新下拉框数据
java.util.List<PadApiService.PadInfo> padList = data.getPadList();
java.util.List<String> padNames = new java.util.ArrayList<>();
padNames.add("请选择设备"); // 默认选项
if (padList != null && !padList.isEmpty()) {
for (PadApiService.PadInfo padInfo : padList) {
padNames.add(padInfo.getPadName() + " (" + padInfo.getStatus() + ")");
}
} else {
padNames.add("暂无可用设备");
}
// 更新进入按钮的点击事件传入真实的Pad数据
updateEnterButtonClickListener(dialog, padList);
}
// 更新Spinner数据
ArrayAdapter<String> adapter = new ArrayAdapter<>(MainActivity.this,
android.R.layout.simple_spinner_item, padNames);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinner.setAdapter(adapter);
@Override
public void onError(int errorCode, String errorMessage) {
// 加载失败显示错误信息
String[] errorItems = {"加载失败,请重试"};
ArrayAdapter<String> errorAdapter = new ArrayAdapter<>(MainActivity.this,
android.R.layout.simple_spinner_item, errorItems);
errorAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinner.setAdapter(errorAdapter);
showToast("获取设备列表失败: " + errorMessage);
}
});
// 更新进入按钮的点击事件传入真实的Pad数据
updateEnterButtonClickListener(dialog, padList);
}
@Override
public void onError(int errorCode, String errorMessage) {
// 加载失败打印详细错误日志并显示错误信息
android.util.Log.e("MainActivity", "=== 获取设备列表接口请求异常 ===");
android.util.Log.e("MainActivity", "Error Code: " + errorCode);
android.util.Log.e("MainActivity", "Error Message: " + errorMessage);
android.util.Log.e("MainActivity", "================================");
// 显示错误信息
String[] errorItems = {"加载失败,请重试"};
ArrayAdapter<String> errorAdapter = new ArrayAdapter<>(MainActivity.this,
android.R.layout.simple_spinner_item, errorItems);
errorAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinner.setAdapter(errorAdapter);
showToast("获取设备列表失败: " + errorMessage);
}
});
} else {
// 如果没有登录数据显示错误
String[] errorItems = {"登录数据丢失,请重新登录"};
ArrayAdapter<String> errorAdapter = new ArrayAdapter<>(this,
android.R.layout.simple_spinner_item, errorItems);
errorAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinner.setAdapter(errorAdapter);
showToast("登录数据丢失,请重新登录");
}
}
/**
@ -530,7 +553,7 @@ public class MainActivity extends AppCompatActivity {
showToast("请选择设备");
} else if (padList != null && selectedPosition <= padList.size()) {
// 获取选中的Pad信息
PadApiService.PadInfo selectedPad = padList.get(selectedPosition - 1); // 减1因为第0个是请选择设备
PadApiService.PadInfo selectedPad = padList.get(selectedPosition - 1); // 减1因为第0个是"请选择设备"
// 调用Pad选择API
selectPadAndEnter(dialog, buttonEnter, selectedPad);
@ -574,7 +597,14 @@ public class MainActivity extends AppCompatActivity {
@Override
public void onError(int errorCode, String errorMessage) {
// 选择失败
// 选择失败打印详细错误日志并显示错误信息
android.util.Log.e("MainActivity", "=== 设备选择接口请求异常 ===");
android.util.Log.e("MainActivity", "Error Code: " + errorCode);
android.util.Log.e("MainActivity", "Error Message: " + errorMessage);
android.util.Log.e("MainActivity", "Selected Pad: " + (selectedPad != null ? selectedPad.getPadName() : "null"));
android.util.Log.e("MainActivity", "==============================");
// 显示错误信息
showToast("选择设备失败: " + errorMessage);
// 恢复按钮状态

6
app/src/main/java/com/ouxuan/oxface/network/NetworkManager.java

@ -8,6 +8,7 @@ import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.ouxuan.oxface.network.callback.NetworkCallback;
import com.ouxuan.oxface.network.interceptor.HeaderInterceptor;
import com.ouxuan.oxface.network.interceptor.NetworkDebugInterceptor;
import com.ouxuan.oxface.network.model.ApiResponse;
import java.util.concurrent.TimeUnit;
@ -68,6 +69,11 @@ public class NetworkManager {
.writeTimeout(NetworkConfig.WRITE_TIMEOUT, TimeUnit.SECONDS)
.addInterceptor(new HeaderInterceptor(context));
// 添加网络调试拦截器优先级最高在所有拦截器之前
if (NetworkConfig.ENABLE_LOG) {
builder.addInterceptor(new NetworkDebugInterceptor());
}
// 添加日志拦截器仅在Debug模式下
if (NetworkConfig.ENABLE_LOG) {
HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor();

17
app/src/main/java/com/ouxuan/oxface/network/api/PadApiService.java

@ -27,19 +27,30 @@ public interface PadApiService {
/**
* 获取Pad列表
* 对应旧接口: /v3/pad/list
* @param stadiumId 场馆ID必需
* @param deviceId 设备ID必需
* @param token 访问令牌必需
* @return Pad列表响应
*/
@GET("v3/pad/list")
Call<ApiResponse<PadListResponse>> padList();
Call<ApiResponse<PadListResponse>> padList(@Query("stadium_id") int stadiumId,
@Query("device_id") String deviceId,
@Query("token") String token);
/**
* 获取Pad列表带查询参数
* 获取Pad列表带额外查询参数
* @param stadiumId 场馆ID必需
* @param deviceId 设备ID必需
* @param token 访问令牌必需
* @param userId 用户ID可选
* @param status 状态筛选可选
* @return Pad列表响应
*/
@GET("v3/pad/list")
Call<ApiResponse<PadListResponse>> padList(@Query("userId") String userId,
Call<ApiResponse<PadListResponse>> padList(@Query("stadium_id") int stadiumId,
@Query("device_id") String deviceId,
@Query("token") String token,
@Query("userId") String userId,
@Query("status") String status);
/**

168
app/src/main/java/com/ouxuan/oxface/network/debug/NetworkDebugLogger.java

@ -0,0 +1,168 @@
package com.ouxuan.oxface.network.debug;
import android.util.Log;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.ResponseBody;
import okio.Buffer;
import java.io.IOException;
import java.net.URLDecoder;
/**
* 网络请求调试日志工具类
* 按照指定格式打印请求和响应信息
*/
public class NetworkDebugLogger {
private static final String TAG = "jsLog";
private static final boolean ENABLE_DEBUG = true; // 调试开关
/**
* 打印网络请求调试信息
* @param request 请求对象
* @param response 响应对象
* @param responseBody 响应体内容
* @param tag 请求标识标签 [list][login]
*/
public static void logNetworkRequest(Request request, Response response, String responseBody, String tag) {
if (!ENABLE_DEBUG) {
return;
}
try {
// 获取请求URL
String url = request.url().toString();
// 获取请求体数据
String requestData = getRequestDataString(request);
// 打印请求信息
Log.e(TAG, "请求 Data: ");
if (requestData != null && !requestData.isEmpty()) {
Log.e(TAG, requestData);
} else {
// 对于GET请求打印查询参数
String queryParams = getQueryParametersAsJson(request);
if (queryParams != null && !queryParams.isEmpty()) {
Log.e(TAG, queryParams);
} else {
Log.e(TAG, "{}");
}
}
Log.e(TAG, " URL:");
Log.e(TAG, url);
// 打印响应信息
Log.e(TAG, " 服务端返回:");
if (responseBody != null && !responseBody.isEmpty()) {
Log.e(TAG, responseBody);
} else {
Log.e(TAG, "空响应");
}
// 打印结束标识
Log.e(TAG, " <<-------------------- " + tag + "[log] ↑↑↑");
} catch (Exception e) {
Log.e(TAG, "网络调试日志打印失败: " + e.getMessage());
}
}
/**
* 获取请求数据包括请求体和查询参数
* @param request 请求对象
* @return 请求数据字符串
*/
private static String getRequestDataString(Request request) {
try {
// 优先获取请求体内容
if (request.body() != null) {
Buffer buffer = new Buffer();
request.body().writeTo(buffer);
String requestBody = buffer.readUtf8();
if (requestBody != null && !requestBody.trim().isEmpty()) {
return requestBody;
}
}
// 如果没有请求体则获取查询参数
return getQueryParametersAsJson(request);
} catch (Exception e) {
Log.e(TAG, "获取请求数据失败: " + e.getMessage());
return "{}";
}
}
/**
* 获取查询参数并格式化为JSON样式
* @param request 请求对象
* @return 查询参数JSON字符串
*/
private static String getQueryParametersAsJson(Request request) {
try {
String url = request.url().toString();
if (url.contains("?")) {
String queryString = url.substring(url.indexOf("?") + 1);
// 将查询参数格式化为JSON样式
StringBuilder jsonStyle = new StringBuilder("{");
String[] params = queryString.split("&");
for (int i = 0; i < params.length; i++) {
String[] keyValue = params[i].split("=");
if (keyValue.length == 2) {
String key = URLDecoder.decode(keyValue[0], "UTF-8");
String value = URLDecoder.decode(keyValue[1], "UTF-8");
jsonStyle.append("\"").append(key).append("\":");
// 尝试判断是否为数字
try {
Integer.parseInt(value);
jsonStyle.append(value);
} catch (NumberFormatException e) {
jsonStyle.append("\"").append(value).append("\"");
}
if (i < params.length - 1) {
jsonStyle.append(",");
}
}
}
jsonStyle.append("}");
return jsonStyle.toString();
}
return "{}";
} catch (Exception e) {
Log.e(TAG, "获取查询参数失败: " + e.getMessage());
return "{}";
}
}
/**
* 打印简化的网络请求信息只有基本信息
* @param method 请求方法
* @param url 请求URL
* @param responseCode 响应码
* @param tag 请求标识标签
*/
public static void logSimpleRequest(String method, String url, int responseCode, String tag) {
if (!ENABLE_DEBUG) {
return;
}
Log.d(TAG, String.format("%s %s - Response: %d %s", method, url, responseCode, tag));
}
/**
* 设置调试开关
* @param enabled 是否启用调试
*/
public static void setDebugEnabled(boolean enabled) {
// 这里可以动态控制调试开关
// 实际项目中可以通过配置文件或BuildConfig控制
}
}

66
app/src/main/java/com/ouxuan/oxface/network/interceptor/NetworkDebugInterceptor.java

@ -0,0 +1,66 @@
package com.ouxuan.oxface.network.interceptor;
import com.ouxuan.oxface.network.debug.NetworkDebugLogger;
import java.io.IOException;
import okhttp3.Interceptor;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.ResponseBody;
import okio.Buffer;
/**
* 网络调试拦截器
* 自动捕获所有网络请求和响应使用NetworkDebugLogger打印调试信息
*/
public class NetworkDebugInterceptor implements Interceptor {
@Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
// 执行请求
Response response = chain.proceed(request);
// 获取响应体内容
String responseBodyString = null;
if (response.body() != null) {
// 读取响应体
ResponseBody responseBody = response.body();
Buffer buffer = new Buffer();
responseBody.source().readAll(buffer);
responseBodyString = buffer.clone().readUtf8();
// 重新创建ResponseBody因为原来的已经被消费了
ResponseBody newResponseBody = ResponseBody.create(
responseBody.contentType(),
responseBodyString
);
response = response.newBuilder().body(newResponseBody).build();
}
// 根据URL路径确定调试标签
String debugTag = getDebugTag(request.url().toString());
// 打印调试信息
NetworkDebugLogger.logNetworkRequest(request, response, responseBodyString, debugTag);
return response;
}
/**
* 根据请求URL确定调试标签
* @param url 请求URL
* @return 调试标签
*/
private String getDebugTag(String url) {
if (url.contains("/v3/pad/login")) {
return "[login]";
} else if (url.contains("/v3/pad/list")) {
return "[list]";
} else if (url.contains("/v3/pad/select")) {
return "[select]";
} else {
return "[unknown]";
}
}
}

43
app/src/main/java/com/ouxuan/oxface/network/utils/NetworkUtils.java

@ -226,6 +226,20 @@ public class NetworkUtils {
return networkManager;
}
/**
* 打印API错误日志当code != 0时
* @param apiName API名称
* @param errorCode 错误代码
* @param errorMessage 错误消息
*/
private static void logApiError(String apiName, int errorCode, String errorMessage) {
android.util.Log.e("NetworkUtils", "===== API请求异常 =====");
android.util.Log.e("NetworkUtils", "API Name: " + apiName);
android.util.Log.e("NetworkUtils", "Error Code: " + errorCode + " (code != 0 表示请求异常)");
android.util.Log.e("NetworkUtils", "Error Message: " + errorMessage);
android.util.Log.e("NetworkUtils", "=============================");
}
// ==================== Pad相关API调用方法 ====================
/**
@ -263,6 +277,8 @@ public class NetworkUtils {
android.util.Log.d("NetworkUtils", "Calling onSuccess with data: " + apiResponse.getData());
callback.onSuccess(apiResponse.getData());
} else {
// 打印详细的错误日志
logApiError("PadLogin", apiResponse.getCode(), apiResponse.getMessage());
android.util.Log.d("NetworkUtils", "Calling onError - Code: " + apiResponse.getCode() + ", Message: " + apiResponse.getMessage());
callback.onError(apiResponse.getCode(), apiResponse.getMessage());
}
@ -287,16 +303,20 @@ public class NetworkUtils {
/**
* 获取Pad列表
* @param stadiumId 场馆ID必需
* @param deviceId 设备ID必需
* @param token 访问令牌必需
* @param callback 回调接口
*/
public static void getPadList(NetworkCallback<PadApiService.PadListResponse> callback) {
public static void getPadList(int stadiumId, String deviceId, String token,
NetworkCallback<PadApiService.PadListResponse> callback) {
if (padApiService == null) {
callback.onError(-1, "NetworkUtils未初始化,请先调用init()方法");
return;
}
callback.onStart();
padApiService.padList().enqueue(new Callback<ApiResponse<PadApiService.PadListResponse>>() {
padApiService.padList(stadiumId, deviceId, token).enqueue(new Callback<ApiResponse<PadApiService.PadListResponse>>() {
@Override
public void onResponse(Call<ApiResponse<PadApiService.PadListResponse>> call,
Response<ApiResponse<PadApiService.PadListResponse>> response) {
@ -307,6 +327,8 @@ public class NetworkUtils {
if (apiResponse.isSuccess()) {
callback.onSuccess(apiResponse.getData());
} else {
// 打印详细的错误日志
logApiError("getPadList", apiResponse.getCode(), apiResponse.getMessage());
callback.onError(apiResponse.getCode(), apiResponse.getMessage());
}
} else {
@ -328,12 +350,15 @@ public class NetworkUtils {
}
/**
* 获取Pad列表带查询参数
* @param userId 用户ID
* @param status 状态筛选
* 获取Pad列表带额外查询参数
* @param stadiumId 场馆ID必需
* @param deviceId 设备ID必需
* @param token 访问令牌必需
* @param userId 用户ID可选
* @param status 状态筛选可选
* @param callback 回调接口
*/
public static void getPadList(String userId, String status,
public static void getPadList(int stadiumId, String deviceId, String token, String userId, String status,
NetworkCallback<PadApiService.PadListResponse> callback) {
if (padApiService == null) {
callback.onError(-1, "NetworkUtils未初始化,请先调用init()方法");
@ -341,7 +366,7 @@ public class NetworkUtils {
}
callback.onStart();
padApiService.padList(userId, status).enqueue(new Callback<ApiResponse<PadApiService.PadListResponse>>() {
padApiService.padList(stadiumId, deviceId, token, userId, status).enqueue(new Callback<ApiResponse<PadApiService.PadListResponse>>() {
@Override
public void onResponse(Call<ApiResponse<PadApiService.PadListResponse>> call,
Response<ApiResponse<PadApiService.PadListResponse>> response) {
@ -352,6 +377,8 @@ public class NetworkUtils {
if (apiResponse.isSuccess()) {
callback.onSuccess(apiResponse.getData());
} else {
// 打印详细的错误日志
logApiError("getPadList(带参数)", apiResponse.getCode(), apiResponse.getMessage());
callback.onError(apiResponse.getCode(), apiResponse.getMessage());
}
} else {
@ -400,6 +427,8 @@ public class NetworkUtils {
if (apiResponse.isSuccess()) {
callback.onSuccess(apiResponse.getData());
} else {
// 打印详细的错误日志
logApiError("selectPad", apiResponse.getCode(), apiResponse.getMessage());
callback.onError(apiResponse.getCode(), apiResponse.getMessage());
}
} else {

3
gradle/wrapper/gradle-wrapper.properties

@ -1,5 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-9.0-bin.zip
distributionUrl=https\://mirrors.cloud.tencent.com/gradle/gradle-9.0-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
Loading…
Cancel
Save