diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index cdf084a..a397742 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -43,6 +43,18 @@ android:name="net.headlezz.notificationlogger.logger.NotificationProvider" android:exported="true" /> + + + + + + + + + diff --git a/app/src/main/java/net/headlezz/notificationlogger/DatabaseUtils.java b/app/src/main/java/net/headlezz/notificationlogger/DatabaseUtils.java index 045a774..cc51b79 100644 --- a/app/src/main/java/net/headlezz/notificationlogger/DatabaseUtils.java +++ b/app/src/main/java/net/headlezz/notificationlogger/DatabaseUtils.java @@ -8,6 +8,7 @@ import net.headlezz.notificationlogger.logger.BlacklistItem; import net.headlezz.notificationlogger.logger.BlacklistTable; import net.headlezz.notificationlogger.logger.LoggedNotification; import net.headlezz.notificationlogger.logger.Logged_notificationTable; +import net.headlezz.notificationlogger.widget.WidgetUtils; public class DatabaseUtils { @@ -16,6 +17,7 @@ public class DatabaseUtils { Logged_notificationTable.CONTENT_URI, Logged_notificationTable.getContentValues(ln, false) ); + WidgetUtils.notifyWidgetsUpdate(context); } public static LoggedNotification getNotificationById(Context context, long id) { @@ -31,6 +33,7 @@ public class DatabaseUtils { // there are no notifications with negative ids, so we use this to select all rows String whereClause = Logged_notificationTable.FIELD_NOTIFICATION_ID + " != -1"; resolver.delete(Logged_notificationTable.CONTENT_URI, whereClause, new String[0]); + WidgetUtils.notifyWidgetsUpdate(context); } public static boolean isPackageBlacklisted(Context context, String packageName) { @@ -71,7 +74,7 @@ public class DatabaseUtils { context.getContentResolver().delete( BlacklistTable.CONTENT_URI, BlacklistTable.FIELD_PACKAGE_NAME + " = ?", - new String[] {packageName} + new String[]{packageName} ); } @@ -79,7 +82,8 @@ public class DatabaseUtils { context.getContentResolver().delete( Logged_notificationTable.CONTENT_URI, Logged_notificationTable.FIELD__ID + " = ?", - new String[] {String.valueOf(id)} + new String[]{String.valueOf(id)} ); + WidgetUtils.notifyWidgetsUpdate(context); } } diff --git a/app/src/main/java/net/headlezz/notificationlogger/widget/ListWidgetProvider.java b/app/src/main/java/net/headlezz/notificationlogger/widget/ListWidgetProvider.java new file mode 100644 index 0000000..20f6042 --- /dev/null +++ b/app/src/main/java/net/headlezz/notificationlogger/widget/ListWidgetProvider.java @@ -0,0 +1,55 @@ +package net.headlezz.notificationlogger.widget; + +import android.app.PendingIntent; +import android.appwidget.AppWidgetManager; +import android.appwidget.AppWidgetProvider; +import android.content.Context; +import android.content.Intent; +import android.net.Uri; +import android.widget.RemoteViews; + +import net.headlezz.notificationlogger.MainActivity; +import net.headlezz.notificationlogger.R; + +public class ListWidgetProvider extends AppWidgetProvider { + + public static final String SHOW_NOTIFICATION_ACTION = "net.headlezz.notificationlogger.listwidget.SHOW_NOTIFICATION_ACTION"; + + @Override + public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { + for(int widgetId : appWidgetIds) { + RemoteViews rvs = updateWidgetListView(context, widgetId); + appWidgetManager.updateAppWidget(appWidgetIds, rvs); + } + super.onUpdate(context, appWidgetManager, appWidgetIds); + } + + private RemoteViews updateWidgetListView(Context context, int appWidgetId) { + RemoteViews rvs = new RemoteViews(context.getPackageName(), R.layout.widget_list); + + Intent serviceIntent = new Intent(context, ListWidgetService.class); + serviceIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId); + serviceIntent.setData(Uri.parse(serviceIntent.toUri(Intent.URI_INTENT_SCHEME))); + + Intent showNotificationIntent = new Intent(context, ListWidgetProvider.class); + showNotificationIntent.setAction(ListWidgetProvider.SHOW_NOTIFICATION_ACTION); + PendingIntent pi = PendingIntent.getBroadcast(context, 0, showNotificationIntent, PendingIntent.FLAG_UPDATE_CURRENT); + rvs.setPendingIntentTemplate(R.id.list_widget_listView, pi); + + rvs.setRemoteAdapter(R.id.list_widget_listView, serviceIntent); + rvs.setEmptyView(R.id.list_widget_listView, R.id.list_widget_empty_view); + + return rvs; + } + + // receives the intent broadcast from list items + @Override + public void onReceive(Context context, Intent intent) { + if (intent.getAction().equals(SHOW_NOTIFICATION_ACTION)) { + Intent mainActivityIntent = new Intent(context, MainActivity.class); + mainActivityIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + context.startActivity(mainActivityIntent); + } + super.onReceive(context, intent); + } +} diff --git a/app/src/main/java/net/headlezz/notificationlogger/widget/ListWidgetService.java b/app/src/main/java/net/headlezz/notificationlogger/widget/ListWidgetService.java new file mode 100644 index 0000000..60ff251 --- /dev/null +++ b/app/src/main/java/net/headlezz/notificationlogger/widget/ListWidgetService.java @@ -0,0 +1,13 @@ +package net.headlezz.notificationlogger.widget; + +import android.appwidget.AppWidgetManager; +import android.content.Intent; +import android.widget.RemoteViewsService; + +public class ListWidgetService extends RemoteViewsService { + @Override + public RemoteViewsFactory onGetViewFactory(Intent intent) { + int appWidgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID); + return new ListWidgetViewFactory(getApplicationContext(), appWidgetId); + } +} diff --git a/app/src/main/java/net/headlezz/notificationlogger/widget/ListWidgetViewFactory.java b/app/src/main/java/net/headlezz/notificationlogger/widget/ListWidgetViewFactory.java new file mode 100644 index 0000000..eee7da8 --- /dev/null +++ b/app/src/main/java/net/headlezz/notificationlogger/widget/ListWidgetViewFactory.java @@ -0,0 +1,100 @@ +package net.headlezz.notificationlogger.widget; + +import android.content.Context; +import android.content.Intent; +import android.database.Cursor; +import android.graphics.Typeface; +import android.text.SpannableString; +import android.text.format.DateUtils; +import android.text.style.StyleSpan; +import android.widget.RemoteViews; +import android.widget.RemoteViewsService; + +import net.headlezz.notificationlogger.R; +import net.headlezz.notificationlogger.logger.LoggedNotification; +import net.headlezz.notificationlogger.logger.Logged_notificationTable; + +import timber.log.Timber; + +public class ListWidgetViewFactory implements RemoteViewsService.RemoteViewsFactory { + + int mAppWidgetId; + Context mContext; + + Cursor mCursor; + + public ListWidgetViewFactory(Context context, int appWidgetId) { + mContext = context; + this.mAppWidgetId = appWidgetId; + } + + + @Override + public void onCreate() { /** ignored **/ } + + @Override + public void onDataSetChanged() { + Timber.d("ON DATA SET CHANGED"); + if(mCursor != null) { + mCursor.close(); + } + mCursor = mContext.getContentResolver().query(Logged_notificationTable.CONTENT_URI, null, null, null, Logged_notificationTable.FIELD_DATE + " DESC"); + } + + @Override + public void onDestroy() { + if(mCursor != null) + mCursor.close(); + } + + @Override + public int getCount() { + if(mCursor == null) { + Timber.d("cursor is null"); + return 0; + } + return mCursor.getCount(); + } + + @Override + public RemoteViews getViewAt(int position) { + RemoteViews rv = new RemoteViews(mContext.getPackageName(), R.layout.widget_list_item); + + mCursor.moveToPosition(position); + LoggedNotification notification = Logged_notificationTable.getRow(mCursor, false); + + rv.setTextViewText(R.id.widget_list_item_title, notification.appName); + + String title = notification.title + ":"; + SpannableString titleSpan = new SpannableString(title + " " + notification.message); + titleSpan.setSpan(new StyleSpan(Typeface.BOLD), 0, title.length(), 0); + + rv.setTextViewText(R.id.widget_list_item_notification, titleSpan); + rv.setTextViewText(R.id.widget_list_item_date, DateUtils.formatDateTime(mContext, notification.date, DateUtils.FORMAT_ABBREV_ALL | DateUtils.FORMAT_SHOW_TIME | DateUtils.FORMAT_SHOW_DATE)); + + Intent intent = new Intent(); + intent.putExtra(Logged_notificationTable.FIELD__ID, notification.id); + rv.setOnClickFillInIntent(R.id.widget_list_item, intent); + return rv; + } + + @Override + public RemoteViews getLoadingView() { + return null; + } + + @Override + public int getViewTypeCount() { + return 1; + } + + @Override + public long getItemId(int position) { + return position; + } + + @Override + public boolean hasStableIds() { + return true; + } +} diff --git a/app/src/main/java/net/headlezz/notificationlogger/widget/WidgetUtils.java b/app/src/main/java/net/headlezz/notificationlogger/widget/WidgetUtils.java new file mode 100644 index 0000000..12d5f6c --- /dev/null +++ b/app/src/main/java/net/headlezz/notificationlogger/widget/WidgetUtils.java @@ -0,0 +1,17 @@ +package net.headlezz.notificationlogger.widget; + +import android.appwidget.AppWidgetManager; +import android.content.ComponentName; +import android.content.Context; + +import net.headlezz.notificationlogger.R; + +public class WidgetUtils { + + public static void notifyWidgetsUpdate(Context context) { + AppWidgetManager manager = AppWidgetManager.getInstance(context); + int[] appWidgetIds = manager.getAppWidgetIds(new ComponentName(context, ListWidgetProvider.class)); + manager.notifyAppWidgetViewDataChanged(appWidgetIds, R.id.list_widget_listView); + } + +} diff --git a/app/src/main/res/drawable/widget_list_preview.png b/app/src/main/res/drawable/widget_list_preview.png new file mode 100644 index 0000000..1a80c66 Binary files /dev/null and b/app/src/main/res/drawable/widget_list_preview.png differ diff --git a/app/src/main/res/layout/widget_list.xml b/app/src/main/res/layout/widget_list.xml new file mode 100644 index 0000000..58170e4 --- /dev/null +++ b/app/src/main/res/layout/widget_list.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/widget_list_item.xml b/app/src/main/res/layout/widget_list_item.xml new file mode 100644 index 0000000..f78f971 --- /dev/null +++ b/app/src/main/res/layout/widget_list_item.xml @@ -0,0 +1,51 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index ce6f3dd..e9b25b7 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -83,6 +83,8 @@ Show Open folder No file browser installed. + Latest Notifications + No notifications logged. Show more info diff --git a/app/src/main/res/xml/widget_info.xml b/app/src/main/res/xml/widget_info.xml new file mode 100644 index 0000000..33fe1b7 --- /dev/null +++ b/app/src/main/res/xml/widget_info.xml @@ -0,0 +1,9 @@ + + + \ No newline at end of file