Skip to content

Commit cdf65c7

Browse files
authored
Merge pull request #4 from scottmconway/custom_denylist
Added custom package denylist MVP
2 parents ea12d60 + 09f5f56 commit cdf65c7

File tree

5 files changed

+139
-29
lines changed

5 files changed

+139
-29
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package net.kzxiv.notify.client;
2+
3+
public class AppConstants {
4+
public static final String TAG = "notifikator";
5+
public static final String PACKAGE_DENY_LIST_PREF_KEY = "package_deny_list";
6+
7+
}

client/src/main/java/net/kzxiv/notify/client/ConfigurationActivity.java

+91-6
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,107 @@
11
package net.kzxiv.notify.client;
22

3-
import android.app.*;
4-
import android.content.res.*;
5-
import android.graphics.*;
6-
import android.graphics.drawable.*;
7-
import android.os.*;
8-
import android.preference.*;
3+
import android.app.Notification;
4+
import android.app.NotificationChannel;
5+
import android.app.NotificationManager;
6+
import android.app.Service;
7+
import android.content.Intent;
8+
import android.content.SharedPreferences;
9+
import android.content.res.Resources;
10+
import android.graphics.Bitmap;
11+
import android.graphics.Color;
12+
import android.graphics.drawable.BitmapDrawable;
13+
import android.net.Uri;
14+
import android.os.Bundle;
15+
import android.preference.Preference;
16+
import android.preference.PreferenceActivity;
17+
import android.preference.PreferenceManager;
18+
import android.preference.PreferenceScreen;
19+
import android.widget.Toast;
20+
21+
import java.io.BufferedReader;
22+
import java.io.IOException;
23+
import java.io.InputStream;
24+
import java.io.InputStreamReader;
25+
import java.util.HashSet;
26+
import java.util.regex.Matcher;
27+
import java.util.regex.Pattern;
928

1029
public class ConfigurationActivity extends PreferenceActivity
1130
{
31+
private static final int PICK_FILE_REQUEST_CODE = 123;
32+
private static final Pattern PACKAGE_NAME_REGEX = Pattern.compile("^[a-z]+(\\.[a-z0-9_]+)*$");
33+
1234
protected void onCreate(Bundle savedInstanceState)
1335
{
1436
super.onCreate(savedInstanceState);
1537

1638
PreferenceManager.setDefaultValues(this, R.xml.preferences, false);
1739
addPreferencesFromResource(R.xml.preferences);
40+
41+
42+
Preference chooseFileButton = findPreference(getString(R.string.key_choose_denylist));
43+
chooseFileButton.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
44+
@Override
45+
public boolean onPreferenceClick(Preference preference) {
46+
openFilePickerForDenylist();
47+
return true;
48+
}
49+
});
50+
51+
}
52+
53+
private void openFilePickerForDenylist() {
54+
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
55+
intent.addCategory(Intent.CATEGORY_OPENABLE);
56+
intent.setType("text/plain");
57+
startActivityForResult(intent, PICK_FILE_REQUEST_CODE);
58+
}
59+
60+
@Override
61+
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
62+
super.onActivityResult(requestCode, resultCode, data);
63+
if (requestCode == PICK_FILE_REQUEST_CODE && resultCode == RESULT_OK) {
64+
if (data != null && data.getData() != null) {
65+
Uri selectedFileUri = data.getData();
66+
readDenylistFile(selectedFileUri);
67+
}
68+
}
1869
}
1970

