diff --git a/android/build.gradle b/android/build.gradle
index 6dae8e6..afd1fdb 100644
--- a/android/build.gradle
+++ b/android/build.gradle
@@ -74,4 +74,5 @@ dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
// TODO: Remove when custom icon available.
implementation 'androidx.appcompat:appcompat:1.1.0'
+ implementation 'com.google.code.gson:gson:2.8.5'
}
diff --git a/android/src/main/AndroidManifest.xml b/android/src/main/AndroidManifest.xml
index 94aef01..ef3bd46 100644
--- a/android/src/main/AndroidManifest.xml
+++ b/android/src/main/AndroidManifest.xml
@@ -3,6 +3,7 @@
+
mService;
+ Context context;
- public RetryHandler(VpnStateService service) {
+ public RetryHandler(VpnStateService service, Context context) {
mService = new WeakReference<>(service);
+ this.context = context;
}
@Override
@@ -468,7 +474,7 @@ public void handleMessage(Message msg) {
}
sendMessageAtTime(obtainMessage(RETRY_MSG), next);
} else {
- mService.get().connect(null, false);
+ mService.get().connect(null, false, context);
}
}
}
diff --git a/android/src/main/kotlin/com/firekamp/flutter_unprotected_wifi/FlutterUnprotectedWifiPlugin.java b/android/src/main/kotlin/com/firekamp/flutter_unprotected_wifi/FlutterUnprotectedWifiPlugin.java
new file mode 100644
index 0000000..44b0008
--- /dev/null
+++ b/android/src/main/kotlin/com/firekamp/flutter_unprotected_wifi/FlutterUnprotectedWifiPlugin.java
@@ -0,0 +1,30 @@
+package com.firekamp.flutter_unprotected_wifi;
+
+import android.content.Context;
+import android.os.Bundle;
+import android.util.Log;
+
+import io.xdea.flutter_vpn.VpnStateHandler;
+
+public class FlutterUnprotectedWifiPlugin {
+ public final static String PLUGIN_TAG = "UnProtectedWiFiPlugin";
+
+ public static Bundle getConfigurationBundle(Context context) {
+ Bundle profileInfo = new Bundle();
+ try {
+ UnProtectedWiFiConfiguration unProtectedWiFiConfiguration = new UnProtectedWiFiConfiguration();
+ unProtectedWiFiConfiguration = unProtectedWiFiConfiguration.getSavedConfiguration(context);
+ profileInfo.putString("Address", unProtectedWiFiConfiguration.address);
+ profileInfo.putString("PackageName", unProtectedWiFiConfiguration.packageName);
+ profileInfo.putString("ActivityName", unProtectedWiFiConfiguration.activityClassName);
+ profileInfo.putString("UserName", unProtectedWiFiConfiguration.userName);
+ profileInfo.putString("DisplayName", unProtectedWiFiConfiguration.displayName);
+ profileInfo.putString("Password", unProtectedWiFiConfiguration.password);
+ profileInfo.putString("VpnType", unProtectedWiFiConfiguration.vpnType);
+ profileInfo.putInt("MTU", unProtectedWiFiConfiguration.mtu);
+ } catch (Exception e) {
+ Log.e(PLUGIN_TAG, e.getMessage());
+ }
+ return profileInfo;
+ }
+}
diff --git a/android/src/main/kotlin/com/firekamp/flutter_unprotected_wifi/NetworkChangeBroadcastReceiver.java b/android/src/main/kotlin/com/firekamp/flutter_unprotected_wifi/NetworkChangeBroadcastReceiver.java
new file mode 100644
index 0000000..48990ba
--- /dev/null
+++ b/android/src/main/kotlin/com/firekamp/flutter_unprotected_wifi/NetworkChangeBroadcastReceiver.java
@@ -0,0 +1,90 @@
+package com.firekamp.flutter_unprotected_wifi;
+
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.net.ConnectivityManager;
+import android.net.NetworkInfo;
+import android.os.Bundle;
+import android.util.Log;
+
+import org.strongswan.android.logic.VpnStateService;
+
+import io.xdea.flutter_vpn.VpnStateHandler;
+
+
+public class NetworkChangeBroadcastReceiver extends BroadcastReceiver {
+
+ private long lastCalledTime;
+ private VpnStateService vpnStateService = new VpnStateService();
+ private VpnStateService.VpnStateListener listener;
+ private UnProtectedWiFiConfiguration unProtectedWiFiConfiguration;
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+
+
+ final boolean isConnected = isConnected(context);
+ NetworkHelper networkHelper = new NetworkHelper();
+ NotificationHelper notificationHelper = new NotificationHelper();
+ boolean isSecuredWiFi = networkHelper.isSecuredWiFi(context);
+ unProtectedWiFiConfiguration = new UnProtectedWiFiConfiguration();
+ unProtectedWiFiConfiguration = unProtectedWiFiConfiguration.getSavedConfiguration(context);
+
+ if (VpnStateHandler.INSTANCE.getVpnStateService() != null) {
+ VpnStateService.State state = VpnStateHandler.INSTANCE.getVpnStateService().getState();
+ if ((state == VpnStateService.State.DISABLED || state == VpnStateService.State.CONNECTED) && isSecuredWiFi && !unProtectedWiFiConfiguration.isAutoConnect) {
+ notificationHelper.clearNotification(context);
+ }
+ if (state == VpnStateService.State.CONNECTED) {
+ return;
+ } else if (isConnected) {
+ SecuredWifiCheckForegroundService.showNotification(context, state, isSecuredWiFi, unProtectedWiFiConfiguration);
+ }
+ Log.i(FlutterUnprotectedWifiPlugin.PLUGIN_TAG, "getVpnStateService " + state);
+ } else {
+ Log.i(FlutterUnprotectedWifiPlugin.PLUGIN_TAG, "getVpnStateService is null");
+ }
+
+
+ SharedPreferenceHelper sharedPreferenceHelper = new SharedPreferenceHelper(context);
+ final boolean lastConnectedStatus = sharedPreferenceHelper.GetLastConnectionStatus();
+ if (lastConnectedStatus == isConnected) {
+ if (!SecuredWifiCheckForegroundService.connect)
+ return;
+ }
+ sharedPreferenceHelper.SaveLastConnectionStatus(isConnected);
+ if (isConnected) {
+
+ if (unProtectedWiFiConfiguration == null) {
+ Log.i(FlutterUnprotectedWifiPlugin.PLUGIN_TAG, "NetworkChangeBroadcastReceiver UnProtectedWiFiPlugin is not configured" + isConnected);
+ return;
+ }
+ Log.i(FlutterUnprotectedWifiPlugin.PLUGIN_TAG, "getVpnStateService new line");
+
+
+ if (VpnStateHandler.INSTANCE.getVpnStateService() != null) {
+ vpnStateService = VpnStateHandler.INSTANCE.getVpnStateService();
+ }
+
+
+ if (!isSecuredWiFi && unProtectedWiFiConfiguration.isAutoConnect) {
+ if (System.currentTimeMillis() - lastCalledTime <= 500) return;
+ lastCalledTime = System.currentTimeMillis();
+
+ Bundle profileInfo = FlutterUnprotectedWifiPlugin.getConfigurationBundle(context);
+ vpnStateService.connect(profileInfo, true, context);
+ }
+ Log.i(FlutterUnprotectedWifiPlugin.PLUGIN_TAG, "NetworkChangeBroadcastReceiver isSecuredWiFi: " + isSecuredWiFi);
+ }
+ Log.i(FlutterUnprotectedWifiPlugin.PLUGIN_TAG, "NetworkChangeBroadcastReceiver isConnected: " + isConnected);
+ }
+
+ public static boolean isConnected(Context context) {
+ ConnectivityManager cm = (ConnectivityManager)
+ context.getSystemService(Context.CONNECTIVITY_SERVICE);
+ NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
+ return activeNetwork != null && activeNetwork.isConnectedOrConnecting();
+ }
+}
diff --git a/android/src/main/kotlin/com/firekamp/flutter_unprotected_wifi/NetworkHelper.java b/android/src/main/kotlin/com/firekamp/flutter_unprotected_wifi/NetworkHelper.java
new file mode 100644
index 0000000..e328f73
--- /dev/null
+++ b/android/src/main/kotlin/com/firekamp/flutter_unprotected_wifi/NetworkHelper.java
@@ -0,0 +1,38 @@
+package com.firekamp.flutter_unprotected_wifi;
+
+import android.content.Context;
+import android.net.wifi.ScanResult;
+import android.net.wifi.WifiInfo;
+import android.net.wifi.WifiManager;
+import android.util.Log;
+
+import java.util.List;
+
+public class NetworkHelper {
+
+ public boolean isSecuredWiFi(Context context) {
+ boolean isSecured = false;
+ try {
+ WifiManager wifi = (WifiManager) context.getApplicationContext().getSystemService(Context.WIFI_SERVICE);
+ List networkList = wifi.getScanResults();
+ WifiInfo wi = wifi.getConnectionInfo();
+ String currentSSID = wi.getSSID();
+ if (networkList != null) {
+ for (ScanResult network : networkList) {
+ if (currentSSID.replace("\"", "").equals(network.SSID)) {
+ String capabilities = network.capabilities;
+ Log.d(FlutterUnprotectedWifiPlugin.PLUGIN_TAG, network.SSID + " capabilities : " + capabilities);
+ if (capabilities.contains("WPA2") || capabilities.contains("WPA") || capabilities.contains("WEP")) {
+ isSecured = true;
+ } else {
+ isSecured = false;
+ }
+ }
+ }
+ }
+ } catch (Exception e) {
+ Log.e(FlutterUnprotectedWifiPlugin.PLUGIN_TAG, e.getMessage());
+ }
+ return isSecured;
+ }
+}
diff --git a/android/src/main/kotlin/com/firekamp/flutter_unprotected_wifi/NotificationHelper.java b/android/src/main/kotlin/com/firekamp/flutter_unprotected_wifi/NotificationHelper.java
new file mode 100644
index 0000000..021e940
--- /dev/null
+++ b/android/src/main/kotlin/com/firekamp/flutter_unprotected_wifi/NotificationHelper.java
@@ -0,0 +1,103 @@
+package com.firekamp.flutter_unprotected_wifi;
+
+import android.app.Notification;
+import android.app.NotificationChannel;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
+import android.content.Context;
+import android.content.Intent;
+import android.content.res.Resources;
+import android.os.Build;
+import android.util.Log;
+
+import androidx.core.app.NotificationCompat;
+
+import java.util.Objects;
+
+import static android.content.Context.NOTIFICATION_SERVICE;
+import static com.firekamp.flutter_unprotected_wifi.SecuredWifiCheckForegroundService.CHANNEL_ID;
+
+public class NotificationHelper {
+ public final static int dissmissableNotificationId = 5;
+ public final static int serviceNotificationId = 2;
+
+ Notification getNotification(Context context, UnProtectedWiFiConfiguration unProtectedWiFiConfiguration, String title, String body) {
+ createNotificationChannel(context, title);
+ Intent notificationIntent = null;
+ try {
+ notificationIntent = new Intent(context, Class.forName(unProtectedWiFiConfiguration.activityClassName));
+ } catch (ClassNotFoundException e) {
+ e.printStackTrace();
+ }
+ PendingIntent pendingIntent = PendingIntent.getActivity(context,
+ 0, notificationIntent, 0);
+ Resources resources = context.getResources();
+ int resourceId = resources.getIdentifier(unProtectedWiFiConfiguration.notificationResourceId, "drawable", context.getPackageName());
+
+ Notification notification = new NotificationCompat.Builder(context, CHANNEL_ID)
+ .setContentTitle(title)
+ .setContentText(body)
+// .setSmallIcon(resourceId) // TODO: Need to get the appropriate notification icon.
+ .setSmallIcon(androidx.appcompat.R.drawable.abc_ic_star_black_48dp)
+ .setContentIntent(pendingIntent)
+ .build();
+ return notification;
+ }
+
+ private NotificationManager createNotificationChannel(Context context, String serviceNotificationTitle) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+ NotificationChannel serviceChannel = new NotificationChannel(
+ CHANNEL_ID,
+ serviceNotificationTitle,
+ NotificationManager.IMPORTANCE_DEFAULT
+ );
+ NotificationManager manager = context.getSystemService(NotificationManager.class);
+ manager.createNotificationChannel(serviceChannel);
+ return manager;
+ }
+ return null;
+ }
+
+ void updateServiceNotification(Context context, UnProtectedWiFiConfiguration unProtectedWiFiConfiguration, String title, String body) {
+ if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
+ NotificationManager notificationManager = createNotificationChannel(context, title);
+ if (notificationManager == null) {
+ notificationManager = context.getSystemService(NotificationManager.class);
+ }
+ final Notification notification = getNotification(context, unProtectedWiFiConfiguration, title, body);
+ notificationManager.notify(serviceNotificationId, notification);
+ }
+ }
+
+ void showNotification(int id, Context context, UnProtectedWiFiConfiguration unProtectedWiFiConfiguration, String title, String body) {
+ if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
+ NotificationManager notificationManager = createNotificationChannel(context, title);
+ if (notificationManager == null) {
+ notificationManager = context.getSystemService(NotificationManager.class);
+ }
+ final Notification notification = getNotification(context, unProtectedWiFiConfiguration, title, body);
+ notificationManager.notify(id, notification);
+ }
+ }
+
+ void showNotification(Context context, Notification notification) {
+ if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
+ NotificationManager notificationManager = createNotificationChannel(context, "UnProtectedWiFi");
+ if (notificationManager == null) {
+ notificationManager = context.getSystemService(NotificationManager.class);
+ }
+ notificationManager.notify(serviceNotificationId, notification);
+ }
+ }
+
+ void clearNotification(Context context) {
+ try {
+ NotificationManager mNotificationManager = (NotificationManager) context.getSystemService(NOTIFICATION_SERVICE);
+ mNotificationManager.cancel(dissmissableNotificationId);
+ } catch (Exception e) {
+ e.printStackTrace();
+ Log.e(FlutterUnprotectedWifiPlugin.PLUGIN_TAG, Objects.requireNonNull(e.getMessage()));
+ }
+ }
+}
+
diff --git a/android/src/main/kotlin/com/firekamp/flutter_unprotected_wifi/RebootBroadcastReceiver.java b/android/src/main/kotlin/com/firekamp/flutter_unprotected_wifi/RebootBroadcastReceiver.java
new file mode 100644
index 0000000..b4411b8
--- /dev/null
+++ b/android/src/main/kotlin/com/firekamp/flutter_unprotected_wifi/RebootBroadcastReceiver.java
@@ -0,0 +1,18 @@
+package com.firekamp.flutter_unprotected_wifi;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.util.Log;
+
+public class RebootBroadcastReceiver extends BroadcastReceiver {
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (Intent.ACTION_BOOT_COMPLETED.equals(intent.getAction())) {
+ Log.i(FlutterUnprotectedWifiPlugin.PLUGIN_TAG, "Rescheduling after boot!");
+ //TODO:Need to implement this one
+ //SecuredWifiCheckForegroundService.startService(context);
+ }
+ }
+}
diff --git a/android/src/main/kotlin/com/firekamp/flutter_unprotected_wifi/SecuredWifiCheckForegroundService.java b/android/src/main/kotlin/com/firekamp/flutter_unprotected_wifi/SecuredWifiCheckForegroundService.java
new file mode 100644
index 0000000..c14d564
--- /dev/null
+++ b/android/src/main/kotlin/com/firekamp/flutter_unprotected_wifi/SecuredWifiCheckForegroundService.java
@@ -0,0 +1,175 @@
+package com.firekamp.flutter_unprotected_wifi;
+
+import android.app.Notification;
+import android.app.Service;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.PackageManager;
+import android.net.ConnectivityManager;
+import android.os.IBinder;
+import android.util.Log;
+
+import androidx.annotation.Nullable;
+import androidx.core.content.ContextCompat;
+
+import org.strongswan.android.logic.VpnStateService;
+
+import java.util.Objects;
+
+import io.xdea.flutter_vpn.VpnStateHandler;
+
+import static com.firekamp.flutter_unprotected_wifi.NotificationHelper.serviceNotificationId;
+
+public class SecuredWifiCheckForegroundService extends Service {
+
+ public static final String CHANNEL_ID = "ForegroundServiceChannel";
+ public static boolean connect = false;
+ private NetworkChangeBroadcastReceiver mConnectivityReceiver;
+ private VpnStateService.VpnStateListener listener;
+
+ @Override
+ public void onCreate() {
+ super.onCreate();
+ }
+
+ @Override
+ public int onStartCommand(Intent intent, int flags, int startId) {
+ UnProtectedWiFiConfiguration unProtectedWiFiConfiguration = new UnProtectedWiFiConfiguration();
+ unProtectedWiFiConfiguration = unProtectedWiFiConfiguration.getSavedConfiguration(getApplicationContext());
+ if (unProtectedWiFiConfiguration == null) {
+ Log.e(FlutterUnprotectedWifiPlugin.PLUGIN_TAG, "UnProtectedPlugin is not initialized");
+ } else {
+ final VpnStateService service = VpnStateHandler.INSTANCE.getVpnStateService();
+ NetworkHelper networkHelper = new NetworkHelper();
+ final Notification notification = getNotification(getApplicationContext(), service == null ? VpnStateService.State.DISABLED : service.getState(), networkHelper.isSecuredWiFi(getApplicationContext()), unProtectedWiFiConfiguration);
+ if (notification != null) {
+ startForeground(serviceNotificationId, notification);
+ if (mConnectivityReceiver != null) {
+ unregisterReceiver(mConnectivityReceiver);
+ }
+ mConnectivityReceiver = new NetworkChangeBroadcastReceiver();
+ registerReceiver(mConnectivityReceiver, new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION));
+ }
+
+ }
+ registerListeners();
+ return START_NOT_STICKY;
+ }
+
+ @Override
+ public void onDestroy() {
+ unregisterReceiver(mConnectivityReceiver);
+ unregisterListeners();
+ super.onDestroy();
+ }
+
+ @Nullable
+ @Override
+ public IBinder onBind(Intent intent) {
+ return null;
+ }
+
+ private void registerListeners() {
+ try {
+ final VpnStateService service = VpnStateHandler.INSTANCE.getVpnStateService();
+
+ listener = () -> {
+ if (service.getState() != null && (service.getState() == VpnStateService.State.DISABLED || service.getState() == VpnStateService.State.CONNECTED)) {
+ NetworkHelper networkHelper = new NetworkHelper();
+ NotificationHelper notificationHelper = new NotificationHelper();
+ boolean isSecuredWiFi = networkHelper.isSecuredWiFi(getApplicationContext());
+ UnProtectedWiFiConfiguration unProtectedWiFiConfiguration = new UnProtectedWiFiConfiguration();
+ unProtectedWiFiConfiguration = unProtectedWiFiConfiguration.getSavedConfiguration(getApplicationContext());
+ if (unProtectedWiFiConfiguration != null) {
+ showNotification(getApplicationContext(), service.getState(), isSecuredWiFi, unProtectedWiFiConfiguration);
+ }
+ }
+ Log.i(FlutterUnprotectedWifiPlugin.PLUGIN_TAG, "State Changed " + VpnStateHandler.INSTANCE.getVpnStateService().getState());
+ };
+
+ if (service != null) {
+ service.registerListener(listener);
+ }
+ } catch (Exception err) {
+ Log.e(FlutterUnprotectedWifiPlugin.PLUGIN_TAG, "registerListeners" + err.getMessage());
+ }
+ }
+
+ private void unregisterListeners() {
+ final VpnStateService service = VpnStateHandler.INSTANCE.getVpnStateService();
+ try {
+ if (service != null && listener != null) {
+ service.unregisterListener(listener);
+ }
+ } catch (Exception e) {
+ Log.e(FlutterUnprotectedWifiPlugin.PLUGIN_TAG, "unregisterListeners" + e.getMessage());
+ }
+ }
+
+ static Notification getNotification(Context context, VpnStateService.State state, boolean isSecured, UnProtectedWiFiConfiguration unProtectedWiFiConfiguration) {
+ if (unProtectedWiFiConfiguration == null) return null;
+ String title = unProtectedWiFiConfiguration.serviceNotificationTitle;
+ String body = unProtectedWiFiConfiguration.serviceNotificationBody;
+ NotificationHelper notificationHelper = new NotificationHelper();
+ if (unProtectedWiFiConfiguration.isAutoConnect) {
+ title = unProtectedWiFiConfiguration.autoConnectTitle;
+ body = unProtectedWiFiConfiguration.autoConnectBody;
+ } else if (unProtectedWiFiConfiguration.isWarn) {
+ if (isSecured || state == VpnStateService.State.CONNECTED) {
+ title = unProtectedWiFiConfiguration.serviceNotificationTitle;
+ body = unProtectedWiFiConfiguration.serviceNotificationBody;
+ } else {
+ title = unProtectedWiFiConfiguration.warnTitle;
+ body = unProtectedWiFiConfiguration.warnBody;
+ }
+ }
+ return notificationHelper.getNotification(context, unProtectedWiFiConfiguration, title, body);
+ }
+
+
+ public static void showNotification(Context context, VpnStateService.State state, boolean isSecured, UnProtectedWiFiConfiguration unProtectedWiFiConfiguration) {
+ try {
+ NotificationHelper notificationHelper = new NotificationHelper();
+ final Notification notification = getNotification(context, state, isSecured, unProtectedWiFiConfiguration);
+ notificationHelper.showNotification(context, notification);
+ } catch (Exception e) {
+ Log.e(FlutterUnprotectedWifiPlugin.PLUGIN_TAG, "unregisterListeners" + e.getMessage());
+ }
+ }
+
+ public static void startService(Context context, boolean connect) {
+ try {
+ Intent serviceIntent = new Intent(context, SecuredWifiCheckForegroundService.class);
+ SecuredWifiCheckForegroundService.connect = connect;
+ ContextCompat.startForegroundService(context, serviceIntent);
+ //scheduleOnReboot(context, true);
+ } catch (Exception e) {
+ Log.e(FlutterUnprotectedWifiPlugin.PLUGIN_TAG, Objects.requireNonNull(e.getMessage()));
+ }
+ }
+
+ public static void stopService(Context context) {
+ try {
+ Intent serviceIntent = new Intent(context, SecuredWifiCheckForegroundService.class);
+ context.getApplicationContext().stopService(serviceIntent);
+ NotificationHelper notificationHelper = new NotificationHelper();
+ notificationHelper.clearNotification(context);
+ //scheduleOnReboot(context, false);
+
+ //Clear Configuration
+ UnProtectedWiFiConfiguration unprotectedWiFlutterVpnPlugin = new UnProtectedWiFiConfiguration();
+ unprotectedWiFlutterVpnPlugin.clearConfiguration(context);
+ } catch (Exception e) {
+ Log.e(FlutterUnprotectedWifiPlugin.PLUGIN_TAG, Objects.requireNonNull(e.getMessage()));
+ }
+ }
+
+
+ private static void scheduleOnReboot(Context context, boolean enable) {
+ ComponentName receiver = new ComponentName(context, RebootBroadcastReceiver.class);
+ PackageManager pm = context.getPackageManager();
+ pm.setComponentEnabledSetting(receiver, enable ? PackageManager.COMPONENT_ENABLED_STATE_ENABLED : PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP);
+ }
+}
diff --git a/android/src/main/kotlin/com/firekamp/flutter_unprotected_wifi/SharedPreferenceHelper.java b/android/src/main/kotlin/com/firekamp/flutter_unprotected_wifi/SharedPreferenceHelper.java
new file mode 100644
index 0000000..5b41b6f
--- /dev/null
+++ b/android/src/main/kotlin/com/firekamp/flutter_unprotected_wifi/SharedPreferenceHelper.java
@@ -0,0 +1,42 @@
+package com.firekamp.flutter_unprotected_wifi;
+
+import android.content.Context;
+import android.content.SharedPreferences;
+
+public class SharedPreferenceHelper {
+ final private SharedPreferences preferences;
+ final private SharedPreferences.Editor editor;
+ final private String CONFIGURATION_KEY = "com.firekamp.flutter_unprotected_wifi.configuration";
+ final private String LAST_CONNECTION_KEY = "com.firekamp.flutter_unprotected_wifi.lastconnection";
+
+
+ SharedPreferenceHelper(Context context) {
+ preferences = context.getSharedPreferences("UnProtectedWiFi", Context.MODE_PRIVATE);
+ editor = preferences.edit();
+ }
+
+
+ void SaveConfiguration(String value) {
+ editor.putString(CONFIGURATION_KEY, value);
+ editor.commit();
+ }
+
+ String GetConfiguration() {
+ return preferences.getString(CONFIGURATION_KEY, null);
+ }
+
+ boolean GetLastConnectionStatus() {
+ return preferences.getBoolean(LAST_CONNECTION_KEY, false);
+ }
+
+ void SaveLastConnectionStatus(boolean value) {
+ editor.putBoolean(LAST_CONNECTION_KEY, value);
+ editor.commit();
+ }
+
+ void clearConfiguration() {
+ editor.putString(CONFIGURATION_KEY, null);
+ editor.commit();
+ }
+}
+
diff --git a/android/src/main/kotlin/com/firekamp/flutter_unprotected_wifi/UnProtectedWiFiConfiguration.java b/android/src/main/kotlin/com/firekamp/flutter_unprotected_wifi/UnProtectedWiFiConfiguration.java
new file mode 100644
index 0000000..2e60cf7
--- /dev/null
+++ b/android/src/main/kotlin/com/firekamp/flutter_unprotected_wifi/UnProtectedWiFiConfiguration.java
@@ -0,0 +1,114 @@
+package com.firekamp.flutter_unprotected_wifi;
+
+import android.content.Context;
+import android.util.Log;
+
+import com.google.gson.Gson;
+
+import java.util.Objects;
+
+public class UnProtectedWiFiConfiguration {
+
+
+ String appName;
+ String notificationResourceId;
+ String serviceNotificationTitle;
+ String serviceNotificationBody;
+ String warnTitle;
+ String warnBody;
+ String autoConnectTitle;
+ String autoConnectBody;
+ String activityClassName;
+ String packageName;
+ String userName;
+ String displayName;
+ String password;
+ String address;
+ String vpnType;
+ int mtu;
+ boolean isAutoConnect;
+ boolean isWarn;
+
+
+ public UnProtectedWiFiConfiguration(String appName,
+ String notificationResourceId,
+ String serviceNotificationTitle,
+ String serviceNotificationBody,
+ String warnTitle,
+ String warnBody,
+ String autoConnectTitle,
+ String autoConnectBody,
+ String activityClassName,
+ String packageName,
+ String userName,
+ String displayName,
+ String password,
+ String address,
+ String vpnType,
+ int mtu,
+ boolean isAutoConnect,
+ boolean isWarn) {
+ this.appName = appName;
+ this.notificationResourceId = notificationResourceId;
+ this.serviceNotificationTitle = serviceNotificationTitle;
+ this.serviceNotificationBody = serviceNotificationBody;
+ this.warnTitle = warnTitle;
+ this.warnBody = warnBody;
+ this.autoConnectTitle = autoConnectTitle;
+ this.autoConnectBody = autoConnectBody;
+ this.activityClassName = activityClassName;
+ this.packageName = packageName;
+ this.userName = userName;
+ this.displayName = displayName;
+ this.password = password;
+ this.address = address;
+ this.vpnType = vpnType;
+ this.mtu = mtu;
+ this.isAutoConnect = isAutoConnect;
+ this.isWarn = isWarn;
+ }
+
+ public UnProtectedWiFiConfiguration() {
+
+ }
+
+
+ public UnProtectedWiFiConfiguration getSavedConfiguration(Context context) {
+ UnProtectedWiFiConfiguration unProtectedWiFiConfiguration = null;
+ try {
+ SharedPreferenceHelper sharedPreferenceHelper = new SharedPreferenceHelper(context);
+ Gson gson = new Gson();
+ String json = sharedPreferenceHelper.GetConfiguration();
+ if (json != null && !json.isEmpty()) {
+ unProtectedWiFiConfiguration = gson.fromJson(json, UnProtectedWiFiConfiguration.class);
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ Log.e(FlutterUnprotectedWifiPlugin.PLUGIN_TAG, "getSavedConfiguration" + Objects.requireNonNull(e.getMessage()));
+ }
+ return unProtectedWiFiConfiguration;
+ }
+
+ public void savedConfiguration(UnProtectedWiFiConfiguration unProtectedWiFiConfiguration, Context context) {
+ try {
+ SharedPreferenceHelper sharedPreferenceHelper = new SharedPreferenceHelper(context);
+ Gson gson = new Gson();
+ String json = gson.toJson(unProtectedWiFiConfiguration);
+ sharedPreferenceHelper.SaveConfiguration(json);
+ } catch (Exception e) {
+ e.printStackTrace();
+ Log.e(FlutterUnprotectedWifiPlugin.PLUGIN_TAG, "savedConfiguration" + Objects.requireNonNull(e.getMessage()));
+ }
+ }
+
+ public void clearConfiguration(Context context) {
+ try {
+ SharedPreferenceHelper sharedPreferenceHelper = new SharedPreferenceHelper(context);
+ sharedPreferenceHelper.clearConfiguration();
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ Log.e(FlutterUnprotectedWifiPlugin.PLUGIN_TAG, "clearConfiguration" + Objects.requireNonNull(e.getMessage()));
+ }
+ }
+}
diff --git a/android/src/main/kotlin/io/xdea/flutter_vpn/FlutterVpnPlugin.kt b/android/src/main/kotlin/io/xdea/flutter_vpn/FlutterVpnPlugin.kt
index 402840d..0978493 100644
--- a/android/src/main/kotlin/io/xdea/flutter_vpn/FlutterVpnPlugin.kt
+++ b/android/src/main/kotlin/io/xdea/flutter_vpn/FlutterVpnPlugin.kt
@@ -23,6 +23,9 @@ import android.net.VpnService
import android.os.Bundle
import android.os.IBinder
import androidx.annotation.NonNull
+import com.firekamp.flutter_unprotected_wifi.NetworkHelper
+import com.firekamp.flutter_unprotected_wifi.SecuredWifiCheckForegroundService
+import com.firekamp.flutter_unprotected_wifi.UnProtectedWiFiConfiguration
import io.flutter.embedding.engine.plugins.FlutterPlugin
import io.flutter.embedding.engine.plugins.activity.ActivityAware
import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding
@@ -44,6 +47,8 @@ class FlutterVpnPlugin : FlutterPlugin, MethodCallHandler, ActivityAware {
/// when the Flutter Engine is detached from the Activity
private lateinit var channel: MethodChannel
private lateinit var eventChannel: EventChannel
+ private val mtuDefaultValue = 1400
+ private val vpnTypeDefaultValue = "ikev2-eap"
private var vpnStateService: VpnStateService? = null
private val _serviceConnection = object : ServiceConnection {
@@ -147,10 +152,10 @@ class FlutterVpnPlugin : FlutterPlugin, MethodCallHandler, ActivityAware {
profileInfo.putString("UserName", map["username"])
profileInfo.putString("DisplayName", map["displayName"])
profileInfo.putString("Password", map["password"])
- profileInfo.putString("VpnType", "ikev2-eap")
- profileInfo.putInt("MTU", map["mtu"]?.toInt() ?: 1400)
+ profileInfo.putString("VpnType", vpnTypeDefaultValue)
+ profileInfo.putInt("MTU", map["mtu"]?.toInt() ?: mtuDefaultValue)
- vpnStateService?.connect(profileInfo, true)
+ vpnStateService?.connect(profileInfo, true,activityBinding.activity)
result.success(true)
}
"getCurrentState" -> {
@@ -161,6 +166,42 @@ class FlutterVpnPlugin : FlutterPlugin, MethodCallHandler, ActivityAware {
}
"getCharonErrorState" -> result.success(vpnStateService?.errorState?.ordinal)
"disconnect" -> vpnStateService?.disconnect()
+ "configure" -> {
+ val map = call.arguments as HashMap
+ val unProtectedWiFiConfiguration = UnProtectedWiFiConfiguration(
+ map["appName"],
+ map["notificationResourceId"],
+ map["serviceNotificationTitle"],
+ map["serviceNotificationBody"],
+ map["warnTitle"],
+ map["warnBody"],
+ map["autoConnectTitle"],
+ map["autoConnectBody"],
+ map["activityClassName"],
+ map["packageName"],
+ map["userName"],
+ map["displayName"],
+ map["password"],
+ map["address"],
+ vpnTypeDefaultValue,
+ map["mtu"]?.toInt() ?: mtuDefaultValue,
+ map["isAutoConnect"]?.toBoolean() ?: false,
+ map["isWarn"]?.toBoolean() ?: false
+ )
+ unProtectedWiFiConfiguration.savedConfiguration(unProtectedWiFiConfiguration,activityBinding.activity)
+ }
+ "startMonitoring" ->
+ {
+ val toConnect = call.arguments?.toString()?.toBoolean() ?: false
+ SecuredWifiCheckForegroundService.startService(activityBinding.activity,toConnect);
+ }
+ "isSecuredWiFi" -> {
+ val networkHelper = NetworkHelper()
+ val isSecured = networkHelper.isSecuredWiFi(activityBinding.activity)
+ result.success(isSecured)
+ }
+ "stopMonitoring" ->
+ SecuredWifiCheckForegroundService.stopService(activityBinding.activity)
else -> result.notImplemented()
}
}
diff --git a/example/android/app/src/main/AndroidManifest.xml b/example/android/app/src/main/AndroidManifest.xml
index 516001a..0bfc451 100644
--- a/example/android/app/src/main/AndroidManifest.xml
+++ b/example/android/app/src/main/AndroidManifest.xml
@@ -6,7 +6,8 @@
to allow setting breakpoints, to provide hot reload, etc.
-->
-
+
+
connectionChangeListener;
+ConnectivityResult currentNetworkState;
+
+final Connectivity connectivity = Connectivity();
+startListener() {
+ if (connectionChangeListener != null) {
+ connectionChangeListener.cancel();
+ connectionChangeListener = null;
+ }
+ connectionChangeListener = connectivity.onConnectivityChanged
+ .listen((ConnectivityResult result) async {
+ if (currentNetworkState != result) {
+ debugPrint("Network Changed ${result.toString()}");
+ currentNetworkState = result;
+ if (currentNetworkState != ConnectivityResult.none) {
+ FlutterVpn.simpleConnect(
+ "location_place_holder", //TODO: Need to add the exact location before tes
+ "user_name_place_holder", //TODO: Need to add the exact location before tes
+ "password_place_holder", //TODO: Need to add the exact location before tes
+ "Test Location",
+ "io.xdea.flutter_vpn_example",
+ "1");
+ }
+ }
+ });
+}
void main() => runApp(MyApp());
@@ -23,9 +53,11 @@ class MyApp extends StatefulWidget {
}
class _MyAppState extends State {
- final _addressController = TextEditingController();
- final _usernameController = TextEditingController();
- final _passwordController = TextEditingController();
+ final _addressController =
+ TextEditingController(text: "vpn.in1.flyundervpn.com");
+ final _usernameController = TextEditingController(text: "vpn-admin");
+ final _passwordController =
+ TextEditingController(text: "TbhRaKURQgo12BfFbMzN3Ot5UnZZ5357");
var state = FlutterVpnState.disconnected;
var charonState = CharonErrorState.NO_ERROR;
@@ -34,9 +66,31 @@ class _MyAppState extends State {
void initState() {
FlutterVpn.prepare();
FlutterVpn.onStateChanged.listen((s) => setState(() => state = s));
+ initUnProtectedWiFiPlugin();
+ startListener();
super.initState();
}
+ initUnProtectedWiFiPlugin() async {
+ await FlutterVpn.unProtectedWiFiConfigure(
+ "Flutter VPN",
+ "ic_launcher",
+ "Checking your WiFi Changes",
+ "Don't worry",
+ "Checking your WiFi Changes",
+ "Don't worry",
+ "Checking your WiFi Changes",
+ "Don't worry",
+ "io.xdea.flutter_vpn_example.MainActivity",
+ "io.xdea.flutter_vpn_example",
+ _usernameController.text,
+ "Test Location",
+ _passwordController.text,
+ _addressController.text,
+ true,
+ true);
+ }
+
@override
Widget build(BuildContext context) {
return MaterialApp(
@@ -65,15 +119,23 @@ class _MyAppState extends State {
RaisedButton(
child: Text('Connect'),
onPressed: () => FlutterVpn.simpleConnect(
- _addressController.text,
- _usernameController.text,
- _passwordController.text,
- ),
+ _addressController.text,
+ _usernameController.text,
+ _passwordController.text,
+ "Test Location",
+ "io.xdea.flutter_vpn_example",
+ "1"),
),
RaisedButton(
child: Text('Disconnect'),
onPressed: () => FlutterVpn.disconnect(),
),
+ RaisedButton(
+ child: Text('IsSecured WiFi'),
+ onPressed: () async {
+ final isSecured = await FlutterVpn.isSecuredWiFi();
+ debugPrint("isSecuredWiFi: $isSecured");
+ }),
RaisedButton(
child: Text('Update State'),
onPressed: () async {
@@ -86,6 +148,16 @@ class _MyAppState extends State {
var newState = await FlutterVpn.charonErrorState;
setState(() => charonState = newState);
}),
+ RaisedButton(
+ child: Text('Start Monitor'),
+ onPressed: () async {
+ await FlutterVpn.startMonitor(true);
+ }),
+ RaisedButton(
+ child: Text('Stop Monitor'),
+ onPressed: () async {
+ await FlutterVpn.stopMonitor();
+ }),
],
),
),
diff --git a/lib/flutter_vpn.dart b/lib/flutter_vpn.dart
index e781232..edad3bb 100644
--- a/lib/flutter_vpn.dart
+++ b/lib/flutter_vpn.dart
@@ -87,12 +87,31 @@ class FlutterVpn {
await _channel.invokeMethod('disconnect');
}
+ static Future isSecuredWiFi() async {
+ return await _channel.invokeMethod('isSecuredWiFi');
+ }
+
+ static Future startMonitor(bool connect) async {
+ await _channel.invokeMethod('startMonitoring',connect.toString());
+ }
+
+ static Future stopMonitor() async {
+ await _channel.invokeMethod('stopMonitoring');
+ }
+
/// Connect to VPN.
///
/// Use given credentials to connect VPN (ikev2-eap).
/// This will create a background VPN service.
/// MTU is only available on android.
- static Future simpleConnect(String address, String username, String password, String displayName, String packageName, String activityName, {int mtu = 1400}) async {
+ static Future simpleConnect(
+ String address,
+ String username,
+ String password,
+ String displayName,
+ String packageName,
+ String activityName,
+ {int mtu = 1400}) async {
await _channel.invokeMethod('connect', {
'address': address,
'username': username,
@@ -103,4 +122,42 @@ class FlutterVpn {
'mtu': mtu.toString()
});
}
+
+ static Future unProtectedWiFiConfigure(
+ String appName,
+ String notificationResourceId,
+ String serviceNotificationTitle,
+ String serviceNotificationBody,
+ String warnTitle,
+ String warnBody,
+ String autoConnectTitle,
+ String autoConnectBody,
+ String activityClassName,
+ String packageName,
+ String userName,
+ String displayName,
+ String password,
+ String address,
+ bool isAutoConnect,
+ bool isWarn,
+ ) async {
+ await _channel.invokeMethod('configure', {
+ 'appName': appName,
+ 'notificationResourceId': notificationResourceId,
+ 'serviceNotificationTitle': serviceNotificationTitle,
+ 'serviceNotificationBody': serviceNotificationBody,
+ 'warnTitle': warnTitle,
+ 'warnBody': warnBody,
+ 'autoConnectTitle': autoConnectTitle,
+ 'autoConnectBody': autoConnectBody,
+ 'activityClassName': activityClassName,
+ 'packageName': packageName,
+ 'userName': userName,
+ 'displayName': displayName,
+ 'password': password,
+ 'address': address,
+ "isAutoConnect": isAutoConnect.toString(),
+ "isWarn": isWarn.toString()
+ });
+ }
}
diff --git a/pubspec.yaml b/pubspec.yaml
index f2cb61d..57afb5a 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -1,6 +1,6 @@
name: flutter_vpn
description: Plugin for developers to access VPN service in their flutter app.
-version: 0.8.5
+version: 0.8.77
authors:
- Jason C.H
- Jerry Wang
@@ -13,6 +13,7 @@ environment:
dependencies:
flutter:
sdk: flutter
+ connectivity: ^0.4.9
dev_dependencies:
flutter_test: