Blackhole Vpn sets up a vpn client for prevent connections for selected apps.
Android has VpnManager api and it is possible to create a vpn connection for specified apps. With this plugin, selected apps network will managed by a dummy vpn which don't make any connection.
Does not require root.
- Android
Any PR for other platforms is appreciated
Firewall apps, data saving apps
This plugin uses
BIND_VPN_SERVICE
permission for setting up vpnservice.If you want to publish your app to Google Play Store you need to document the use of vpnservice at store listing. See more at here
No need to edit AndroidManifest.xml
Make sure to minimum sdk version is 21 or above in android/app/build.gradle
defaultConfig {
minSdkVersion 21
}
All the methods below are available after importing the package and getting the instance of the plugin.
import 'package:blackhole_vpn/blackhole_vpn.dart';
final blackholeVpn = BlackholeVpnPlatform.instance;
You have to know package names for the apps do you want to use the blackhole vpn. Example app uses android_package_manager plugin.
//Request permission then start blackhole vpn for specified apps
await blackholeVpn.runVpnService(["com.google.youtube","com.android.chrome"]);
Specified apps will not able to connect internet and local network. Returns
bool
whether the user accepted permission.
await blackholeVpn.isActive(); //Returns bool
await blackholeVpn.stopVpn(); //Alternatively user can stop it via vpn notification or system settings
Android let users to start or stop vpn service via vpn notification or system settings. You can track vpn state changes with specified methods.
-
Using
VpnStateObserver
widgetVpnStateObserver( builder: (isActive) => switch (isActive) { true => Text("Blackhole vpn active"), false => Text( "Blackhole vpn not active"), null => Text("Loading") })
-
Listening
vpnStatusStream
blackholeVpn.vpnStatusStream.listen((isActive) { if (isActive) { print("Blackhole vpn active"); } else { print("Blackhole vpn not active"); } });
vpnStatusStream
is a broadcast stream, it can be listened multiple times. It may not emit any value if vpn state is not changed. Checking state withisActive()
before listen is recommended.
import 'package:flutter_test/flutter_test.dart';
import 'package:blackhole_vpn/blackhole_vpn.dart';
import 'package:blackhole_vpn/blackhole_vpn_platform_interface.dart';
import 'package:plugin_platform_interface/plugin_platform_interface.dart';
class TestBlackholeVpnPlatform
with MockPlatformInterfaceMixin
implements BlackholeVpnPlatform {
var _isActive = false;
@override
Future<bool> runVpnService(_) async {
_isActive = true;
return true;
}
@override
Future<bool> isActive() async {
return _isActive;
}
@override
Future<void> stopVpnService() async {
_isActive = false;
}
@override
Stream<bool> getVpnStatusStream() => throw UnimplementedError();
}
void main() {
BlackholeVpnPlatform.instance = TestBlackholeVpnPlatform();
test('test runVpnService', () async {
final blackholeVpn = BlackholeVpnPlatform.instance;
expect(await blackholeVpn.runVpnService([]), isTrue);
expect(await blackholeVpn.isActive(), isTrue);
});
}