Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -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'
}
1 change: 1 addition & 0 deletions android/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

<application>
<service
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@

import androidx.core.content.ContextCompat;

import com.firekamp.flutter_unprotected_wifi.FlutterUnprotectedWifiPlugin;

import org.strongswan.android.data.VpnProfile;
import org.strongswan.android.logic.imc.ImcState;
import org.strongswan.android.logic.imc.RemediationInstruction;
Expand Down Expand Up @@ -97,7 +99,7 @@ public VpnStateService getService() {
public void onCreate() {
/* this handler allows us to notify listeners from the UI thread and
* not from the threads that actually report any state changes */
mHandler = new RetryHandler(this);
mHandler = new RetryHandler(this, getApplicationContext());
}

@Override
Expand Down Expand Up @@ -261,9 +263,8 @@ public void disconnect() {
* previous profile if null
* @param fromScratch true if this is a manual retry/reconnect or a completely new connection
*/
public void connect(Bundle profileInfo, boolean fromScratch) {
public void connect(Bundle profileInfo, boolean fromScratch, Context context) {
/* we assume we have the necessary permission */
Context context = getApplicationContext();
Intent intent = new Intent(context, CharonVpnService.class);
if (profileInfo == null) {
profileInfo = mProfileInfo;
Expand All @@ -274,6 +275,9 @@ public void connect(Bundle profileInfo, boolean fromScratch) {
/* reset if this is a manual retry or a new connection */
mTimeoutProvider.reset();
} else { /* mark this as an automatic retry */
if(profileInfo==null) {
profileInfo = FlutterUnprotectedWifiPlugin.getConfigurationBundle(context);
}
profileInfo.putBoolean(CharonVpnService.KEY_IS_RETRY, true);
}
intent.putExtras(profileInfo);
Expand Down Expand Up @@ -447,9 +451,11 @@ private void resetRetryTimer() {
*/
private static class RetryHandler extends Handler {
WeakReference<VpnStateService> mService;
Context context;

public RetryHandler(VpnStateService service) {
public RetryHandler(VpnStateService service, Context context) {
mService = new WeakReference<>(service);
this.context = context;
}

@Override
Expand All @@ -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);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -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;
}
}
Original file line number Diff line number Diff line change
@@ -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();
}
}
Original file line number Diff line number Diff line change
@@ -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<ScanResult> 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;
}
}
Original file line number Diff line number Diff line change
@@ -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()));
}
}
}

Original file line number Diff line number Diff line change
@@ -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);
}
}
}
Loading