NotificationListenerService Implementation

Estoy intentando implementar NotificationListnerService que se agrega en Android 4.3 pero no puedo obtener los detalles de la notificación.

Mi código es el siguiente

public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this); mBuilder.setSmallIcon(R.drawable.ic_launcher); mBuilder.setContentTitle("notification test"); mBuilder.setContentText("Notification text"); mBuilder.setAutoCancel(true); Intent resultIntent = new Intent(this, ResultActivity.class); TaskStackBuilder stackBuilder = TaskStackBuilder.create(this); // Adds the back stack for the Intent (but not the Intent itself) stackBuilder.addParentStack(ResultActivity.class); // Adds the Intent that starts the Activity to the top of the stack stackBuilder.addNextIntent(resultIntent); PendingIntent resultPendingIntent = stackBuilder.getPendingIntent( 0, PendingIntent.FLAG_UPDATE_CURRENT ); mBuilder.setContentIntent(resultPendingIntent); NotificationManager manager = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE); manager.notify(1, mBuilder.build()); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); return true; } } public class NotificationListenerTesting extends NotificationListenerService{ public static String TAG = "NotificationListenerTesting"; //private StatusBarNotification[] mStatusBarNotification; @Override public void onCreate(){ super.onCreate(); Log.d(TAG, "Inside on create"); } @Override public IBinder onBind(Intent intent) { return null; } @Override public void onNotificationPosted(StatusBarNotification sbn) { TAG = "onNotificationPosted"; Log.d(TAG, "id = " + sbn.getId() + "Package Name" + sbn.getPackageName() + "Post time = " + sbn.getPostTime() + "Tag = " + sbn.getTag()); } @Override public void onNotificationRemoved(StatusBarNotification sbn) { TAG = "onNotificationRemoved"; Log.d(TAG, "id = " + sbn.getId() + "Package Name" + sbn.getPackageName() + "Post time = " + sbn.getPostTime() + "Tag = " + sbn.getTag()); } } 

El archivo de manifiesto de Android es

                  

pero después de la notificación, haga clic o en la notificación NotificationListenerService no se llama, ¿Qué hay de malo en esto o me extrañó algo? ¿Cómo implementarlo?

Dentro del NotificationListenerService necesita un looper para comunicarse con el hilo de la GUI para que pueda crear una difusión para manejar la interacción de la GUI.

Espero que este ejemplo te ayude.

Debe otorgar acceso a su aplicación para leer notificaciones: “Configuración> Seguridad> Acceso a notificaciones” y verifique su aplicación.

Al menos un problema con su código es que su implementación de onBind ()

No hay necesidad de anular este método. Pero si debe hacerlo, al menos devuelva el IBinder devuelto por la superclase.

 @Override public IBinder onBind(Intent intent) { return super.onBind(intent); } 

Puede ser un poco tarde. Pero hace unos meses también tuve problemas para hacer que NotificationListenerService funcionara.

Desde entonces aprendí cómo implementarlo y sentí la necesidad de construir un tutorial de implementación para ayudar a otros que pasaron por lo mismo que yo.

Si alguien está interesado, revise el proyecto aquí: https://github.com/Chagall/notification-listener-service-example

Espero que ayude a alguien que está luchando con eso.

Sé que es demasiado tarde para responder la pregunta, pero como no pude encontrar Configuración> Sonido y notificaciones -> Acceso a notificaciones, de modo que autorizo ​​el acceso directo a las notificaciones de mi aplicación activando esta intención:

startActivity (nuevo propósito (Settings.ACTION_NOTIFICATION_LISTENER_SETTINGS));

Me encontré con el mismo problema y he encontrado algunas pistas para eso.

NotificationListenerService no se puede ejecutar a menos que llame a bindService() para iniciarlo.

A veces se iniciaba automáticamente cuando habilitaba “Acceso de notificación” y otras veces no.

