diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 447661f4..f90a3794 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -119,6 +119,8 @@
+
+
diff --git a/app/src/main/java/com/emanuelef/remote_capture/ActionReceiver.java b/app/src/main/java/com/emanuelef/remote_capture/ActionReceiver.java
new file mode 100644
index 00000000..3249a77c
--- /dev/null
+++ b/app/src/main/java/com/emanuelef/remote_capture/ActionReceiver.java
@@ -0,0 +1,55 @@
+/*
+ * This file is part of PCAPdroid.
+ *
+ * PCAPdroid is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * PCAPdroid is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with PCAPdroid. If not, see .
+ *
+ * Copyright 2022 - Emanuele Faranda
+ */
+
+package com.emanuelef.remote_capture;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.util.Log;
+
+import androidx.core.app.NotificationManagerCompat;
+
+import com.emanuelef.remote_capture.model.AppDescriptor;
+import com.emanuelef.remote_capture.model.Blocklist;
+
+public class ActionReceiver extends BroadcastReceiver {
+ public static final String EXTRA_UNBLOCK_APP = "unblock_app";
+ private static final String TAG = "TAG";
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ String unblock_app = intent.getStringExtra(EXTRA_UNBLOCK_APP);
+
+ if((unblock_app != null) && !unblock_app.isEmpty()) {
+ Log.d(TAG, "unblock_app: " + unblock_app);
+ Blocklist blocklist = PCAPdroid.getInstance().getBlocklist();
+ blocklist.removeApp(unblock_app);
+ blocklist.saveAndReload();
+
+ // remove notification
+ NotificationManagerCompat man = NotificationManagerCompat.from(context);
+ man.cancel(CaptureService.NOTIFY_ID_APP_BLOCKED);
+
+ AppDescriptor app = AppsResolver.resolve(context.getPackageManager(), unblock_app, 0);
+ String label = (app != null) ? app.getName() : unblock_app;
+ Utils.showToastLong(context, R.string.app_unblocked, label);
+ }
+ }
+}
diff --git a/app/src/main/java/com/emanuelef/remote_capture/CaptureService.java b/app/src/main/java/com/emanuelef/remote_capture/CaptureService.java
index dcd2e3db..0a10cf9c 100644
--- a/app/src/main/java/com/emanuelef/remote_capture/CaptureService.java
+++ b/app/src/main/java/com/emanuelef/remote_capture/CaptureService.java
@@ -59,6 +59,7 @@ import androidx.preference.PreferenceManager;
import com.emanuelef.remote_capture.activities.CaptureCtrl;
import com.emanuelef.remote_capture.activities.ConnectionsActivity;
+import com.emanuelef.remote_capture.activities.FirewallActivity;
import com.emanuelef.remote_capture.activities.MainActivity;
import com.emanuelef.remote_capture.fragments.ConnectionsFragment;
import com.emanuelef.remote_capture.model.AppDescriptor;
@@ -98,9 +99,9 @@ public class CaptureService extends VpnService implements Runnable {
private static final String NOTIFY_CHAN_MALWARE_DETECTION = "Malware detection";
private static final String NOTIFY_CHAN_OTHER = "Other";
private static final int VPN_MTU = 10000;
- private static final int NOTIFY_ID_VPNSERVICE = 1;
- private static final int NOTIFY_ID_LOW_MEMORY = 2;
- private static final int NOTIFY_ID_APP_BLOCKED = 3;
+ public static final int NOTIFY_ID_VPNSERVICE = 1;
+ public static final int NOTIFY_ID_LOW_MEMORY = 2;
+ public static final int NOTIFY_ID_APP_BLOCKED = 3;
private static CaptureService INSTANCE;
final ReentrantLock mLock = new ReentrantLock();
final Condition mCaptureStopped = mLock.newCondition();
@@ -485,16 +486,26 @@ public class CaptureService extends VpnService implements Runnable {
AppDescriptor app = appsResolver.getByPackage(packageName, 0);
String label = (app != null) ? app.getName() : packageName;
+ PendingIntent pi = PendingIntent.getActivity(CaptureService.this, 0,
+ new Intent(CaptureService.this, FirewallActivity.class), Utils.getIntentFlags(0));
+
+ PendingIntent unblockIntent = PendingIntent.getBroadcast(CaptureService.this, 0,
+ new Intent(CaptureService.this, ActionReceiver.class)
+ .putExtra(ActionReceiver.EXTRA_UNBLOCK_APP, packageName), Utils.getIntentFlags(PendingIntent.FLAG_UPDATE_CURRENT));
+
// Notify the user
NotificationManagerCompat man = NotificationManagerCompat.from(context);
if(man.areNotificationsEnabled()) {
Notification notification = new NotificationCompat.Builder(CaptureService.this, NOTIFY_CHAN_OTHER)
+ .setContentIntent(pi)
.setSmallIcon(R.drawable.ic_logo)
.setColor(ContextCompat.getColor(CaptureService.this, R.color.colorPrimary))
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
.setCategory(NotificationCompat.CATEGORY_STATUS)
.setContentTitle(getString(R.string.app_blocked))
.setContentText(getString(R.string.app_blocked_info, label))
+ .setAutoCancel(true)
+ .addAction(R.drawable.ic_check_solid, getString(R.string.action_unblock), unblockIntent)
.build();
man.notify(NOTIFY_ID_APP_BLOCKED, notification);
diff --git a/app/src/main/java/com/emanuelef/remote_capture/fragments/AppsFragment.java b/app/src/main/java/com/emanuelef/remote_capture/fragments/AppsFragment.java
index 7abc2fd1..792282e3 100644
--- a/app/src/main/java/com/emanuelef/remote_capture/fragments/AppsFragment.java
+++ b/app/src/main/java/com/emanuelef/remote_capture/fragments/AppsFragment.java
@@ -181,9 +181,7 @@ public class AppsFragment extends Fragment implements ConnectionsListener {
else
return super.onContextItemSelected(item);
- blocklist.save();
- if(CaptureService.isServiceActive())
- CaptureService.requireInstance().reloadBlocklist();
+ blocklist.saveAndReload();
// refresh the item
mAdapter.notifyItemChanged(app);
diff --git a/app/src/main/java/com/emanuelef/remote_capture/fragments/ConnectionsFragment.java b/app/src/main/java/com/emanuelef/remote_capture/fragments/ConnectionsFragment.java
index 850cdc4e..b5709290 100644
--- a/app/src/main/java/com/emanuelef/remote_capture/fragments/ConnectionsFragment.java
+++ b/app/src/main/java/com/emanuelef/remote_capture/fragments/ConnectionsFragment.java
@@ -557,11 +557,8 @@ public class ConnectionsFragment extends Fragment implements ConnectionsListener
} else if(whitelist_changed) {
whitelist.save();
CaptureService.reloadMalwareWhitelist();
- } else if(blocklist_changed) {
- blocklist.save();
- if(CaptureService.isServiceActive())
- CaptureService.requireInstance().reloadBlocklist();
- }
+ } else if(blocklist_changed)
+ blocklist.saveAndReload();
return true;
}
diff --git a/app/src/main/java/com/emanuelef/remote_capture/model/Blocklist.java b/app/src/main/java/com/emanuelef/remote_capture/model/Blocklist.java
index 1261e321..6217edf5 100644
--- a/app/src/main/java/com/emanuelef/remote_capture/model/Blocklist.java
+++ b/app/src/main/java/com/emanuelef/remote_capture/model/Blocklist.java
@@ -5,6 +5,8 @@ import android.os.SystemClock;
import android.util.ArrayMap;
import android.util.Log;
+import com.emanuelef.remote_capture.CaptureService;
+
import java.util.Iterator;
import java.util.Map;
@@ -69,4 +71,11 @@ public class Blocklist extends MatchList {
mUidToGrace.remove(uid);
super.addApp(uid);
}
+
+ public void saveAndReload() {
+ save();
+
+ if(CaptureService.isServiceActive())
+ CaptureService.requireInstance().reloadBlocklist();
+ }
}
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 26154924..e3574845 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -383,6 +383,7 @@
Block newly installed apps
App blocked
The %1$s app has been blocked by the firewall
+ The %1$s app has been unblocked
This view may contain sensitive information, like your passwords and access tokens.\n\nNever give out this information to anyone, it may be a scam attempt
Cancel
Show data