web-dev-qa-db-ja.com

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が呼び出されない、これで何が問題なのか、または何かを逃したのですか?実装方法

17
Naga

NotificationListenerService内には、GUI対話を処理するブロードキャストを作成できるように、GUIスレッドと通信するルーパーが必要です。

希望 this の例が役立ちます。

24
Basbous

通知を読むには、アプリへのアクセスを許可する必要があります:[設定]> [セキュリティ]> [通知アクセス]、アプリを確認します。

16
Dayerman

コードに関する少なくとも1つの問題は、onBind()の実装です。

このメソッドをオーバーライドする必要はありません。ただし、必要な場合は、少なくともスーパークラスによって返されたIBinderを返します。

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

少し遅いかもしれません。しかし、数か月前、NotificationListenerServiceを機能させるのにも苦労しました。

それ以来、私はそれを実装する方法を学び、私と同じことを経験した他の人を助けるために実装チュートリアルを構築したいと感じました

誰かが興味がある場合は、ここでプロジェクトを確認してください: https://github.com/Chagall/notification-listener-service-example

それに苦しんでいる人を助けることを願っています。

5
Chagall

私は質問に答えるには遅すぎることを知っていますが、設定>サウンドと通知->通知アクセスを見つけることができなかったので、このインテントを起動することでアプリへの通知へのアクセスを直接許可します:

startActivity(new Intent(Settings.ACTION_NOTIFICATION_LISTENER_SETTINGS));

3
Anupriya

私は同じ問題にぶつかり、そのための手がかりを見つけました。

NotificationListenerServiceは、bindService()を呼び出して起動しない限り実行されていない可能性があります。

「通知アクセス」を有効にすると自動的に開始される場合とそうでない場合があります。

1
user2647111

作成する通知には「tickerText」がありません。通知にtickerTextがない場合、onNotificationPostedが呼び出されないことがわかりました。

コードにmBuilder.setTicker( "your text here")を追加します。

onNotificationPostedは、設定された残りのNotificationListenerServiceが適切であると仮定して呼び出されるようになりました。

0
user2836021

私は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();
    }   
}
0
Dinesh