diff --git a/app/build.gradle b/app/build.gradle
index bdb7845b..5833f185 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -5,13 +5,13 @@ def keystoreProperties = new Properties()
keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
android {
- compileSdkVersion = 31
+ compileSdkVersion = 34
defaultConfig {
applicationId = "eu.faircode.netguard"
versionName = "2.309"
minSdkVersion 22
- targetSdkVersion 31
+ targetSdkVersion 34
versionCode = 2023082401
archivesBaseName = "NetGuard-v$versionName"
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 5e6cfae7..e78ea6a6 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -12,6 +12,7 @@
+
diff --git a/app/src/main/java/eu/faircode/netguard/ActivityMain.java b/app/src/main/java/eu/faircode/netguard/ActivityMain.java
index 59acf6af..de565bb2 100644
--- a/app/src/main/java/eu/faircode/netguard/ActivityMain.java
+++ b/app/src/main/java/eu/faircode/netguard/ActivityMain.java
@@ -19,6 +19,7 @@ package eu.faircode.netguard;
Copyright 2015-2019 by Marcel Bokhorst (M66B)
*/
+import android.Manifest;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
@@ -63,6 +64,8 @@ import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.SearchView;
import androidx.appcompat.widget.SwitchCompat;
+import androidx.core.app.ActivityCompat;
+import androidx.core.content.ContextCompat;
import androidx.core.graphics.drawable.DrawableCompat;
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
import androidx.preference.PreferenceManager;
@@ -94,6 +97,7 @@ public class ActivityMain extends AppCompatActivity implements SharedPreferences
private static final int REQUEST_VPN = 1;
private static final int REQUEST_INVITE = 2;
public static final int REQUEST_ROAMING = 3;
+ private static final int REQUEST_NOTIFICATIONS = 4;
private static final int MIN_SDK = Build.VERSION_CODES.LOLLIPOP_MR1;
@@ -306,6 +310,17 @@ public class ActivityMain extends AppCompatActivity implements SharedPreferences
TextView tvDisabled = findViewById(R.id.tvDisabled);
tvDisabled.setVisibility(enabled ? View.GONE : View.VISIBLE);
+ // Notification permissions
+ TextView tvNotifications = findViewById(R.id.tvNotifications);
+ tvNotifications.setVisibility(View.GONE);
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU)
+ tvNotifications.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ requestPermissions(new String[]{Manifest.permission.POST_NOTIFICATIONS}, REQUEST_NOTIFICATIONS);
+ }
+ });
+
// Application list
RecyclerView rvApplication = findViewById(R.id.rvApplication);
rvApplication.setHasFixedSize(false);
@@ -511,6 +526,15 @@ public class ActivityMain extends AppCompatActivity implements SharedPreferences
IAB.isPurchasedAny(this) || getIntentPro(this).resolveActivity(pm) == null
? View.GONE : View.VISIBLE);
+ boolean canNotify =
+ (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU ||
+ (ContextCompat.checkSelfPermission(this,
+ android.Manifest.permission.POST_NOTIFICATIONS) ==
+ PackageManager.PERMISSION_GRANTED));
+ TextView tvNotifications = findViewById(R.id.tvNotifications);
+ if (tvNotifications != null)
+ tvNotifications.setVisibility(canNotify ? View.GONE : View.VISIBLE);
+
super.onResume();
}
@@ -612,9 +636,23 @@ public class ActivityMain extends AppCompatActivity implements SharedPreferences
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
- if (requestCode == REQUEST_ROAMING)
+ super.onRequestPermissionsResult(requestCode, permissions, grantResults);
+ if (requestCode == REQUEST_ROAMING) {
if (grantResults[0] == PackageManager.PERMISSION_GRANTED)
ServiceSinkhole.reload("permission granted", this, false);
+ } else if (requestCode == REQUEST_NOTIFICATIONS) {
+ if (grantResults[0] != PackageManager.PERMISSION_GRANTED &&
+ !ActivityCompat.shouldShowRequestPermissionRationale(this,
+ Manifest.permission.POST_NOTIFICATIONS))
+ try {
+ Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
+ Uri uri = Uri.fromParts("package", getPackageName(), null);
+ intent.setData(uri);
+ startActivity(intent);
+ } catch (Throwable ex) {
+ Log.e(TAG, ex + "\n" + ex.getStackTrace());
+ }
+ }
}
@Override
diff --git a/app/src/main/res/drawable/twotone_notifications_24.xml b/app/src/main/res/drawable/twotone_notifications_24.xml
new file mode 100644
index 00000000..3f4d8f05
--- /dev/null
+++ b/app/src/main/res/drawable/twotone_notifications_24.xml
@@ -0,0 +1,15 @@
+
+
+
+
diff --git a/app/src/main/res/layout/main.xml b/app/src/main/res/layout/main.xml
index 503a83c1..d8a9eafd 100644
--- a/app/src/main/res/layout/main.xml
+++ b/app/src/main/res/layout/main.xml
@@ -27,6 +27,19 @@
android:textColor="?attr/colorOff"
android:visibility="gone" />
+
+
%1$d allowed, %2$d blocked, %3$d hosts
Waiting for event
NetGuard is disabled, use the switch above to enable NetGuard
+ Tap to grant notification permissions (for access attempt notifications, error messages, etc.)
Google forces me to state that the app collects and shares email addresses when it does not.
I refuse to make false statements.