71+
private void readDenylistFile(Uri fileUri) {
72+
try {
73+
InputStream inputStream = getContentResolver().openInputStream(fileUri);
74+
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
75+
HashSet<String> lines = new HashSet<String>();
76+
String line;
77+
78+
while ((line = reader.readLine()) != null) {
79+
Matcher matcher = PACKAGE_NAME_REGEX.matcher(line);
80+
if (matcher.matches()) {
81+
lines.add(line);
82+
}
83+
else {
84+
// TODO parsing error - should we ignore this package name, or stop parsing and err out?
85+
// For now we'll just ignore specific entries
86+
87+
// TODO should source error text from res/values
88+
Toast.makeText(getApplicationContext(), String.format("Invalid package name for deny list - \"%s\"", line), Toast.LENGTH_SHORT).show();
89+
}
90+
}
91+
reader.close();
92+
inputStream.close();
93+
94+
// save result in stored preferences
95+
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
96+
SharedPreferences.Editor editor = sharedPreferences.edit();
97+
98+
editor.putStringSet(AppConstants.PACKAGE_DENY_LIST_PREF_KEY, lines);
99+
editor.apply();
100+
101+
} catch (IOException e) {
102+
e.printStackTrace();
103+
}
104+
}
20105
public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference)
21106
{
22107
int NOTIFICATION_ID = 0;

client/src/main/java/net/kzxiv/notify/client/NotificationService.java

+33-23
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,55 @@
11
package net.kzxiv.notify.client;
22

3-
import android.app.*;
4-
import android.content.*;
5-
import android.content.pm.*;
6-
import android.content.res.*;
7-
import android.graphics.*;
8-
import android.graphics.drawable.*;
9-
import android.net.*;
10-
import android.preference.*;
11-
import android.service.notification.*;
12-
import android.util.*;
13-
import org.json.*;
14-
import java.io.*;
15-
import java.nio.charset.*;
16-
import java.util.Arrays;
3+
import android.app.Notification;
4+
import android.content.Context;
5+
import android.content.Intent;
6+
import android.content.SharedPreferences;
7+
import android.content.pm.ApplicationInfo;
8+
import android.content.pm.PackageManager;
9+
import android.content.res.Resources;
10+
import android.graphics.Bitmap;
11+
import android.graphics.drawable.BitmapDrawable;
12+
import android.net.ConnectivityManager;
13+
import android.net.NetworkInfo;
14+
import android.preference.PreferenceManager;
15+
import android.service.notification.NotificationListenerService;
16+
import android.service.notification.StatusBarNotification;
17+
import android.util.Log;
18+
19+
import org.json.JSONException;
20+
import org.json.JSONObject;
21+
22+
import java.io.IOException;
23+
import java.nio.charset.Charset;
1724
import java.util.HashSet;
1825
import java.util.Set;
1926

2027
public class NotificationService extends NotificationListenerService
2128
{
29+
private static final String TAG = AppConstants.TAG;
30+
2231
public void onCreate()
2332
{
2433
super.onCreate();
2534
PreferenceManager.setDefaultValues(this, R.xml.preferences, false);
26-
Log.d("Notifikator", "Notification service created.");
35+
Log.d(TAG, "Notification service created.");
2736
}
2837

2938
public void onDestroy()
3039
{
31-
Log.d("Notifikator", "Notification service destroyed.");
40+
Log.d(TAG, "Notification service destroyed.");
3241
super.onDestroy();
3342
}
3443

3544
public void onNotificationPosted(StatusBarNotification sbn)
3645
{
3746
// Skip notifications from denied packages
38-
// TODO make user-configurable
39-
final Set<String> packageDenylist = new HashSet<String>(
40-
Arrays.asList("org.fdroid.fdroid", "com.topjohnwu.magisk", "com.aurora.store", "com.android.messaging", "dev.ukanth.ufirewall", "com.android.packageinstaller"));
47+
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
48+
final Set<String> packageDenylist = sharedPreferences.getStringSet(AppConstants.PACKAGE_DENY_LIST_PREF_KEY, new HashSet<>());
49+
4150
String packageName = sbn.getPackageName();
4251
if (packageDenylist.contains(packageName)){
52+
Log.d(TAG, String.format("blocked notification for package \"%s\"", packageName));
4353
return;
4454
}
4555

@@ -50,7 +60,7 @@ public void onNotificationPosted(StatusBarNotification sbn)
5060

5161
if (!enabled)
5262
{
53-
Log.i("Notifikator", "Skipping notification because not enabled.");
63+
Log.i(TAG, "Skipping notification because not enabled.");
5464
return;
5565
}
5666

@@ -63,7 +73,7 @@ public void onNotificationPosted(StatusBarNotification sbn)
6373

6474
if (ni == null || ni.getType() != ConnectivityManager.TYPE_WIFI)
6575
{
66-
Log.i("Notifikator", "Skipping notification because not connected to wifi.");
76+
Log.i(TAG, "Skipping notification because not connected to wifi.");
6777
return;
6878
}
6979
}
@@ -73,7 +83,7 @@ public void onNotificationPosted(StatusBarNotification sbn)
7383

7484
if (endpointUrl == null || "".equals(endpointUrl))
7585
{
76-
Log.e("Notifikator", "No endpoint specified.");
86+
Log.e(TAG, "No endpoint specified.");
7787
return;
7888
}
7989

@@ -99,7 +109,7 @@ else if (res.getString(R.string.protocol_gotify).equals(protocol))
99109

100110
if (payload == null)
101111
{
102-
Log.e("Notifikator", String.format("No payload or unknown protocol \"%s\".", protocol));
112+
Log.e(TAG, String.format("No payload or unknown protocol \"%s\".", protocol));
103113
return;
104114
}
105115

client/src/main/res/values/strings.xml

+3
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
<string name="key_endpointuser">EndpointUsername</string>
1111
<string name="key_endpointpw">EndpointPassword</string>
1212
<string name="key_send">NotificationSend</string>
13+
<string name="key_choose_denylist">ChooseDenylist</string>
1314

1415
<string name="protocol_kodi">kodi</string>
1516
<string name="protocol_kodi_addon">kodi+addon</string>
@@ -38,6 +39,8 @@
3839
<string name="enabled_summary">Forward received notifications</string>
3940
<string name="wifionly">Wi-Fi Only</string>
4041
<string name="wifionly_summary">Only forward notifications when connected to Wi-Fi</string>
42+
<string name="choose_denylist">Package Denylist File</string>
43+
<string name="choose_denylist_summary">Select file to initialize package denylist</string>
4144
<string name="protocol">Protocol</string>
4245
<string name="protocol_summary">How to encode the notification data</string>
4346
<string name="notification_access">Open Notification Access</string>

client/src/main/res/xml/preferences.xml

+5
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,11 @@
1111
android:summary="@string/wifionly_summary"
1212
android:key="@string/key_wifionly"
1313
android:defaultValue="false" />
14+
<Preference
15+
android:title="@string/choose_denylist"
16+
android:summary="@string/choose_denylist_summary"
17+
android:key="@string/key_choose_denylist"
18+
android:id="@+id/chooseDenylistButton" />
1419
<Preference
1520
android:title="@string/notification_access"
1621
android:summary="@string/notification_access_summary">

0 commit comments

Comments
 (0)