12 changed files with 417 additions and 60 deletions
-
3.idea/.gitignore
-
6.idea/AndroidProjectSystem.xml
-
10.idea/migrations.xml
-
10.idea/misc.xml
-
17.idea/runConfigurations.xml
-
130app/src/main/java/com/ouxuan/oxface/MainActivity.java
-
6app/src/main/java/com/ouxuan/oxface/network/NetworkManager.java
-
17app/src/main/java/com/ouxuan/oxface/network/api/PadApiService.java
-
168app/src/main/java/com/ouxuan/oxface/network/debug/NetworkDebugLogger.java
-
66app/src/main/java/com/ouxuan/oxface/network/interceptor/NetworkDebugInterceptor.java
-
43app/src/main/java/com/ouxuan/oxface/network/utils/NetworkUtils.java
-
3gradle/wrapper/gradle-wrapper.properties
@ -0,0 +1,3 @@ |
|||||
|
# Default ignored files |
||||
|
/shelf/ |
||||
|
/workspace.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> |
@ -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> |
@ -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> |
@ -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> |
@ -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控制 |
||||
|
} |
||||
|
} |
@ -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]"; |
||||
|
} |
||||
|
} |
||||
|
} |
@ -1,5 +1,6 @@ |
|||||
distributionBase=GRADLE_USER_HOME |
distributionBase=GRADLE_USER_HOME |
||||
distributionPath=wrapper/dists |
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 |
zipStoreBase=GRADLE_USER_HOME |
||||
zipStorePath=wrapper/dists |
zipStorePath=wrapper/dists |
Write
Preview
Loading…
Cancel
Save
Reference in new issue