mirror of
https://github.com/KDE/kdeconnect-android
synced 2025-09-01 06:35:09 +00:00
Rewritten the Notification Filter.
- Now we display every app in the phone. - We show the app icon next to the name. - Some apps can now be disabled by default. Disabled notifications for the default Android messaging app, as SMS notifications are already handled by the telephony plugin. BUG: 367930
This commit is contained in:
@@ -15,10 +15,18 @@
|
|||||||
android:paddingBottom="5dp"
|
android:paddingBottom="5dp"
|
||||||
android:id="@+id/tFilter"/>
|
android:id="@+id/tFilter"/>
|
||||||
|
|
||||||
|
<ProgressBar
|
||||||
|
android:layout_marginTop="64dip"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:id="@+id/spinner" />
|
||||||
|
|
||||||
<ListView
|
<ListView
|
||||||
android:layout_width="fill_parent"
|
android:layout_width="fill_parent"
|
||||||
android:layout_height="fill_parent"
|
android:layout_height="fill_parent"
|
||||||
android:id="@+id/lvFilterApps"
|
android:id="@+id/lvFilterApps"
|
||||||
|
android:visibility="gone"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
@@ -6,4 +6,11 @@ public class StringsHelper {
|
|||||||
|
|
||||||
public static final Charset UTF8 = Charset.forName("UTF-8");
|
public static final Charset UTF8 = Charset.forName("UTF-8");
|
||||||
|
|
||||||
|
public static int compare(String a, String b) {
|
||||||
|
if (a == b) return 0;
|
||||||
|
if (a == null) return -1;
|
||||||
|
if (b == null) return 1;
|
||||||
|
return a.compareToIgnoreCase(b);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -26,26 +26,32 @@ import android.database.Cursor;
|
|||||||
import android.database.sqlite.SQLiteDatabase;
|
import android.database.sqlite.SQLiteDatabase;
|
||||||
import android.database.sqlite.SQLiteOpenHelper;
|
import android.database.sqlite.SQLiteOpenHelper;
|
||||||
|
|
||||||
|
import java.util.HashSet;
|
||||||
|
|
||||||
public class AppDatabase {
|
public class AppDatabase {
|
||||||
|
|
||||||
public static final String KEY_ROW_ID = "id";
|
static final private HashSet<String> disabledByDefault = new HashSet<>();
|
||||||
public static final String KEY_NAME = "app";
|
static {
|
||||||
public static final String KEY_PACKAGE_NAME = "packageName";
|
disabledByDefault.add("com.android.messaging"); //We already have sms notifications in the telephony plugin
|
||||||
public static final String KEY_IS_ENABLED = "isEnabled";
|
disabledByDefault.add("com.google.android.googlequicksearchbox"); //Google Now notifications re-spawn every few minutes
|
||||||
|
}
|
||||||
|
|
||||||
private static final String DATABASE_NAME = "Applications";
|
static final String KEY_PACKAGE_NAME = "packageName";
|
||||||
private static final String DATABASE_TABLE = "Applications";
|
static final String KEY_IS_ENABLED = "isEnabled";
|
||||||
private static final int DATABASE_VERSION = 1;
|
|
||||||
|
|
||||||
private final Context ourContext;
|
static final String DATABASE_NAME = "Applications";
|
||||||
private SQLiteDatabase ourDatabase;
|
static final String DATABASE_TABLE = "Applications";
|
||||||
private DbHelper ourHelper;
|
static final int DATABASE_VERSION = 2;
|
||||||
|
|
||||||
|
final Context ourContext;
|
||||||
|
SQLiteDatabase ourDatabase;
|
||||||
|
DbHelper ourHelper;
|
||||||
|
|
||||||
public AppDatabase(Context c) {
|
public AppDatabase(Context c) {
|
||||||
ourContext = c;
|
ourContext = c;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class DbHelper extends SQLiteOpenHelper{
|
private static class DbHelper extends SQLiteOpenHelper {
|
||||||
|
|
||||||
public DbHelper(Context context) {
|
public DbHelper(Context context) {
|
||||||
super(context, DATABASE_NAME, null, DATABASE_VERSION);
|
super(context, DATABASE_NAME, null, DATABASE_VERSION);
|
||||||
@@ -53,73 +59,57 @@ public class AppDatabase {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate(SQLiteDatabase db) {
|
public void onCreate(SQLiteDatabase db) {
|
||||||
db.execSQL("CREATE TABLE " + DATABASE_TABLE + "(" + KEY_ROW_ID + " INTEGER PRIMARY KEY AUTOINCREMENT,"
|
db.execSQL("CREATE TABLE " + DATABASE_TABLE + "(" + KEY_PACKAGE_NAME + " TEXT PRIMARY KEY NOT NULL, " + KEY_IS_ENABLED + " TEXT NOT NULL); ");
|
||||||
+ KEY_NAME + " TEXT NOT NULL, " + KEY_PACKAGE_NAME + " TEXT NOT NULL, " + KEY_IS_ENABLED + " TEXT NOT NULL); ");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onUpgrade(SQLiteDatabase db, int i, int i2) {
|
public void onUpgrade(SQLiteDatabase db, int i, int i2) {
|
||||||
db.execSQL("DROP TABLE IF EXISTS "+ DATABASE_TABLE);
|
db.execSQL("DROP TABLE IF EXISTS "+ DATABASE_TABLE);
|
||||||
onCreate(db);
|
onCreate(db);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void open(){
|
public void open() {
|
||||||
ourHelper = new DbHelper(ourContext);
|
ourHelper = new DbHelper(ourContext);
|
||||||
ourDatabase = ourHelper.getWritableDatabase();
|
ourDatabase = ourHelper.getWritableDatabase();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void close() {
|
||||||
public void close(){
|
|
||||||
ourHelper.close();
|
ourHelper.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Cursor getAllApplications()
|
public void setEnabled(String packageName, boolean isEnabled) {
|
||||||
{
|
String[] columns = new String []{KEY_IS_ENABLED};
|
||||||
String[] columns = new String []{KEY_ROW_ID,KEY_NAME,KEY_PACKAGE_NAME,KEY_IS_ENABLED};
|
Cursor res = ourDatabase.query(DATABASE_TABLE, columns, KEY_PACKAGE_NAME + " =? ",new String[]{packageName},null,null,null);
|
||||||
Cursor res = ourDatabase.query(DATABASE_TABLE,columns,null,null,null,null,KEY_NAME);
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
public long create(String appName, String packageName, boolean isEnabled) {
|
|
||||||
ContentValues cv = new ContentValues();
|
ContentValues cv = new ContentValues();
|
||||||
cv.put(KEY_NAME, appName);
|
|
||||||
cv.put(KEY_PACKAGE_NAME, packageName);
|
|
||||||
cv.put(KEY_IS_ENABLED, isEnabled?"true":"false");
|
cv.put(KEY_IS_ENABLED, isEnabled?"true":"false");
|
||||||
return ourDatabase.insert(DATABASE_TABLE, null, cv);
|
if (res.getCount() > 0) {
|
||||||
}
|
cv.put(KEY_PACKAGE_NAME, packageName);
|
||||||
|
ourDatabase.insert(DATABASE_TABLE, null, cv);
|
||||||
public long update(String packageName, boolean isEnabled) {
|
} else {
|
||||||
ContentValues cvUpdate = new ContentValues();
|
ourDatabase.update(DATABASE_TABLE, cv, KEY_PACKAGE_NAME + "=?",new String[]{packageName});
|
||||||
cvUpdate.put(KEY_IS_ENABLED, isEnabled?"true":"false");
|
}
|
||||||
return ourDatabase.update(DATABASE_TABLE,cvUpdate,KEY_PACKAGE_NAME + "=?",new String[]{packageName});
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean exists(String packageName) {
|
|
||||||
String[] columns = new String []{KEY_ROW_ID};
|
|
||||||
Cursor res = ourDatabase.query(DATABASE_TABLE,columns,KEY_PACKAGE_NAME + " =? ",new String[]{packageName},null,null,null);
|
|
||||||
int count = res.getCount();
|
|
||||||
res.close();
|
res.close();
|
||||||
return (count != 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isEnabled(String packageName){
|
public boolean isEnabled(String packageName) {
|
||||||
String[] columns = new String []{KEY_IS_ENABLED};
|
String[] columns = new String []{KEY_IS_ENABLED};
|
||||||
Cursor res = ourDatabase.query(DATABASE_TABLE,columns,KEY_PACKAGE_NAME + " =? ",new String[]{packageName},null,null,null);
|
Cursor res = ourDatabase.query(DATABASE_TABLE,columns,KEY_PACKAGE_NAME + " =? ",new String[]{packageName},null,null,null);
|
||||||
boolean result = true; //Apps are enabled by default
|
boolean result;
|
||||||
if (res.getCount() > 0) {
|
if (res.getCount() > 0) {
|
||||||
res.moveToFirst();
|
res.moveToFirst();
|
||||||
result = (res.getString(res.getColumnIndex(KEY_IS_ENABLED))).equals("true");
|
result = (res.getString(res.getColumnIndex(KEY_IS_ENABLED))).equals("true");
|
||||||
|
} else {
|
||||||
|
result = getDefaultStatus(packageName);
|
||||||
}
|
}
|
||||||
res.close();
|
res.close();
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void delete(String packageName){
|
private boolean getDefaultStatus(String packageName) {
|
||||||
ourDatabase.delete(DATABASE_TABLE,KEY_PACKAGE_NAME + " =? ",new String[]{packageName} );
|
return !disabledByDefault.contains(packageName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -22,142 +22,144 @@ package org.kde.kdeconnect.Plugins.NotificationsPlugin;
|
|||||||
|
|
||||||
import android.content.pm.ApplicationInfo;
|
import android.content.pm.ApplicationInfo;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.database.Cursor;
|
import android.content.res.Resources;
|
||||||
|
import android.graphics.Bitmap;
|
||||||
|
import android.graphics.Canvas;
|
||||||
|
import android.graphics.drawable.BitmapDrawable;
|
||||||
|
import android.graphics.drawable.Drawable;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.support.v7.app.ActionBarActivity;
|
import android.support.v7.app.ActionBarActivity;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
import android.widget.AdapterView;
|
import android.widget.AdapterView;
|
||||||
import android.widget.ArrayAdapter;
|
import android.widget.BaseAdapter;
|
||||||
|
import android.widget.CheckedTextView;
|
||||||
import android.widget.ListView;
|
import android.widget.ListView;
|
||||||
|
|
||||||
import org.kde.kdeconnect.BackgroundService;
|
import org.kde.kdeconnect.BackgroundService;
|
||||||
|
import org.kde.kdeconnect.Helpers.StringsHelper;
|
||||||
import org.kde.kdeconnect_tp.R;
|
import org.kde.kdeconnect_tp.R;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Comparator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class NotificationFilterActivity extends ActionBarActivity {
|
public class NotificationFilterActivity extends ActionBarActivity {
|
||||||
|
|
||||||
private AppDatabase appDatabase;
|
AppDatabase appDatabase;
|
||||||
|
|
||||||
|
static class AppListInfo {
|
||||||
|
String pkg;
|
||||||
|
String name;
|
||||||
|
Drawable icon;
|
||||||
|
boolean isEnabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
AppListInfo[] apps;
|
||||||
|
|
||||||
|
class AppListAdapter extends BaseAdapter {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getCount() {
|
||||||
|
return apps.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AppListInfo getItem(int position) {
|
||||||
|
return apps[position];
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getItemId(int position) {
|
||||||
|
return position;
|
||||||
|
}
|
||||||
|
|
||||||
|
public View getView(int position, View view, ViewGroup parent) {
|
||||||
|
if (view == null) {
|
||||||
|
LayoutInflater inflater = getLayoutInflater();
|
||||||
|
view = inflater.inflate(android.R.layout.simple_list_item_multiple_choice, null, true);
|
||||||
|
}
|
||||||
|
CheckedTextView checkedTextView = (CheckedTextView)view;
|
||||||
|
checkedTextView.setText(apps[position].name);
|
||||||
|
checkedTextView.setCompoundDrawablesWithIntrinsicBounds(apps[position].icon, null, null, null);
|
||||||
|
checkedTextView.setCompoundDrawablePadding((int)(8*getResources().getDisplayMetrics().density));
|
||||||
|
|
||||||
|
return view;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
setContentView(R.layout.activity_notification_filter);
|
setContentView(R.layout.activity_notification_filter);
|
||||||
final ListView listView = (ListView)findViewById(R.id.lvFilterApps);
|
appDatabase = new AppDatabase(NotificationFilterActivity.this);
|
||||||
appDatabase = new AppDatabase(this);
|
|
||||||
|
|
||||||
deleteUninstalledApps();
|
new Thread(new Runnable() {
|
||||||
addNewlyInstalledApps();
|
@Override
|
||||||
|
public void run() {
|
||||||
|
|
||||||
appDatabase.open();
|
PackageManager packageManager = getPackageManager();
|
||||||
Cursor res = appDatabase.getAllApplications();
|
List<ApplicationInfo> appList = packageManager.getInstalledApplications(0);
|
||||||
res.moveToFirst();
|
int count = appList.size();
|
||||||
|
|
||||||
String[] appName = new String[res.getCount()];
|
apps = new AppListInfo[count];
|
||||||
final String[] pkgName = new String[res.getCount()];
|
appDatabase.open();
|
||||||
Boolean[] isFiltered = new Boolean[res.getCount()];
|
for (int i = 0; i < count; i++) {
|
||||||
|
ApplicationInfo appInfo = appList.get(i);
|
||||||
|
apps[i] = new AppListInfo();
|
||||||
|
apps[i].pkg = appInfo.packageName;
|
||||||
|
apps[i].name = appInfo.loadLabel(packageManager).toString();
|
||||||
|
apps[i].icon = resizeIcon(appInfo.loadIcon(packageManager), 48);
|
||||||
|
apps[i].isEnabled = appDatabase.isEnabled(appInfo.packageName);
|
||||||
|
}
|
||||||
|
appDatabase.close();
|
||||||
|
|
||||||
int i = 0;
|
Arrays.sort(apps, new Comparator<AppListInfo>() {
|
||||||
while(!res.isAfterLast()){
|
@Override
|
||||||
appName[i] = res.getString(res.getColumnIndex(AppDatabase.KEY_NAME));
|
public int compare(AppListInfo lhs, AppListInfo rhs) {
|
||||||
pkgName[i] = res.getString(res.getColumnIndex(AppDatabase.KEY_PACKAGE_NAME));
|
return StringsHelper.compare(lhs.name, rhs.name);
|
||||||
isFiltered[i] = res.getString(res.getColumnIndex(AppDatabase.KEY_IS_ENABLED)).equals("true");
|
}
|
||||||
res.moveToNext();
|
});
|
||||||
i++;
|
|
||||||
}
|
|
||||||
res.close();
|
|
||||||
appDatabase.close();
|
|
||||||
|
|
||||||
ArrayAdapter<String> adapter = new ArrayAdapter<>(this,
|
runOnUiThread(new Runnable() {
|
||||||
android.R.layout.simple_list_item_multiple_choice, android.R.id.text1, appName);
|
@Override
|
||||||
|
public void run() {
|
||||||
|
displayAppList();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}).start();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void displayAppList() {
|
||||||
|
|
||||||
|
final ListView listView = (ListView) findViewById(R.id.lvFilterApps);
|
||||||
|
AppListAdapter adapter = new AppListAdapter();
|
||||||
listView.setAdapter(adapter);
|
listView.setAdapter(adapter);
|
||||||
listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
|
listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
|
||||||
for (i = 0 ; i < isFiltered.length; i++){
|
|
||||||
if (isFiltered[i]) {
|
|
||||||
listView.setItemChecked(i, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
|
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
|
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
|
||||||
boolean checked = listView.isItemChecked(i);
|
boolean checked = listView.isItemChecked(i);
|
||||||
//Log.e("NotificationFilterActivity", pkgName[i] + ":" + checked);
|
|
||||||
appDatabase.open();
|
appDatabase.open();
|
||||||
appDatabase.update(pkgName[i], checked);
|
appDatabase.setEnabled(apps[i].pkg, checked);
|
||||||
appDatabase.close();
|
appDatabase.close();
|
||||||
|
apps[i].isEnabled = checked;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
for (int i = 0 ; i < apps.length; i++) {
|
||||||
|
listView.setItemChecked(i, apps[i].isEnabled);
|
||||||
// Delete apps from database which are uninstalled
|
|
||||||
private void deleteUninstalledApps(){
|
|
||||||
Cursor res;
|
|
||||||
appDatabase.open();
|
|
||||||
res = appDatabase.getAllApplications();
|
|
||||||
if (res != null) {
|
|
||||||
res.moveToFirst();
|
|
||||||
while (!res.isAfterLast()) {
|
|
||||||
String packageName = res.getString(res.getColumnIndex(AppDatabase.KEY_PACKAGE_NAME));
|
|
||||||
if (!isPackageInstalled(packageName)) {
|
|
||||||
appDatabase.delete(packageName);
|
|
||||||
}
|
|
||||||
res.moveToNext();
|
|
||||||
}
|
|
||||||
res.close();
|
|
||||||
}
|
|
||||||
appDatabase.close();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// Adding newly installed apps in database
|
|
||||||
private void addNewlyInstalledApps() {
|
|
||||||
|
|
||||||
List<ApplicationInfo> PackList = getPackageManager().getInstalledApplications(0);
|
|
||||||
appDatabase.open();
|
|
||||||
|
|
||||||
for (int i=0; i < PackList.size(); i++)
|
|
||||||
{
|
|
||||||
ApplicationInfo PackInfo = PackList.get(i);
|
|
||||||
|
|
||||||
String appName = PackInfo.loadLabel(getPackageManager()).toString();
|
|
||||||
String packageName = PackInfo.packageName;
|
|
||||||
|
|
||||||
if ( (PackInfo.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0 ) {
|
|
||||||
|
|
||||||
if (!appDatabase.exists(packageName)) {
|
|
||||||
appDatabase.create(appName, packageName, true);
|
|
||||||
}
|
|
||||||
//Log.e("App FLAG_UPDATED_SYSTEM_APP: " + Integer.toString(i), appName);
|
|
||||||
|
|
||||||
} else if ( (PackInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
|
|
||||||
|
|
||||||
//ignore these apps
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
if (!appDatabase.exists(packageName)) {
|
|
||||||
appDatabase.create(appName, packageName, true);
|
|
||||||
}
|
|
||||||
//Log.e("App : " + Integer.toString(i), appName);
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
appDatabase.close();
|
listView.setVisibility(View.VISIBLE);
|
||||||
|
findViewById(R.id.spinner).setVisibility(View.GONE);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isPackageInstalled(String packageName){
|
|
||||||
PackageManager pm = getPackageManager();
|
|
||||||
try {
|
|
||||||
pm.getPackageInfo(packageName, PackageManager.GET_META_DATA);
|
|
||||||
} catch (Exception e) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onStart() {
|
protected void onStart() {
|
||||||
super.onStart();
|
super.onStart();
|
||||||
@@ -170,4 +172,19 @@ public class NotificationFilterActivity extends ActionBarActivity {
|
|||||||
BackgroundService.removeGuiInUseCounter(this);
|
BackgroundService.removeGuiInUseCounter(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Drawable resizeIcon(Drawable icon, int maxSize) {
|
||||||
|
Resources res = getResources();
|
||||||
|
|
||||||
|
//Convert to display pixels
|
||||||
|
maxSize = (int)(maxSize*res.getDisplayMetrics().density);
|
||||||
|
|
||||||
|
Bitmap bitmap = Bitmap.createBitmap(maxSize, maxSize, Bitmap.Config.ARGB_8888);
|
||||||
|
Canvas canvas = new Canvas(bitmap);
|
||||||
|
icon.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
|
||||||
|
icon.draw(canvas);
|
||||||
|
|
||||||
|
return new BitmapDrawable(res, bitmap);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -170,11 +170,6 @@ public class NotificationsPlugin extends Plugin implements NotificationReceiver.
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (packageName.equals("com.google.android.googlequicksearchbox")) {
|
|
||||||
//HACK: Hide Google Now notifications that keep constantly popping up (and without text because we don't know how to read them properly)
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
NetworkPackage np = new NetworkPackage(PACKAGE_TYPE_NOTIFICATION);
|
NetworkPackage np = new NetworkPackage(PACKAGE_TYPE_NOTIFICATION);
|
||||||
|
|
||||||
if (packageName.equals("org.kde.kdeconnect_tp"))
|
if (packageName.equals("org.kde.kdeconnect_tp"))
|
||||||
|
Reference in New Issue
Block a user