La notificación que crees no tiene “tickerText”. He encontrado que si la notificación no tiene tickerText, onNotificationPosted no se llama.

En su código, agregue mBuilder.setTicker (“su texto aquí”).

onNotificationPosted ahora se debe llamar suponiendo que el rest de la instalación de NotificationListenerService es copacetic.

Estoy haciendo lo mismo que en GitHub, pero aún así no entraré en la clase de notificación.

 import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.os.IBinder; import android.service.notification.NotificationListenerService; import android.service.notification.StatusBarNotification; import android.util.Log; /** * @author dinesh * */ public class UserNotificationService extends NotificationListenerService { private String TAG = "UserNotificationService"; UserNotificationServiceReceiver notfRcvr; @Override public void onNotificationRemoved(StatusBarNotification sbn) { Log.i(TAG,"********** onNotificationRemoved"); Log.i(TAG,"ID :" + sbn.getId() + "\t" + sbn.getNotification().tickerText +"\t" + sbn.getPackageName()); Intent i = new Intent("de.tu.darmstadt.moodsense.services.Notification"); i.putExtra("notification event", "On notification removed"); sendBroadcast(i); } @Override public IBinder onBind(Intent intent) { return super.onBind(intent); } @Override public void onNotificationPosted(StatusBarNotification sbn) { Log.i(TAG,"********** onNotificationPosted"); Log.i(TAG,"ID :" + sbn.getId() + "\t" + sbn.getNotification().tickerText + "\t" + sbn.getPackageName()); Intent i = new Intent("de.tu.darmstadt.moodsense.services.Notification"); i.putExtra("notification event", "On notification posted"); sendBroadcast(i); } @Override public void onCreate() { super.onCreate(); notfRcvr = new UserNotificationServiceReceiver(); IntentFilter filter = new IntentFilter(); filter.addAction("de.tu.darmstadt.moodsense.services.Notification"); registerReceiver(notfRcvr, filter); } @Override public void onDestroy() { super.onDestroy(); unregisterReceiver(notfRcvr); } class UserNotificationServiceReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { // TODO Auto-generated method stub if(intent.getStringExtra("command").equals("clearall")) { UserNotificationService.this.cancelAllNotifications(); } } } } import java.lang.Thread.State; import java.util.Calendar; import java.util.Date; import java.util.List; import twitter4j.Status; import twitter4j.TwitterException; import de.tu.darmstadt.moodsense.R; import de.tu.darmstadt.moodsense.app.UserMood; import de.tu.darmstadt.moodsense.constants.Constants; import de.tu.darmstadt.moodsense.util.MqttMoodClient; import de.tu.darmstadt.moodsense.util.TwitterMoodUtils; import de.tu.darmstadt.moodsense.util.TwitterUtils; import android.app.AlarmManager; import android.app.Notification; import android.app.NotificationManager; import android.app.PendingIntent; import android.app.Service; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.SharedPreferences; import android.net.ConnectivityManager; import android.net.NetworkInfo; import android.os.IBinder; import android.os.SystemClock; import android.preference.PreferenceManager; import android.support.v4.app.NotificationCompat; import android.util.Log; /** * @author dinesh * Added for V1.1 * Code style based on : https://newcircle.com/s/post/1049/ * tutorial_services_part_1_android_bootcamp_series_2012 * */ public class UserMoodService extends Service{ static final String TAG = "UserMoodService"; public static boolean userMoodSet = false; //declarations for twitter private SharedPreferences prefs; SharedPreferences userPref; String userTwitterMood = ""; String worldTwitterMood = ""; String screenName, userName; int m_counter; long shortMinutes; boolean m_enterMood; int m_myMood; int m_moodIntensity; MqttMoodClient mqc; TwitterMoodUtils tmu; Calendar cal = Calendar.getInstance(); private static final int MY_NOTIFICATION_ID=1; NotificationManager notificationManager; Notification myNotification; UserMoodNotificationReceiver usrMoodNotfnnRcvr; public UserMoodService() { // TODO Auto-generated constructor stub mqc = new MqttMoodClient(); tmu = new TwitterMoodUtils(); } public void reset() { m_myMood = Constants.NUM_MOOD_TYPES; m_moodIntensity = Constants.MILD; m_enterMood = false; m_counter = 0; } @Override public IBinder onBind(Intent arg0) { return null; } @Override public void onTaskRemoved(Intent rootIntent) { // TODO Auto-generated method stub Intent restartService = new Intent(getApplicationContext(),this.getClass()); restartService.setPackage(getPackageName()); PendingIntent restartServicePI = PendingIntent.getService(getApplicationContext(), 1, restartService, PendingIntent.FLAG_ONE_SHOT); AlarmManager alarmService = (AlarmManager)getApplicationContext().getSystemService(Context.ALARM_SERVICE); alarmService.set(AlarmManager.ELAPSED_REALTIME, SystemClock.elapsedRealtime() +100, restartServicePI); } /** (non-Javadoc) * @see android.app.Service#onCreate() */ @Override public void onCreate() { Log.d(TAG, "OnCreation"); //super.onCreate(); usrMoodNotfnnRcvr = new UserMoodNotificationReceiver(); IntentFilter filter = new IntentFilter(); filter.addAction("Notofication Obj"); registerReceiver(usrMoodNotfnnRcvr, filter); } /** (non-Javadoc) * @see android.app.Service#onStartCommand(android.content.Intent, int, int) */ @Override public int onStartCommand(Intent intent, int flags, int startId) { Log.d(TAG, "OnStartCommand"); try { ConnectivityManager cm = (ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE); NetworkInfo netInfo = cm.getActiveNetworkInfo(); if (netInfo != null && netInfo.isConnectedOrConnecting()) { Log.d(TAG,"Twitter loop enter"); //Check the user's mood on twitter computeMoodOnTwitter(); if(userMoodSet) { Log.d(TAG, "user's twitter mood" + userTwitterMood); } /*else { Log.d(TAG, "user mood not set, world mood computation started"); //If user's mood is not set then check for world's mood }*/ } } catch(Exception e) { e.printStackTrace(); } return START_STICKY; } private void computeMoodOnTwitter() { // TODO Auto-generated method stub reset(); this.prefs = PreferenceManager.getDefaultSharedPreferences(this); Thread twitterThread; twitterThread = new Thread() { public void run() { //userMoodSet = false; Log.d(TAG, "User mood is :: "+ userMoodSet); /*try { String usrNme = TwitterUtils.getUserName(prefs).toString(); List statuses = TwitterUtils.getHomeTimeline(prefs); for(int i=0; i < Constants.NUM_MOOD_TYPES; i++) { for (int j =0 ; j < Constants.NUM_MOOD_TYPES; j++) { for (twitter4j.Status status : statuses) { //Check if the status is from the user and it matches our mood strings if(status.getText().contains(Constants.searchStrings[i][j]) && (status.getUser().getScreenName().equals(usrNme))) { Date date = status.getCreatedAt(); long Minutes = tmu.getMinuteDifference(cal.getTime(), date); if((Constants.sdf.format(date).equals(Constants.sdf.format(cal.getTime())))) { //Increment counter for each tweet Log.d(TAG, "User has a status"); userMoodSet = true; m_counter++; //track time for the first tweet if(m_counter == 1) { shortMinutes = Minutes; m_moodIntensity = computeMoodIntensity(i,j); m_myMood = i; Log.d(TAG, "intensity + mood" + m_moodIntensity +","+ m_myMood); Log.d(TAG,"SocialMood:: mymood- " + Constants.moodIntensityNames[m_moodIntensity]+ " "+ Constants.moodNames[m_myMood]); Log.d(TAG, "SocialMood:: status-"+status.getText()); } else //counter more than 1 //track time for the later tweets { //take latest tweet only if logged minutes is shorter than earlier minutes if(Minutes < shortMinutes) { shortMinutes = Minutes; Log.d(TAG, "Called compute mood_intensity :: "+ m_counter); m_moodIntensity = computeMoodIntensity(i,j); m_myMood = i; } } } } } } } } catch(TwitterException te) { userMoodSet = false; Log.d(TAG, "Unable to process twitter get requests "+te.getErrorCode()+ " "+ te.getErrorMessage()); } catch (Exception e) { // TODO Auto-generated catch block Log.d(TAG,"Error msg"); e.printStackTrace(); }*/ try { stopThread(this); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } }; twitterThread.start(); } public int computeMoodIntensity(int m_detect, int m_type) { // TODO Auto-generated method stub for(int j=0; j < Constants.m_extreme.length; j++) { if(m_type == Constants.m_extreme[m_detect][j]) return Constants.EXTREME; } for(int j=0; j < Constants.m_considerable.length; j++) { if(m_type == Constants.m_considerable[m_detect][j]) return Constants.CONSIDERABLE; } return Constants.MILD; } private String userStatusToMood(int myMood) { // TODO Auto-generated method stub String userMood = Constants.userNoTwitter; if(m_myMood >= Constants.NUM_MOOD_TYPES) { m_enterMood = true; Log.d(TAG, userMood); //Unreachable code - maybe we need to delete this ?? QNS /*Intent i = new Intent(UserMoodService.this,UserMood.class); i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); startActivity(i);*/ } else { userMood = "User mood is "+ Constants.moodNames[m_myMood]; userTwitterMood = Constants.moodIntensityNames[m_moodIntensity] +" "+Constants.moodNames[m_myMood]; Log.d(TAG, "Updated user mood is "+userTwitterMood); //call MQTT MqttMoodClient mqc = new MqttMoodClient(); mqc.setupMqttClient(); mqc.sendMessage(userTwitterMood); } return userMood; } private void stopThread(Thread theThread) throws Exception { // method to stop the worker thread once the process needed to do has been completed Log.d(TAG,"userMoodSet :: "+ userMoodSet); if (theThread != null) { theThread = null; Log.d(TAG, "Execution complete inside stop thread"); if(userMoodSet) userStatusToMood(m_myMood); } if(!userMoodSet) { Log.d(TAG, "In world thread"); //Call world Service //WorldMoodService worldService = new WorldMoodService(); //worldService.computeWorldMood(this); //show notification!! /** * V1.1 * @author dinesh * Code adapted from : http://android-er.blogspot.de/2013/06/ * start-activity-once-notification-clicked.html */ Intent myIntent = new Intent(UserMoodService.this, UserMood.class); PendingIntent pendingIntent = PendingIntent.getActivity( UserMoodService.this, 0, myIntent, Intent.FLAG_ACTIVITY_NEW_TASK); myNotification = new NotificationCompat.Builder(UserMoodService.this) .setContentTitle("MoodSense notification") .setContentText("Please enter mood to play music as per your mood") .setTicker("Please enter mood to play music as per your mood") .setWhen(System.currentTimeMillis()) .setContentIntent(pendingIntent) .setDefaults(Notification.DEFAULT_SOUND) .setAutoCancel(true) .setSmallIcon(R.drawable.app_icon) .build(); notificationManager = (NotificationManager)UserMoodService.this. getSystemService(Context.NOTIFICATION_SERVICE); notificationManager.notify(MY_NOTIFICATION_ID, myNotification); } else if (userMoodSet) { Intent i = new Intent("de.tu.darmstadt.moodsense.services.Notification"); i.putExtra("command", "clear all"); sendBroadcast(i); } } public class UserMoodNotificationReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { String temp = intent.getStringExtra("notification event"); } } /** (non-Javadoc) * @see android.app.Service#onDestroy() */ @Override public void onDestroy() { Log.d(TAG, "OnDeletion"); super.onDestroy(); } }