package com.reindeercrafts.notificationpeek; import android.app.Notification; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.SharedPreferences; import android.preference.PreferenceManager; import android.service.notification.NotificationListenerService; import android.service.notification.StatusBarNotification; import com.reindeercrafts.notificationpeek.blacklist.AppList; import com.reindeercrafts.notificationpeek.peek.NotificationPeek; import com.reindeercrafts.notificationpeek.settings.PreferenceKeys; import com.reindeercrafts.notificationpeek.utils.AccessChecker; /** * Notification listener service. Implemented onNotificationPosted * method so that whenever a notification is posted, it'll be saved * into database. * <p/> * Created by zhelu on 2/21/14. */ public class NotificationService extends NotificationListenerService { private static final String TAG = NotificationService.class.getSimpleName(); private static final int INVAID_ID = -1; public static final String ACTION_DISMISS_NOTIFICATION = NotificationActionReceiver.class.getSimpleName() + ".dismiss_notification"; public static final String ACTION_PREFERENCE_CHANGED = NotificationService.class.getSimpleName() + ".preference_changed"; public static final String ACTION_QUIET_HOUR_CHANGE = NotificationService.class.getSimpleName() + ".quiet_hour_changed"; public static final String EXTRA_PACKAGE_NAME = "PackageName"; public static final String EXTRA_NOTIFICATION_ID = "NotificationId"; public static final String EXTRA_NOTIFICATION_TAG = "NotificationTag"; private int mPeekTimeoutMultiplier; private int mSensorTimeoutMultiplier; private boolean mShowContent; private NotificationHub mNotificationHub; private NotificationPeek mNotificationPeek; private NotificationActionReceiver mReceiver; private AppList mAppList; @Override public void onCreate() { super.onCreate(); mNotificationHub = NotificationHub.getInstance(); mNotificationPeek = new NotificationPeek(mNotificationHub, this); SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this); // Retrieve user specified peek timeout. mPeekTimeoutMultiplier = Integer.parseInt(preferences.getString(PreferenceKeys.PREF_PEEK_TIMEOUT, "1")); // Does user select always listening? mSensorTimeoutMultiplier = Integer.parseInt(preferences.getString(PreferenceKeys.PREF_SENSOR_TIMEOUT, "1")); // Does user select always show content? mShowContent = preferences.getBoolean(PreferenceKeys.PREF_ALWAYS_SHOW_CONTENT, false); mAppList = AppList.getInstance(this); registerNotificationActionReceiver(); } @Override public void onNotificationPosted(StatusBarNotification sbn) { Notification postedNotification = sbn.getNotification(); if (postedNotification.tickerText == null || sbn.isOngoing() || !sbn.isClearable() || isInBlackList(sbn)) { return; } if (mAppList.isInQuietHour(sbn.getPostTime())) { // The first notification arrived during quiet hour will unregister all sensor listeners. mNotificationPeek.unregisterEventListeners(); return; } mNotificationHub.addNotification(sbn); if (AccessChecker.isDeviceAdminEnabled(this)) { mNotificationPeek .showNotification(sbn, false, mPeekTimeoutMultiplier, mSensorTimeoutMultiplier, mShowContent); } } @Override public void onNotificationRemoved(StatusBarNotification sbn) { mNotificationHub.removeNotification(sbn); } @Override public void onDestroy() { super.onDestroy(); mNotificationPeek.unregisterScreenReceiver(); unregisterReceiver(mReceiver); } /** * Check if the given package name is in black list or its priority is low. * There are some notifications that contain ticker text or content, * but they are actually not useful and not from user applications. * * @param notification Given StatusBarNotification object. * @return True if the package is in black list, false otherwise. */ private boolean isInBlackList(StatusBarNotification notification) { return notification.getNotification().priority < Notification.PRIORITY_DEFAULT || mAppList.shouldPeekWakeUp(notification); } private void registerNotificationActionReceiver() { mReceiver = new NotificationActionReceiver(); IntentFilter intentFilter = new IntentFilter(); intentFilter.addAction(ACTION_DISMISS_NOTIFICATION); intentFilter.addAction(ACTION_PREFERENCE_CHANGED); intentFilter.addAction(ACTION_QUIET_HOUR_CHANGE); // Receive wallpaper change action to inform NotificationPeek to update background. intentFilter.addAction(Intent.ACTION_WALLPAPER_CHANGED); registerReceiver(mReceiver, intentFilter); } public class NotificationActionReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); if (action.equals(ACTION_DISMISS_NOTIFICATION)) { String packageName = intent.getStringExtra(EXTRA_PACKAGE_NAME); String tag = intent.getStringExtra(EXTRA_NOTIFICATION_TAG); int id = intent.getIntExtra(EXTRA_NOTIFICATION_ID, INVAID_ID); cancelNotification(packageName, tag, id); } else if (action.equals(ACTION_PREFERENCE_CHANGED)) { // Update user preferences. String changedKey = intent.getStringExtra(PreferenceKeys.INTENT_ACTION_KEY); String newValue = intent.getStringExtra(PreferenceKeys.INTENT_ACTION_NEW_VALUE); if (changedKey.equals(PreferenceKeys.PREF_PEEK_TIMEOUT)) { mPeekTimeoutMultiplier = Integer.parseInt(newValue); } else if (changedKey.equals(PreferenceKeys.PREF_SENSOR_TIMEOUT)) { mSensorTimeoutMultiplier = Integer.parseInt(newValue); } else if (changedKey.equals(PreferenceKeys.PREF_ALWAYS_SHOW_CONTENT)) { mShowContent = Boolean.parseBoolean(newValue); } else if (changedKey.equals(PreferenceKeys.PREF_BACKGROUND) || changedKey.equals(PreferenceKeys.PREF_DIM) || changedKey.equals(PreferenceKeys.PREF_RADIUS)) { mNotificationPeek.updateBackgroundImageView(); } } else if (action.equals(Intent.ACTION_WALLPAPER_CHANGED)) { // Wallpaper has been changed, update Peek. mNotificationPeek.updateBackgroundImageView(); } else if (action.equals(ACTION_QUIET_HOUR_CHANGE)) { // Quiet hour has been changed, update AppList settings. mAppList.updateQuietHour(); } } } }