Skip to content

Commit

Permalink
调整安卓端逻辑
Browse files Browse the repository at this point in the history
  • Loading branch information
vnt-dev committed Jun 1, 2024
1 parent 7a30e64 commit c424aa4
Show file tree
Hide file tree
Showing 22 changed files with 953 additions and 497 deletions.
2 changes: 1 addition & 1 deletion android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<application
android:name="${applicationName}"
android:icon="@mipmap/ic_launcher"
android:label="vnt_app">
android:label="VNT">
<service
android:name=".vpn.MyVpnService"
android:exported="true"
Expand Down
76 changes: 34 additions & 42 deletions android/app/src/main/java/top/wherewego/vnt_app/MainActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import android.content.Intent;
import android.net.VpnService;
import android.os.Bundle;

import androidx.annotation.NonNull;

Expand All @@ -20,30 +21,39 @@ public class MainActivity extends FlutterActivity {
private static final String CHANNEL = "top.wherewego.vnt/vpn";
private static final int VPN_REQUEST_CODE = 1;
private static final String TAG = "MainActivity";
private MethodChannel.Result pendingResult;
private DeviceConfig pendingConfig;
public static MethodChannel channel;

@Override
public void configureFlutterEngine(@NonNull FlutterEngine flutterEngine) {
super.configureFlutterEngine(flutterEngine);
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}

new MethodChannel(flutterEngine.getDartExecutor().getBinaryMessenger(), CHANNEL)
.setMethodCallHandler(
(call, result) -> {
if (call.method.equals("startVpn")) {
try {
Map<String, Object> arguments = call.arguments();
DeviceConfig config = parseDeviceConfig(arguments);
startVpnService(config, result);
} catch (Exception e) {
result.error("VPN_ERROR", "Invalid DeviceConfig", e);
}

} else {
result.notImplemented();
}
@Override
public void configureFlutterEngine(@NonNull FlutterEngine flutterEngine) {
super.configureFlutterEngine(flutterEngine);
channel = new MethodChannel(flutterEngine.getDartExecutor().getBinaryMessenger(), CHANNEL);
channel.setMethodCallHandler((call, result) -> {
if (call.method.equals("startVpn")) {
try {
Map<String, Object> arguments = call.arguments();
DeviceConfig config = parseDeviceConfig(arguments);
startVpnService(config, result);
} catch (Exception e) {
result.error("VPN_ERROR", "Invalid DeviceConfig", e);
}
);
} else if (call.method.equals("stopVpn")) {
try {
MyVpnService.stopVpn();
} catch (Exception e) {
result.error("VPN_ERROR", "stopVpn", e);
}
} else {
result.notImplemented();
}
}
);

}

private DeviceConfig parseDeviceConfig(Map<String, Object> arguments) {
Expand All @@ -65,8 +75,8 @@ private DeviceConfig parseDeviceConfig(Map<String, Object> arguments) {
}

private void startVpnService(DeviceConfig config, MethodChannel.Result result) {
pendingResult = result;
pendingConfig = config;
MyVpnService.pendingResult = result;
MyVpnService.pendingConfig = config;
Intent intent = VpnService.prepare(this);
if (intent != null) {
startActivityForResult(intent, VPN_REQUEST_CODE);
Expand All @@ -79,29 +89,11 @@ private void startVpnService(DeviceConfig config, MethodChannel.Result result) {
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == VPN_REQUEST_CODE) {
if (resultCode == RESULT_OK) {
// 用户同意授权,继续启动 VPN 服务
if (pendingResult != null && pendingConfig != null) {
// 在新线程中启动 VPN 服务
new Thread(() -> {
try {
MyVpnService vpnService = new MyVpnService();
int fd = vpnService.startVpn(pendingConfig);
pendingResult.success(fd);
} catch (Exception e) {
pendingResult.error("VPN_ERROR", "Failed to start VPN", e);
}

pendingResult = null;
pendingConfig = null;
}).start();
}
Intent serviceIntent = new Intent(this, MyVpnService.class);
startService(serviceIntent);
} else {
// 用户拒绝授权,返回错误结果给 Flutter
if (pendingResult != null) {
pendingResult.error("VPN_ERROR", "User denied VPN authorization", null);
pendingResult = null;
pendingConfig = null;
}
MyVpnService.callError("User denied VPN authorization", null);
}
}
super.onActivityResult(requestCode, resultCode, data);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,25 @@ public Route(int destination, int netmask) {
this.destination = destination;
this.netmask = netmask;
}

@Override
public String toString() {
return "Route{" +
"destination=" + destination +
", netmask=" + netmask +
'}';
}
}

@Override
public String toString() {
return "DeviceConfig{" +
"virtualIp=" + virtualIp +
", virtualNetmask=" + virtualNetmask +
", virtualGateway=" + virtualGateway +
", mtu=" + mtu +
", externalRoute=" + externalRoute +
'}';
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,25 +1,78 @@
package top.wherewego.vnt_app.vpn;

import android.content.Intent;
import android.content.IntentFilter;
import android.net.ConnectivityManager;
import android.net.VpnService;
import android.os.ParcelFileDescriptor;
import android.system.OsConstants;
import android.util.Log;

import java.io.IOException;

import io.flutter.plugin.common.MethodChannel;
import top.wherewego.vnt_app.MainActivity;

public class MyVpnService extends VpnService {
private static final String TAG = "MyVpnService";
private ParcelFileDescriptor vpnInterface;
private static ParcelFileDescriptor vpnInterface;
private volatile static MyVpnService vpnService;

public static MethodChannel.Result pendingResult;
public static DeviceConfig pendingConfig;

public static synchronized void callSuccess(int fd) {
if (pendingResult != null) {
pendingResult.success(fd);
}
pendingResult = null;
}

public static synchronized void callError(String msg, Exception e) {
if (pendingResult != null) {
pendingResult.error("VPN_ERROR", msg, e);
}
pendingResult = null;
}

@Override
public synchronized int onStartCommand(Intent intent, int flags, int startId) {
vpnService = this;
new Thread(() -> {
try {
int fd = startVpn(pendingConfig);
callSuccess(fd);
} catch (Exception e) {
Log.e(TAG, "pendingConfig =" + pendingConfig.toString(), e);
callError("Failed to start VPN", e);
}
}).start();
return START_STICKY;
}

public int startVpn(DeviceConfig config) {
@Override
public void onCreate() {
// Listen for connectivity updates
IntentFilter ifConnectivity = new IntentFilter();
ifConnectivity.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
super.onCreate();
}

public static void stopVpn() {
MainActivity.channel.invokeMethod("stopVnt", null);
if (vpnService != null) {
vpnService.stopSelf();
}
if (vpnInterface != null) {
try {
vpnInterface.close();
} catch (IOException e) {
Log.e(TAG, "Error closing existing VPN interface", e);
}
}
}

private int startVpn(DeviceConfig config) {
Builder builder = new Builder();
String ip = IpUtils.intToIpAddress(config.virtualIp);
int prefixLength = IpUtils.subnetMaskToPrefixLength(config.virtualNetmask);
Expand All @@ -44,19 +97,12 @@ public int startVpn(DeviceConfig config) {
} catch (Exception e) {
Log.e(TAG, "Error establishing VPN interface", e);
}

return vpnInterface.getFd();
}

@Override
public void onDestroy() {
super.onDestroy();
if (vpnInterface != null) {
try {
vpnInterface.close();
} catch (IOException e) {
Log.e(TAG, "Error closing VPN interface", e);
}
}
stopVpn();
}
}
Binary file modified android/app/src/main/jniLibs/arm64-v8a/librust_lib_vnt_app.so
Binary file not shown.
Binary file modified android/app/src/main/jniLibs/armeabi-v7a/librust_lib_vnt_app.so
Binary file not shown.
Binary file modified android/app/src/main/jniLibs/x86/librust_lib_vnt_app.so
Binary file not shown.
Binary file modified android/app/src/main/jniLibs/x86_64/librust_lib_vnt_app.so
Binary file not shown.
9 changes: 8 additions & 1 deletion lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@ Future<void> main() async {
await appWindow.show();
});
}
if (Platform.isAndroid) {
VntAppCall.init();
}

runApp(const VntApp());
}
Expand Down Expand Up @@ -340,6 +343,10 @@ class _HomePageState extends State<HomePage> with WindowListener {
}
} else if (msg == 'stop') {
_closeVnt();
if (onece) {
onece = false;
Navigator.of(context).pop();
}
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('VNT服务停止')),
);
Expand Down Expand Up @@ -392,7 +399,7 @@ class _HomePageState extends State<HomePage> with WindowListener {
);
}
} else if (msg is RustConnectInfo) {
if (onece && msg.count > 60) {
if (onece && msg.count > BigInt.from(60)) {
onece = false;
Navigator.of(context).pop();
_closeVnt();
Expand Down
10 changes: 9 additions & 1 deletion lib/network_config_input_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -461,7 +461,15 @@ class _NetworkConfigInputPageState extends State<NetworkConfigInputPage> {
),
_buildDropdownField(
'加密算法',
['aes_gcm', 'aes_cbc', 'aes_ecb', 'sm4_cbc'],
[
'aes_gcm',
'chacha20_poly1305',
'chacha20',
'aes_cbc',
'aes_ecb',
'sm4_cbc',
'xor'
],
_encryptionAlgorithm,
(value) {
setState(() {
Expand Down
Loading

0 comments on commit c424aa4

Please sign in to comment.