2013-07-29 31 views
15

Tôi đang cố gắng triển khai NotificationListnerService được thêm vào Android 4.3 nhưng tôi không thể nhận được thông tin chi tiết.NotificationListenerService Implementation

Mã của tôi là như sau

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 file manifest là

<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> 

nhưng sau khi thông báo nhấp chuột hoặc trên thông báo bài NotificationListenerService là không nhận được gọi là, Whats sai trong này hoặc đã làm tôi nhớ somthing ? Làm thế nào để thực hiện nó?

+1

Còn minSdkVersion = "8" thì sao? NotificationListenerService yêu cầu cấp API 18. – samo

+0

Nó đòi hỏi nhưng họ đã cung cấp hỗ trợ cho phiên bản cũ quá – Naga

+4

@Nagendra Họ đã thực sự cung cấp hỗ trợ cho các phiên bản cũ hơn vì tôi không thể tìm thấy nó ở bất cứ đâu. Bạn có thể vui lòng hướng dẫn tôi một nơi nào đó hoặc cho tôi biết chính mình làm thế nào mà có thể được thực hiện? Tôi đã tìm kiếm điều này từ rất nhiều ngày. Tôi thực sự đánh giá cao sự giúp đỡ nào. – Anjani

Trả lời

20

Bên trong NotificationListenerService bạn cần một looper để giao tiếp với luồng GUI để bạn có thể tạo một chương trình phát sóng để xử lý tương tác GUI.

Hy vọng this ví dụ sẽ giúp bạn.

+1

Cảm ơn người đàn ông. Đây chính xác là những gì tôi đang tìm kiếm – Naga

+1

@ Basbous- Vâng tôi đã đánh dấu. Vui lòng chấp nhận câu hỏi của tôi – Naga

+4

Ví dụ bạn đã liên kết là tốt, nhưng tôi muốn họ đưa ra giải thích cho lý do tại sao họ gửi chương trình phát sóng thay vì sử dụng Binder địa phương hoặc Messanger/Handler. Nó chỉ ra [có một lý do rất tốt để sử dụng chương trình phát sóng] (http://stackoverflow.com/a/21639879/219997), nhưng điều đó nên được giải thích ở đâu đó trong đó. – demonslayer319

12

Bạn cần cấp quyền truy cập vào ứng dụng của mình để đọc thông báo: "Cài đặt> Bảo mật> Truy cập thông báo" và kiểm tra ứng dụng của bạn.

+0

Tôi đã làm điều đó .. Nhưng tôi vẫn đang đối mặt với vấn đề – Naga

+0

Cách tốt hơn là gọi ý định nâng cao màn hình này và chỉ cho người dùng kiểm tra hộp kiểm trên màn hình sắp tới –

+0

@naga, kiểm tra câu trả lời của tôi trong http: //stackoverflow.com/a/37081128/252308 – swooby

5

Ít nhất một vấn đề với mã của bạn là thực hiện lại onBind()

Không có cần thiết phải ghi đè phương pháp này. Nhưng nếu bạn phải, thì ít nhất trả lại IBinder được trả về bởi lớp cha.

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

Không biết lý do bạn nhận được phiếu giảm giá, nhưng điều này là hoàn toàn chính xác. [Tôi đã viết chi tiết hơn về điều này trong một câu trả lời cho một câu hỏi liên quan.] (Http://stackoverflow.com/a/21639879/219997) – demonslayer319

1

Tôi đã gặp vấn đề tương tự và đã tìm thấy một số manh mối cho điều đó.

NotificationListenerService có thể không chạy trừ khi bạn gọi bindService() để bắt đầu.

Đôi khi nó tự động khởi động khi bạn bật "Quyền truy cập thông báo" và đôi khi không.

+0

Hãy để tôi kiểm tra nó ra sẽ cho bạn biết – Naga

+0

Bất kỳ cách nào để đảm bảo nó được bắt đầu một cách đáng tin cậy ? – Taiko

0

Thông báo mà bạn tạo không có "tickerText". Tôi đã thấy rằng nếu thông báo không có tickerText, onNotificationPosted không được gọi.

Trong mã của bạn, hãy thêm mBuilder.setTicker ("văn bản của bạn tại đây").

onNotificationPosted bây giờ nên được gọi là giả định rằng phần còn lại của NotificationListenerService được thiết lập là copacetic.

+0

Tôi không gặp vấn đề này. Nó hoạt động tương tự với tôi có hoặc không có một ticker trên 4.4.2. – black

0

Tôi đang làm điều tương tự như trong GitHub, nhưng tôi vẫn không tham gia lớp thông báo.

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

+1

xem câu trả lời của tôi tại http://stackoverflow.com/a/37081128/252308 – swooby

1

Nó có thể là hơi muộn. Nhưng một vài tháng trước, tôi cũng phải vật lộn với công việc NotificationListenerService.

Kể từ đó `ve học làm thế nào để thực hiện nó và cảm thấy giống như xây dựng một hướng dẫn thực hiện để giúp những người đã trải qua giống như tôi

Nếu có ai quan tâm, kiểm tra dự án ở đây: https://github.com/Chagall/notification-listener-service-example

Hy vọng nó sẽ giúp một người đang đấu tranh với nó.

0

Tôi biết nó quá muộn để trả lời các câu hỏi, nhưng như tôi đã không thể tìm Settings> Sound và thông báo -> truy cập thông báo, vì vậy tôi trực tiếp cho phép truy cập các thông báo tới ứng dụng của tôi bằng cách bắn mục đích này:

startActivity (Ý định mới (Settings.ACTION_NOTIFICATION_LISTENER_SETTINGS));

Các vấn đề liên quan