Connect to the OpenVPN service using Flutter. Contributions through issues and pull requests are highly appreciated!
Include the following code in the onActivityResult
method of MainActivity.java
(if you are using Java):
OpenVPNFlutterPlugin.connectWhileGranted(requestCode == 24 && resultCode == RESULT_OK);
The complete method should look like this:
...
import id.laskarmedia.openvpn_flutter.OpenVPNFlutterPlugin;
...
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
OpenVPNFlutterPlugin.connectWhileGranted(requestCode == 24 && resultCode == RESULT_OK);
super.onActivityResult(requestCode, resultCode, data);
}
Include the following code in the onActivityResult
method of MainActivity.kt
(if you are using Kotlin):
OpenVPNFlutterPlugin.connectWhileGranted(requestCode == 24 && resultCode == RESULT_OK);
The complete method should look like this:
...
import id.laskarmedia.openvpn_flutter.OpenVPNFlutterPlugin
...
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
OpenVPNFlutterPlugin.connectWhileGranted(requestCode == 24 && resultCode == RESULT_OK)
super.onActivityResult(requestCode, resultCode, data)
}
If you encounter issues with the app not connecting using the latest Flutter SDK, apply the following quick fix:
Ensure that you include the following attribute within the <application>
tag in your AndroidManifest.xml
file:
<application
...
android:extractNativeLibs="true"
...>
</application>
Add the App Groups
and Network Extensions
capabilities to the Runner's target. Refer to the image below for detailed instructions:
Click the +
button on the bottom left, choose NETWORK EXTENSION
, and follow the instructions in the image below:
Add the same capabilities to the VPNExtension as you did for the Runner's target:
Add the following lines to your Podfile (ios/Podfile
):
target 'VPNExtension' do
use_frameworks!
pod 'OpenVPNAdapter', :git => 'https://github.com/ss-abramchuk/OpenVPNAdapter.git', :tag => '0.8.0'
end
Open VPNExtension > PacketTunnelProvider.swift
and copy-paste the script from PacketTunnelProvider.swift.
You must use iOS devices instead of the simulator to connect.
Before starting, initialize the OpenVPN plugin:
late OpenVPN openvpn;
@override
void initState() {
openvpn = OpenVPN(onVpnStatusChanged: _onVpnStatusChanged, onVpnStageChanged: _onVpnStageChanged);
openvpn.initialize(
groupIdentifier: "GROUP_IDENTIFIER", ///Example 'group.com.laskarmedia.vpn'
providerBundleIdentifier: "NETWORK_EXTENSION_IDENTIFIER", ///Example 'id.laskarmedia.openvpnFlutterExample.VPNExtension'
localizedDescription: "LOCALIZED_DESCRIPTION" ///Example 'Laskarmedia VPN'
);
}
void _onVpnStatusChanged(VPNStatus? vpnStatus){
setState((){
this.status = vpnStatus;
});
}
void _onVpnStageChanged(VPNStage? stage){
setState((){
this.stage = stage;
});
}
void connect() {
openvpn.connect(
config,
name,
username: username,
password: password,
bypassPackages: [],
// In iOS connection can get stuck in "connecting" if this flag is "false".
// Solution is to switch it to "true".
certIsRequired: false,
);
}
void disconnect(){
openvpn.disconnect();
}
- You can use app bundles to publish the app.
- Add the following to your files in the
android
folder (special thanks to #10). Otherwise, the connection may not be established in some cases and will silently report "disconnected" when trying to connect. This is likely related to some symbols being stripped by Google Play.
gradle.properties > android.bundle.enableUncompressedNativeLibs=false
AndroidManifest > android:extractNativeLibs="true" in the application tag
Add the following inside the android
tag in app/build.gradle
:
android {
...
//from here ======
lintOptions {
disable 'InvalidPackage'
checkReleaseBuilds false
}
packagingOptions {
jniLibs {
useLegacyPackaging = true
}
}
bundle {
language {
enableSplit = false
}
density {
enableSplit = false
}
abi {
enableSplit = false
}
}
//to here
...
}
As the plugin shows notifications for connection status and connection details, you must request permission using third-party packages.
Example using permission_handler:
///Put it anywhere you wish, like once you initialize the VPN or pre-connect to the server
Permission.notification.isGranted.then((_) {
if (!_) Permission.notification.request();
});
- View Apple Guidelines relating to VPN.
- This plugin DOES use encryption, but it uses exempt encryptions.
- openvpn_flutter for this plugin
- ics-openvpn for the Android engine
- OpenVPNAdapter for the iOS engine
If you appreciate my work, don't forget to give a thumbs up or support me with a cup of coffee.