我正在尝试实现在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没有被调用,这是错误的还是我错过了什么?如何实现呢?
答案 0 :(得分:23)
在NotificationListenerService中,你需要一个looper来与GUI线程进行通信,这样你就可以创建一个广播来处理GUI交互。
希望this示例可以帮助您。
答案 1 :(得分:16)
您需要授予对应用的访问权限才能阅读通知: “设置&gt;安全性&gt;通知访问”并检查您的应用。
答案 2 :(得分:8)
您的代码至少有一个问题是您的onBind()
的实现没有必要覆盖此方法。但如果必须,那么至少返回超类返回的IBinder。
@Override
public IBinder onBind(Intent intent) {
return super.onBind(intent);
}
答案 3 :(得分:4)
可能有点晚了。但几个月前,我也在努力使NotificationListenerService工作。
从那时起,我已经学会了如何实现它,感觉就像构建一个实现教程来帮助那些和我一样的人
如果有兴趣,请在此处查看项目: https://github.com/Chagall/notification-listener-service-example
希望能帮助那些正在努力解决的人。
答案 4 :(得分:3)
我知道回答这个问题为时已晚,但因为我无法找到设置&gt;声音和通知 - &gt;通知访问权限,因此我通过触发此意图直接允许访问我的应用程序:
startActivity(new Intent(Settings.ACTION_NOTIFICATION_LISTENER_SETTINGS));
答案 5 :(得分:1)
我遇到了同样的问题,并找到了一些线索。
NotificationListenerService
可能无法运行,除非您致电bindService()
启动它。
有时它会在您启用“通知访问权限”时自动启动,有时则不会。
答案 6 :(得分:0)
您构建的通知没有“tickerText”。我发现如果通知没有tickerText,则onNotificationPosted不会被调用。
在你的代码中添加mBuilder.setTicker(“你的文字在这里”)。
现在应该调用onNotificationPosted,假设NotificationListenerService的其余部分设置为copacetic。答案 7 :(得分:0)
我在做与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();
}
}
答案 8 :(得分:0)
package com.hiteshsahu.notificationlistener.notification
import android.app.Activity
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.service.notification.NotificationListenerService
import android.service.notification.StatusBarNotification
import android.util.Log
import androidx.localbroadcastmanager.content.LocalBroadcastManager
class CustomNotificationListenerService : NotificationListenerService() {
private var commandFromUIReceiver: CommandFromUIReceiver? = null
override fun onCreate() {
super.onCreate()
// Register broadcast from UI
commandFromUIReceiver = CommandFromUIReceiver()
val filter = IntentFilter()
filter.addAction(READ_COMMAND_ACTION)
registerReceiver(commandFromUIReceiver, filter)
}
/**
* New Notn Added Callback
*/
override fun onNotificationPosted(newNotification: StatusBarNotification) {
Log.i(
TAG,
"-------- onNotificationPosted(): " + "ID :" + newNotification.id + "\t" + newNotification.notification.tickerText + "\t" + newNotification.packageName
)
sendResultOnUI("onNotificationPosted :" + newNotification.packageName + "\n")
}
/**
* Notn Removed callback
*/
override fun onNotificationRemoved(removedNotification: StatusBarNotification) {
Log.i(
TAG,
"-------- onNotificationRemoved() :" + "ID :" + removedNotification.id + "\t" + removedNotification.notification.tickerText + "\t" + removedNotification.packageName
)
sendResultOnUI("onNotificationRemoved: " + removedNotification.packageName + "\n")
}
internal inner class CommandFromUIReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
if (intent.getStringExtra(COMMAND_KEY) == CLEAR_NOTIFICATIONS)
// remove Notns
cancelAllNotifications()
else if (intent.getStringExtra(COMMAND_KEY) == GET_ACTIVE_NOTIFICATIONS)
// Read Notns
fetchCurrentNotifications()
}
}
/**
* Fetch list of Active Notns
*/
private fun fetchCurrentNotifications() {
sendResultOnUI("===== Notification List START ====")
val activeNotnCount = this@CustomNotificationListenerService.activeNotifications.size
if (activeNotnCount > 0) {
for (count in 0..activeNotnCount) {
val sbn = this@CustomNotificationListenerService.activeNotifications[count]
sendResultOnUI("#" + count.toString() + " Package: " + sbn.packageName + "\n")
}
} else {
sendResultOnUI("No active Notn found")
}
sendResultOnUI("===== Notification List END====")
}
// sendMessage success result on UI
private fun sendResultOnUI(result: String?) {
val resultIntent = Intent(UPDATE_UI_ACTION)
resultIntent.putExtra(RESULT_KEY, Activity.RESULT_OK)
resultIntent.putExtra(RESULT_VALUE, result)
LocalBroadcastManager.getInstance(this).sendBroadcast(resultIntent)
}
override fun onDestroy() {
super.onDestroy()
unregisterReceiver(commandFromUIReceiver)
}
companion object {
const val TAG = "NotificationListener"
//Update UI action
const val UPDATE_UI_ACTION = "ACTION_UPDATE_UI"
const val READ_COMMAND_ACTION = "ACTION_READ_COMMAND"
// Bundle Key Value Pair
const val RESULT_KEY = "readResultKey"
const val RESULT_VALUE = "readResultValue"
//Actions sent from UI
const val COMMAND_KEY = "READ_COMMAND"
const val CLEAR_NOTIFICATIONS = "clearall"
const val GET_ACTIVE_NOTIFICATIONS = "list"
}
}
完成项目