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が呼び出されない、これで何が問題なのか、または何かを逃したのですか?実装方法
NotificationListenerService内には、GUI対話を処理するブロードキャストを作成できるように、GUIスレッドと通信するルーパーが必要です。
希望 this の例が役立ちます。
通知を読むには、アプリへのアクセスを許可する必要があります:[設定]> [セキュリティ]> [通知アクセス]、アプリを確認します。
コードに関する少なくとも1つの問題は、onBind()の実装です。
このメソッドをオーバーライドする必要はありません。ただし、必要な場合は、少なくともスーパークラスによって返されたIBinderを返します。
@Override
public IBinder onBind(Intent intent) {
return super.onBind(intent);
}
少し遅いかもしれません。しかし、数か月前、NotificationListenerServiceを機能させるのにも苦労しました。
それ以来、私はそれを実装する方法を学び、私と同じことを経験した他の人を助けるために実装チュートリアルを構築したいと感じました
誰かが興味がある場合は、ここでプロジェクトを確認してください: https://github.com/Chagall/notification-listener-service-example
それに苦しんでいる人を助けることを願っています。
私は質問に答えるには遅すぎることを知っていますが、設定>サウンドと通知->通知アクセスを見つけることができなかったので、このインテントを起動することでアプリへの通知へのアクセスを直接許可します:
startActivity(new Intent(Settings.ACTION_NOTIFICATION_LISTENER_SETTINGS));
私は同じ問題にぶつかり、そのための手がかりを見つけました。
NotificationListenerService
は、bindService()
を呼び出して起動しない限り実行されていない可能性があります。
「通知アクセス」を有効にすると自動的に開始される場合とそうでない場合があります。
作成する通知には「tickerText」がありません。通知にtickerTextがない場合、onNotificationPostedが呼び出されないことがわかりました。
コードにmBuilder.setTicker( "your text here")を追加します。
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();
}
}