diff --git a/AndroidManifest.xml b/AndroidManifest.xml index 6cbe4a78..bd649760 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -185,7 +185,15 @@ - + + + diff --git a/res/layout/activity_notification_filter.xml b/res/layout/activity_notification_filter.xml new file mode 100644 index 00000000..66442b08 --- /dev/null +++ b/res/layout/activity_notification_filter.xml @@ -0,0 +1,22 @@ + + + + + + + diff --git a/res/values/strings.xml b/res/values/strings.xml index 8d154b35..be25f6a1 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -102,6 +102,8 @@ Add devices by IP Noisy notifications Vibrate and play a sound when receiving a file + Notification filter + Notifications will be synchronized for selected applications Internal storage All files SD card %d @@ -120,7 +122,6 @@ 1 minute 2 minutes - 10000000 20000000 diff --git a/src/org/kde/kdeconnect/Plugins/NotificationsPlugin/AppDatabase.java b/src/org/kde/kdeconnect/Plugins/NotificationsPlugin/AppDatabase.java new file mode 100644 index 00000000..2dbc249d --- /dev/null +++ b/src/org/kde/kdeconnect/Plugins/NotificationsPlugin/AppDatabase.java @@ -0,0 +1,134 @@ +/* + * Copyright 2015 Vineet Garg + * + * This program 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 2 of + * the License or (at your option) version 3 or any later version + * accepted by the membership of KDE e.V. (or its successor approved + * by the membership of KDE e.V.), which shall act as a proxy + * defined in Section 14 of version 3 of the license. + * + * This program 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 this program. If not, see . +*/ + +package org.kde.kdeconnect.Plugins.NotificationsPlugin; + +import android.content.ContentValues; +import android.content.Context; +import android.database.Cursor; +import android.database.sqlite.SQLiteDatabase; +import android.database.sqlite.SQLiteOpenHelper; +import android.util.Log; + +public class AppDatabase { + + public static final String KEY_ROW_ID = "id"; + public static final String KEY_NAME = "app"; + public static final String KEY_PACKAGE_NAME = "packageName"; + public static final String KEY_IS_FILTERED = "isFiltered"; + + + private static final String DATABASE_NAME = "Applications"; + private static final String DATABASE_TABLE = "Applications"; + private static final int DATABASE_VESRION = 1; + + private Context ourContext; + private SQLiteDatabase ourDatabase; + private DbHelper ourHelper; + + public AppDatabase(Context c) { + ourContext = c; + } + + private static class DbHelper extends SQLiteOpenHelper{ + + public DbHelper(Context context) { + super(context, DATABASE_NAME, null, DATABASE_VESRION); + } + + @Override + public void onCreate(SQLiteDatabase db) { + db.execSQL("CREATE TABLE " + DATABASE_TABLE + "(" + KEY_ROW_ID + " INTEGER PRIMARY KEY AUTOINCREMENT," + + KEY_NAME + " TEXT NOT NULL, " + KEY_PACKAGE_NAME + " TEXT NOT NULL, " + KEY_IS_FILTERED + " TEXT NOT NULL); "); + } + + @Override + public void onUpgrade(SQLiteDatabase db, int i, int i2) { + db.execSQL("DROP TABLE IF EXISTS "+ DATABASE_TABLE); + onCreate(db); + + } + + } + + public AppDatabase open(){ + ourHelper = new DbHelper(ourContext); + ourDatabase = ourHelper.getWritableDatabase(); + return this; + } + + + public void close(){ + ourHelper.close(); + } + + public Cursor getAllApplications() + { + String[] columns = new String []{KEY_ROW_ID,KEY_NAME,KEY_PACKAGE_NAME,KEY_IS_FILTERED} ; + Cursor res = ourDatabase.query(DATABASE_TABLE,columns,null,null,null,null,KEY_NAME); + return res; + } + + + public long createEntry(String app, String packagename,String isFiltered) { + ContentValues cv = new ContentValues(); + cv.put(KEY_NAME,app); + cv.put(KEY_PACKAGE_NAME,packagename); + cv.put(KEY_IS_FILTERED,isFiltered); + return ourDatabase.insert(DATABASE_TABLE,null,cv); + } + + public long updateEntry(String packageName, String value) { + ContentValues cvUpdate = new ContentValues(); + cvUpdate.put(KEY_IS_FILTERED,value); + return ourDatabase.update(DATABASE_TABLE,cvUpdate,KEY_PACKAGE_NAME + "=?",new String[]{packageName}); + } + + public boolean checkEntry(String packageName) { + String[] columns = new String []{KEY_ROW_ID,KEY_NAME,KEY_PACKAGE_NAME,KEY_IS_FILTERED} ; + Cursor res = ourDatabase.query(DATABASE_TABLE,columns,KEY_PACKAGE_NAME + " =? ",new String[]{packageName},null,null,null); + if (res.getCount() != 0){ + return true; + }else { + return false; + } + + } + + public boolean isFilterEnabled(String packageName){ + String[] columns = new String []{KEY_ROW_ID,KEY_NAME,KEY_PACKAGE_NAME,KEY_IS_FILTERED} ; + Cursor res = ourDatabase.query(DATABASE_TABLE,columns,KEY_PACKAGE_NAME + " =? ",new String[]{packageName},null,null,null); + if (res.getCount() > 0){ + res.moveToFirst(); + if ((res.getString(res.getColumnIndex(KEY_IS_FILTERED))).equals("true")){ + return true; + }else{ + return false; + } + }else{ + return true; + } + } + public void delete(String packageName){ + ourDatabase.delete(DATABASE_TABLE,KEY_PACKAGE_NAME + " =? ",new String[]{packageName} ); + } + + +} diff --git a/src/org/kde/kdeconnect/Plugins/NotificationsPlugin/NotificationFilterActivity.java b/src/org/kde/kdeconnect/Plugins/NotificationsPlugin/NotificationFilterActivity.java new file mode 100644 index 00000000..0beff93b --- /dev/null +++ b/src/org/kde/kdeconnect/Plugins/NotificationsPlugin/NotificationFilterActivity.java @@ -0,0 +1,171 @@ +/* + * Copyright 2015 Vineet Garg + * + * This program 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 2 of + * the License or (at your option) version 3 or any later version + * accepted by the membership of KDE e.V. (or its successor approved + * by the membership of KDE e.V.), which shall act as a proxy + * defined in Section 14 of version 3 of the license. + * + * This program 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 this program. If not, see . +*/ + +package org.kde.kdeconnect.Plugins.NotificationsPlugin; + +import android.content.pm.ApplicationInfo; +import android.content.pm.PackageManager; +import android.database.Cursor; +import android.support.v7.app.ActionBarActivity; +import android.os.Bundle; +import android.util.Log; +import android.view.View; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.ListView; + +import org.kde.kdeconnect_tp.R; + +import java.util.List; + +public class NotificationFilterActivity extends ActionBarActivity { + + ListView listView; + AppDatabase appDatabase; + String[] appName; + String[][] database; + int i=0; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_notification_filter); + listView = (ListView)findViewById(R.id.lvFilterApps); + appDatabase = new AppDatabase(this); + + deleteUninstalledApps(); + addNewlyInstalledApps(); + + appDatabase.open(); + Cursor res = appDatabase.getAllApplications(); + res.moveToFirst(); + + appName = new String[res.getCount()]; + database = new String [res.getCount()][3]; + + while(!res.isAfterLast()){ + appName[i] = res.getString(res.getColumnIndex(AppDatabase.KEY_NAME)); + database[i][0] = res.getString(res.getColumnIndex(AppDatabase.KEY_NAME)); + database[i][1] = res.getString(res.getColumnIndex(AppDatabase.KEY_PACKAGE_NAME)); + database[i][2] = res.getString(res.getColumnIndex(AppDatabase.KEY_IS_FILTERED)); + + res.moveToNext(); + i++; + } + appDatabase.close(); + + + ArrayAdapter adapter = new ArrayAdapter(this, + android.R.layout.simple_list_item_multiple_choice,android.R.id.text1, appName); + listView.setAdapter(adapter); + listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE); + + for (i=0 ; i adapterView, View view, int i, long l) { + appDatabase.open(); + if (listView.isItemChecked(i)){ + database[i][2] = "true" ; + appDatabase.updateEntry(database[i][1],"true"); + }else{ + database[i][2] = "false"; + appDatabase.updateEntry(database[i][1],"false"); + } + appDatabase.close(); + } + }); + } + + // 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() == false){ + String packageName = res.getString(res.getColumnIndex(AppDatabase.KEY_PACKAGE_NAME)); + if (!isPackageInstalled(packageName)){ + appDatabase.delete(packageName); + } + res.moveToNext(); + } + } + appDatabase.close(); + + } + + // Adding newly installed apps in database + private void addNewlyInstalledApps(){ + + List PackList = getPackageManager().getInstalledApplications(0); + appDatabase.open(); + + for (int i=0; i < PackList.size(); i++) + { + ApplicationInfo PackInfo = PackList.get(i); + + if ( (PackInfo.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0 ) + { + String AppName = PackInfo.loadLabel(getPackageManager()).toString(); + String packageName = PackInfo.packageName; + if (!appDatabase.checkEntry(packageName)){ + appDatabase.createEntry(PackInfo.loadLabel(getPackageManager()).toString(), + PackInfo.packageName, + "true"); + } +// Log.e("App : " + Integer.toString(i), AppName); + }else if ((PackInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0){ + //ignore these apps + }else{ + String packageName = PackInfo.packageName; + if (!appDatabase.checkEntry(packageName)){ + appDatabase.createEntry(PackInfo.loadLabel(getPackageManager()).toString(), + PackInfo.packageName, + "true"); + } + //Log.e("App : " + Integer.toString(i), AppName); + } + } + + appDatabase.close(); + + } + + private boolean isPackageInstalled(String packageName){ + PackageManager pm = getPackageManager(); + try{ + pm.getPackageInfo(packageName,PackageManager.GET_META_DATA); + }catch (Exception e){ + return false; + } + return true; + } + + + + +} diff --git a/src/org/kde/kdeconnect/Plugins/NotificationsPlugin/NotificationsPlugin.java b/src/org/kde/kdeconnect/Plugins/NotificationsPlugin/NotificationsPlugin.java index f54c48f5..ab6383fd 100644 --- a/src/org/kde/kdeconnect/Plugins/NotificationsPlugin/NotificationsPlugin.java +++ b/src/org/kde/kdeconnect/Plugins/NotificationsPlugin/NotificationsPlugin.java @@ -64,7 +64,7 @@ public class NotificationsPlugin extends Plugin implements NotificationReceiver. @Override public boolean hasSettings() { - return false; + return true; } @Override @@ -199,6 +199,7 @@ public class NotificationsPlugin extends Plugin implements NotificationReceiver. public void sendNotification(StatusBarNotification statusBarNotification, boolean requestAnswer) { Notification notification = statusBarNotification.getNotification(); + AppDatabase appDatabase = new AppDatabase(context); if ((notification.flags & Notification.FLAG_FOREGROUND_SERVICE) != 0 || (notification.flags & Notification.FLAG_ONGOING_EVENT) != 0 @@ -207,6 +208,13 @@ public class NotificationsPlugin extends Plugin implements NotificationReceiver. return; } + appDatabase.open(); + if (!appDatabase.isFilterEnabled(statusBarNotification.getPackageName())){ + return; + // we dont want notification from this app + } + appDatabase.close(); + NotificationId id = NotificationId.fromNotification(statusBarNotification); NetworkPackage np = new NetworkPackage(NetworkPackage.PACKAGE_TYPE_NOTIFICATION); diff --git a/src/org/kde/kdeconnect/UserInterface/PluginSettingsActivity.java b/src/org/kde/kdeconnect/UserInterface/PluginSettingsActivity.java index abe1db15..240c16c6 100644 --- a/src/org/kde/kdeconnect/UserInterface/PluginSettingsActivity.java +++ b/src/org/kde/kdeconnect/UserInterface/PluginSettingsActivity.java @@ -23,6 +23,9 @@ package org.kde.kdeconnect.UserInterface; import android.content.Intent; import android.os.Bundle; import android.preference.PreferenceActivity; +import android.util.Log; + +import org.kde.kdeconnect.Plugins.NotificationsPlugin.NotificationFilterActivity; public class PluginSettingsActivity extends PreferenceActivity { @@ -31,7 +34,13 @@ public class PluginSettingsActivity extends PreferenceActivity { super.onCreate(savedInstanceState); String resource_name = getIntent().getStringExtra(Intent.EXTRA_INTENT); - int resource_file = getResources().getIdentifier(resource_name, "xml", getPackageName()); - addPreferencesFromResource(resource_file); + if (resource_name.equals("plugin_notifications_preferences")){ + Intent intent = new Intent(PluginSettingsActivity.this,NotificationFilterActivity.class); + startActivity(intent); + finish(); + }else { + int resource_file = getResources().getIdentifier(resource_name, "xml", getPackageName()); + addPreferencesFromResource(resource_file); + } } }