NotificationListenerService实现

我想实现在Android 4.3中添加的NotificationListnerService,但我无法获取通知的详细信息。

我的代码如下

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()); } } 

Android清单文件是

 <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.notificationtest" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="18" /> <application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <activity android:name="com.example.notificationtest.MainActivity" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <activity android:name="com.example.notificationtest.ResultActivity"></activity> <service android:name="com.example.notificationtest.NotificationListenerTesting" android:label="notification" android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE"> <intent-filter> <action android:name="android.service.notification.NotificationListenerService"/> </intent-filter> </service> </application> </manifest> 

但通知后点击或通知后NotificationListenerService没有被调用,这是什么错误或我想念somthing? 如何实现它?

在NotificationListenerService内部,您需要一个活页夹与GUI线程进行通信,以便您可以创build一个广播来处理GUI交互。

希望这个例子能帮助你。

您需要授予您应用的访问权限以读取通知:“设置>安全>通知访问”并检查您的应用。

你的代码至less有一个问题是你的onBind()

没有必要重写这个方法。 但是,如果你必须的话,至less要返回超类返回的IBinder。

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

我遇到了同样的问题,并find了一些线索。

NotificationListenerService可能不会运行,除非您调用bindService()来启动它。

有时会在启用“通知访问”时自动启动,有时则不会。

您build立的通知没有“tickerText”。 我发现如果通知没有tickerText,onNotificationPosted不会被调用。

在你的代码中添加mBuilder.setTicker(“你的文字在这里”)。

现在应该调用onNotificationPosted,假定NotificationListenerService设置的其余部分是并发的。

我在GitHub中做同样的事情,但是我仍然没有进入通知类。

 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<Status> 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(); } } 

可能有点晚了。 但几个月前,我还努力使NotificationListenerService工作。

从那以后,我学会了如何实现它,并且感觉就像构build一个实现教程来帮助那些和我一样的人

如果有人感兴趣,请在这里检查项目: https : //github.com/Chagall/notification-listener-service-example

希望它能帮助那些正在为之奋斗的人。

我知道它太迟回答这个问题,但因为我无法find设置>声音和通知 – >通知访问,所以我直接允许通知访问我的应用程序通过发射这个意图:

startActivity(new Intent(Settings.ACTION_NOTIFICATION_LISTENER_SETTINGS));