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 |
|||
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 |
Write
Preview
Loading…
Cancel
Save
Reference in new issue