diff --git a/app/src/main/assets/v2ray/arm64-v8a/config.json b/app/src/main/assets/v2ray/arm64-v8a/config.json index 93d0e0f..f536d0d 100644 --- a/app/src/main/assets/v2ray/arm64-v8a/config.json +++ b/app/src/main/assets/v2ray/arm64-v8a/config.json @@ -119,5 +119,6 @@ "outboundTag": "direct" } ] - } + }, + "tun_address": "172.19.0.1" } \ No newline at end of file diff --git a/app/src/main/java/com/example/studyapp/config/ConfigLoader.java b/app/src/main/java/com/example/studyapp/config/ConfigLoader.java new file mode 100644 index 0000000..24c46f6 --- /dev/null +++ b/app/src/main/java/com/example/studyapp/config/ConfigLoader.java @@ -0,0 +1,48 @@ +package com.example.studyapp.config; + +import android.content.Context; + +import org.json.JSONException; +import org.json.JSONObject; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStreamReader; + +public class ConfigLoader { + + // 从 assets 中读取 JSON 文件并解析 + public static String getTunnelAddress() { + String jsonStr; + // 获取应用私有目录的文件路径 + File configFile = new File("/data/v2ray/config.json"); + + // 检查文件是否存在 + if (!configFile.exists()) { + return "172.19.0.1"; // 返回默认地址 + } + + try (BufferedReader reader = new BufferedReader( + new InputStreamReader(new FileInputStream(configFile)))) { + StringBuilder stringBuilder = new StringBuilder(); + String line; + while ((line = reader.readLine()) != null) { + stringBuilder.append(line); + } + jsonStr = stringBuilder.toString(); + + // 解析 JSON + JSONObject jsonObject = new JSONObject(jsonStr); + return jsonObject.optString("tun_address", "172.19.0.1"); + } catch (FileNotFoundException e) { + e.printStackTrace(); + return "172.19.0.1"; + } catch (IOException | JSONException e) { + e.printStackTrace(); + return "172.19.0.1"; + } + } +} diff --git a/app/src/main/java/com/example/studyapp/proxy/CustomVpnService.java b/app/src/main/java/com/example/studyapp/proxy/CustomVpnService.java index d7c196d..babb1c7 100644 --- a/app/src/main/java/com/example/studyapp/proxy/CustomVpnService.java +++ b/app/src/main/java/com/example/studyapp/proxy/CustomVpnService.java @@ -5,6 +5,7 @@ import android.net.VpnService; import android.os.ParcelFileDescriptor; import android.util.Log; +import com.example.studyapp.config.ConfigLoader; import com.example.studyapp.utils.V2rayUtil; import java.io.BufferedReader; @@ -22,9 +23,8 @@ import java.util.List; public class CustomVpnService extends VpnService { - private static final String TUN_ADDRESS = "172.19.0.1"; // TUN 的 IP 地址 + private static final String TUN_ADDRESS = ConfigLoader.getTunnelAddress(); // TUN 的 IP 地址 private static final int PREFIX_LENGTH = 28; // 子网掩码 - private static final int MAX_RETRY = 5; private ParcelFileDescriptor vpnInterface; // TUN 接口描述符 diff --git a/app/src/main/java/com/example/studyapp/utils/V2rayUtil.java b/app/src/main/java/com/example/studyapp/utils/V2rayUtil.java index d25cf5f..ac93430 100644 --- a/app/src/main/java/com/example/studyapp/utils/V2rayUtil.java +++ b/app/src/main/java/com/example/studyapp/utils/V2rayUtil.java @@ -10,6 +10,7 @@ import java.io.IOException; import java.io.InputStream; public class V2rayUtil { + private static File v2rayConfig,v2rayBinary; public static void startV2Ray(Context context) { try { @@ -19,10 +20,6 @@ public class V2rayUtil { return; } - // 获取文件路径 - File v2rayBinary = new File(context.getCodeCacheDir(), "v2ray"); - File v2rayConfig = new File(context.getCodeCacheDir(), "config.json"); - // 构建命令 ProcessBuilder builder = new ProcessBuilder(v2rayBinary.getAbsolutePath(), "-config", v2rayConfig.getAbsolutePath()).redirectErrorStream(true); @@ -48,18 +45,18 @@ public class V2rayUtil { try { // 检查并复制 v2ray 可执行文件 String abi = Build.SUPPORTED_ABIS[0]; // 获取当前设备支持的 ABI 架构 - File binaryOutputFile = new File(context.getCodeCacheDir(), "v2ray"); + v2rayBinary = new File(context.getCodeCacheDir(), "v2ray"); - if (!binaryOutputFile.exists()) { + if (!v2rayBinary.exists()) { InputStream binaryInputStream = context.getAssets().open("v2ray/" + abi + "/v2ray"); - FileOutputStream binaryOutputStream = new FileOutputStream(binaryOutputFile); + FileOutputStream binaryOutputStream = new FileOutputStream(v2rayBinary); try { byte[] buffer = new byte[1024]; int length; while ((length = binaryInputStream.read(buffer)) > 0) { binaryOutputStream.write(buffer, 0, length); } - Log.i("V2Ray", "Copied v2ray binary to: " + binaryOutputFile.getAbsolutePath()); + Log.i("V2Ray", "Copied v2ray binary to: " + v2rayBinary.getAbsolutePath()); } catch (Exception e) { Log.e("V2rayUtil", "Failed to copy v2ray binary", e); return false; @@ -68,12 +65,12 @@ public class V2rayUtil { binaryOutputStream.close(); } } - binaryOutputFile.setExecutable(true, false); - binaryOutputFile.setReadable(true, false); - binaryOutputFile.setWritable(true, false); + v2rayBinary.setExecutable(true, false); + v2rayBinary.setReadable(true, false); + v2rayBinary.setWritable(true, false); // 检查文件是否已经具有可执行权限 - if (!binaryOutputFile.canExecute()) { + if (!v2rayBinary.canExecute()) { Log.e("V2rayUtil", "Binary file does not have execute permission. Aborting start."); return false; } @@ -81,18 +78,18 @@ public class V2rayUtil { // 检查并复制 config.json 文件 - File configFile = new File(context.getCodeCacheDir(), "config.json"); + v2rayConfig = new File("/data/v2ray/config.json"); - if (!configFile.exists()) { + if (!v2rayConfig.exists()) { InputStream configInputStream = context.getAssets().open("v2ray/" + abi + "/config.json"); - FileOutputStream configOutputStream = new FileOutputStream(configFile); + FileOutputStream configOutputStream = new FileOutputStream(v2rayConfig); try { byte[] buffer = new byte[1024]; int length; while ((length = configInputStream.read(buffer)) > 0) { configOutputStream.write(buffer, 0, length); } - Log.i("V2Ray", "Copied v2ray config.json to: " + configFile.getAbsolutePath()); + Log.i("V2Ray", "Copied v2ray config.json to: " + v2rayConfig.getAbsolutePath()); } catch (Exception e) { Log.e("V2rayUtil", "Failed to copy config.json", e); return false; @@ -101,8 +98,8 @@ public class V2rayUtil { configOutputStream.close(); } } - configFile.setReadable(true, false); - configFile.setWritable(true, false); + v2rayConfig.setReadable(true, false); + v2rayConfig.setWritable(true, false); return true; } catch (IOException e) {