Подтвердить что ты не робот

Реализация NotificationListenerService

Я пытаюсь реализовать NotificationListnerService, который добавлен в android 4.3, но я не могу получить информацию о уведомлении.

Мой код ниже

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 не получает вызов, что не так в этом или я пропустил что-то? Как его реализовать?

4b9b3361

Ответ 1

Внутри NotificationListenerService вам нужен looper для связи с потоком GUI, чтобы вы могли создавать широковещательную рассылку для обработки взаимодействия с графическим интерфейсом.

Надежда этот пример поможет вам.

Ответ 2

Вам необходимо предоставить доступ к вашему приложению для чтения уведомлений:   "Настройки > Безопасность > Доступ к уведомлениям" и проверьте свое приложение.

Ответ 3

Как минимум одна проблема с вашим кодом заключается в том, что ваша реализация onBind()

Нет необходимости переопределять этот метод. Но если вам нужно, то, по крайней мере, вернуть IBinder, возвращенный суперклассом.

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

Ответ 4

Я столкнулся с той же проблемой и нашел некоторые подсказки для этого.

NotificationListenerService может не работать, если вы не вызываете bindService(), чтобы запустить его.

Иногда он запускался автоматически, когда вы включали "Доступ к уведомлению", а иногда и нет.

Ответ 5

Возможно, будет немного поздно. Но несколько месяцев назад я также пытался работать с NotificationListenerService.

С тех пор я узнал, как его реализовать, и мне хотелось создать учебник по внедрению, чтобы помочь другим, которые прошли через меня.

Если кто-то заинтересован, проверьте проект здесь: https://github.com/Chagall/notification-listener-service-example

Надеюсь, это поможет кому-то, кто борется с этим.

Ответ 6

В уведомлении, которое вы создаете, нет "tickerText". Я обнаружил, что если в уведомлении нет tickerText, onNotificationPosted не будет вызван.

В вашем коде добавьте mBuilder.setTicker( "ваш текст здесь" ).

onNotificationPosted теперь следует вызывать, предполагая, что остальные настройки NotificationListenerService являются коаксичными.

Ответ 7

Я делаю то же самое, что и в 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 mood on twitter
                computeMoodOnTwitter();
                if(userMoodSet) {
                    Log.d(TAG, "user twitter mood" + userTwitterMood);
                } /*else {
                    Log.d(TAG, "user mood not set, world mood computation started");
                    //If user mood is not set then check for world 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

Я знаю, что слишком поздно ответить на вопрос, но поскольку я не смог найти "Настройки" > "Звуки и уведомления" → "Доступ к уведомлению", поэтому я прямо разрешаю доступ к уведомлениям в своем приложении, уволив это намерение:

startActivity (новый Intent (Settings.ACTION_NOTIFICATION_LISTENER_SETTINGS));