Tuesday 26 May 2015

Android Read Status Bar Notification | Android Read all incoming notification | Android Read Incoming Sms | Android Read Incoming Call

Hello Friends,
    Today, I am going to share a small tutorial on android "NotificationListenerService"
    which help us to read the all app notifications. This tutorial covers following
    points.

 




Feature:
1. We can easily read the notification of other android application or read all status bar
     notification,
2. Read|Listen incoming whatsapp messages
3. Read all incoming SMS
4. Read all incoming calls
5. Battery Low

Step1 : Create a Notification Service Class :
                    This class extends NotificationListenerService class which contains
                    two method:
                 a) onNotificationPosted(StatusBarNotification sbn) :
                           Implement this method to learn about new notifications as they are
                           posted by apps.
                 b) onNotificationRemoved(StatusBarNotification sbn) :
                           Implement this method to learn when notifications are removed.                         

 Note: The StatusBarNotifcation object contains extras, app package name and
            ticker name

1. NotificationService.java

package android.notifications;

import android.app.Notification;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.service.notification.NotificationListenerService;
import android.service.notification.StatusBarNotification;
import android.util.Log;
import android.support.v4.content.LocalBroadcastManager;

import java.io.ByteArrayOutputStream;

/**
 * Created by mukesh on 19/5/15.
 */
public class NotificationService extends NotificationListenerService {

    Context context;

    @Override

    public void onCreate() {

        super.onCreate();
        context = getApplicationContext();

    }
    @Override

    public void onNotificationPosted(StatusBarNotification sbn) {
        String pack = sbn.getPackageName();
        String ticker ="";
        if(sbn.getNotification().tickerText !=null) {
            ticker = sbn.getNotification().tickerText.toString();
        }
        Bundle extras = sbn.getNotification().extras;
        String title = extras.getString("android.title");
        String text = extras.getCharSequence("android.text").toString();
        int id1 = extras.getInt(Notification.EXTRA_SMALL_ICON);
        Bitmap id = sbn.getNotification().largeIcon;


        Log.i("Package",pack);
        Log.i("Ticker",ticker);
        Log.i("Title",title);
        Log.i("Text",text);

        Intent msgrcv = new Intent("Msg");
        msgrcv.putExtra("package", pack);
        msgrcv.putExtra("ticker", ticker);
        msgrcv.putExtra("title", title);
        msgrcv.putExtra("text", text);
        if(id != null) {
            ByteArrayOutputStream stream = new ByteArrayOutputStream();
            id.compress(Bitmap.CompressFormat.PNG, 100, stream);
            byte[] byteArray = stream.toByteArray();
            msgrcv.putExtra("icon",byteArray);
        }
        LocalBroadcastManager.getInstance(context).sendBroadcast(msgrcv);


    }

    @Override

    public void onNotificationRemoved(StatusBarNotification sbn) {
        Log.i("Msg","Notification Removed");

    }
}

2.MainActivity.java

package android.notifications;

import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.support.v4.content.LocalBroadcastManager;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.ListView;

import java.util.ArrayList;

/**
 * Created by mukesh on 19/5/15.
 */
public class MainActivity extends Activity {

    ListView list;
    CustomListAdapter adapter;
    ArrayList modelList;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        modelList = new ArrayList();
        adapter = new CustomListAdapter(getApplicationContext(), modelList);
        list=(ListView)findViewById(R.id.list);
        list.setAdapter(adapter);
        LocalBroadcastManager.getInstance(this).registerReceiver(onNotice, new IntentFilter("Msg"));
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.menu_main, menu);//Menu Resource, Menu
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case R.id.action_settings:
                Intent intent = new Intent(
                        "android.settings.ACTION_NOTIFICATION_LISTENER_SETTINGS");
                startActivity(intent);
                return true;
            default:
                return super.onOptionsItemSelected(item);
        }
    }
    private BroadcastReceiver onNotice= new BroadcastReceiver() {

        @Override
        public void onReceive(Context context, Intent intent) {
           // String pack = intent.getStringExtra("package");
            String title = intent.getStringExtra("title");
            String text = intent.getStringExtra("text");
            //int id = intent.getIntExtra("icon",0);

            Context remotePackageContext = null;
            try {
//                remotePackageContext = getApplicationContext().createPackageContext(pack, 0);
//                Drawable icon = remotePackageContext.getResources().getDrawable(id);
//                if(icon !=null) {
//                    ((ImageView) findViewById(R.id.imageView)).setBackground(icon);
//                }
                byte[] byteArray =intent.getByteArrayExtra("icon");
                Bitmap bmp = null;
                if(byteArray !=null) {
                    bmp = BitmapFactory.decodeByteArray(byteArray, 0, byteArray.length);
                }
                Model model = new Model();
                model.setName(title +" " +text);
                model.setImage(bmp);

                if(modelList !=null) {
                    modelList.add(model);
                    adapter.notifyDataSetChanged();
                }else {
                    modelList = new ArrayList();
                    modelList.add(model);
                    adapter = new CustomListAdapter(getApplicationContext(), modelList);
                    list=(ListView)findViewById(R.id.list);
                    list.setAdapter(adapter);
                }

            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    };
}

3. AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>

<manifest xmlns:android="http://schemas.android.com/apk/res/android"

    package="android.notifications">
    <uses-permission android:name="android.permission.RECEIVE_SMS" />
    <uses-permission android:name="android.permission.READ_SMS" />
    <uses-permission android:name="android.permission.READ_PHONE_STATE"/>
    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme">
        <activity
            android:name="android.notifications.MainActivity"
            android:configChanges="keyboardHidden|orientation|screenSize"
            android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <service
            android:name="android.notifications.NotificationService"
            android:label="@string/app_name"
            android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SER                          VICE">
            <intent-filter>
                <action android:name="android.service.notification.NotificationLi                                  stenerService" />
            </intent-filter>
        </service>
        <receiver android:name="android.notifications.IncomingSms">
           <intent-filter>
               <action android:name="android.provider.Telephony.SMS_RECEIVED" />
           </intent-filter>
        </receiver>
        <receiver android:name=".ServiceReceiver" >
            <intent-filter>
                <action android:name="android.intent.action.PHONE_STATE" />
            </intent-filter>
        </receiver>
    </application>
</manifest>


4. Android check Notification Access Setting is enable or not:


//check notification access setting is enabled or not
public static boolean checkNotificationEnabled() {
         try{
       if(Settings.Secure.getString(MainActivity.mActivity.getContentResolver(),
                 "enabled_notification_listeners").contains(App.getContext().getPackageName())) 
      {
    return true;
      } else {
         return false;
      }

 }catch(Exception e) {
  e.printStackTrace();
 }
 return false;
}



Download Complete Code From Here NotificationListener


Hope, this will helps someone.
Enjoy Coding .... :)

Mukesh Kumar

Hi Guys I am from Delhi working as Web/Mobile Application Developer(Android Developer), also have knowledge of Roboelctric and Mockito ,android test driven development... Blogging has been my passion and I think blogging is one of the powerful medium to share knowledge and ideas....

40 comments:

  1. awsome work Mukesh , this post is very informative and helpful

    helped me a lot

    ReplyDelete
  2. dude i used your code in my project it gives the null pointer exception in the bitmap object it says that the boolean android bitmap compress

    ReplyDelete
    Replies
    1. for which app you are fetching the image...in some app notification we didn't received image so in that case I am showing app icon launcher.

      Delete
  3. i am fetching for the whatsapp in my phone .. and its showing me that error
    and please send me your mail id mine is chauhanadit7@gmail.com so that i can mail you instead of commenting

    ReplyDelete
  4. This app reads all notifications? If I receive the first notification I can read all informations, but when I receive the second notification I cant- read all informations because it is append to first notifications. In the status bar the two notifications of same app are in an only notification. How can I read it?

    ReplyDelete
  5. its working fine but when my app is closed am not getting notification so can you please share code for that also... thanks in advance

    my id id pawanvijay02@gmail.com

    ReplyDelete
  6. thanks for this code...am not getting notifications when my app is closed can you please send me code for that also? my id is pawanvijay02@gmail.com

    thanks in advance

    ReplyDelete
    Replies
    1. Hello Pawan,
      add start sticky in notification service class.

      Delete
  7. hi, can you plase send me a code for reading whatsapp messages into android app.
    I am new to android app development

    ReplyDelete
    Replies
    1. Hello ,
      I already attach the complete code in this post. Check it.
      Its helps to read your whatsapp messages too.

      Delete
  8. Bute while i run this code from github, nothing is displayed below the actionbar with heading remote notification.

    ReplyDelete
    Replies
    1. May be you didn't enable the Notification listener from setting menu, turn on and then try.

      Delete
  9. How to turn on it.?

    ReplyDelete
    Replies
    1. run it on android 4.3 and above and check setting
      menu from top right.See the screen shot above....

      Delete
  10. how can i enable it?

    ReplyDelete
  11. I enabled it. Even though app crashes. please help

    ReplyDelete
  12. Can you please give the code that reads only whatsapp messages?

    ReplyDelete
  13. Hi. Thanks a lot for this code. I wonder how to run this app in background right from boot up. Currently it works, only if I open it.

    ReplyDelete
  14. Hi Mukesh,
    brilliant code... well done, but yaar i have 1 question.

    this is listening to all the incoming/or going to be coming Notifications...
    Now what if i want it to give me a list of present(Current) notifications that are alive in the StatusBar.. but havent been attended to?
    So basically it should be able to extract the same from an already existing notification when i have started your app...
    Please guide me how to go about doing so.. thanx

    ReplyDelete
  15. Hi, the code is good, but i can read only first Whatsapp's notification. The other notification it doesn't read, it read in android.text this:" 2 new messagges". I would read the text of the messagges

    ReplyDelete
  16. Hello Chiara,
    add below code which helps you to read whatsapp's second
    notifcation text or evrey message one by one:

    String text = null;
    if (extras.getCharSequence("android.text") != null) {
    text = extras.getCharSequence("android.text").toString();
    }
    if (text == null) {
    // for whatsapp on kitkat second whats app text
    // will be null
    if (extras.get("android.textLines") != null) {
    CharSequence[] charText = (CharSequence[]) extras
    .get("android.textLines");
    if (charText.length > 0) {
    text = charText[charText.length - 1].toString();
    }
    }
    }

    ReplyDelete
  17. Why error This code "Bundle extras = sbn.getNotific ation().extras;", in Ecclipse sdk 18
    "Extras no be resolved and not a field"?

    ReplyDelete
  18. Hey Thank you so much.. It is very informative. However, why it does not catch notifications from few Apps like Way2 news and of moneycontrol

    ReplyDelete
  19. Hi,
    Thanks for this tutorial.I was able to get it work.I have two problems though
    1.I need to show corresponding app icon on notification and on click i must open the same app
    2.When i navigate screen the previous notification that are present in statusbar aren't shown in app.I want to show until user click clear notification.
    So kindly help me to solve this.Email me @ themebowlapps@gmail.com

    ReplyDelete
  20. Hi,How to show corresponding app icon on left side of notification rather than default icon?

    ReplyDelete
    Replies
    1. Hello Govind,
      check below block of code where I am checking if there is a user profile then we are showing his pic else default app launcher icon.
      Modify the code acc. to you.

      if(id != null) {
      ByteArrayOutputStream stream = new ByteArrayOutputStream();
      id.compress(Bitmap.CompressFormat.PNG, 100, stream);
      byte[] byteArray = stream.toByteArray();
      msgrcv.putExtra("icon",byteArray);
      }

      Delete
    2. Hi,
      Thanks for your immediate response.I already tried this code.But all i see is default icon on side for all apps.I don't see whatsapp icon for whatsapp msg nor default system message icon for sms.I m stuck.Kindly help me to find a solution

      Delete
  21. Okay, you need default icon then add this block of code in else part(
    if no whats app profile pic the get default laucher icon )
    if(id != null) {
    }else{
    if (pack != null) {
    Drawable d = getPackageManager()
    .getApplicationIcon(pack);
    Bitmap bitmap = ((BitmapDrawable) d)
    .getBitmap();

    ByteArrayOutputStream stream = new ByteArrayOutputStream();
    bitmap.compress(
    Bitmap.CompressFormat.JPEG,
    100, stream);
    byte[] bitmapdata = stream
    .toByteArray();

    }
    }
    }

    ReplyDelete
  22. which min API I need to use NotificationListener ?

    ReplyDelete
  23. Thanks a lot Mukesh for the code. I think you should also make video tutorials as your a very talented guy and it would help a lot of people.

    ReplyDelete
    Replies
    1. Thanks dear will try to make the youtube video blog.

      Delete
  24. in my code CustomListAdapter cannot be resolved to a type..
    How do I solve this?

    ReplyDelete
    Replies
    1. Show me the code..may be because you didn't closing the
      brackets properly.

      Delete
  25. Hello, Firsly thanks for post. I took source code and run. it runs , when facebook or other apss notifications comes, it shows but for whatsapp it doesn't . Second one is when i close app it doesnt work. Can u explain the solution for these two problems ?

    ReplyDelete
  26. For running this app in background you can use service class.

    Nice coding..

    ReplyDelete
  27. where do we have to put the check permission code snippet#4 ?

    ReplyDelete
  28. This is a fantastic application!
    I added this at the end of onCreate so it only checks perm once.

    LocalBroadcastManager.getInstance(this).registerReceiver(onNotice, new IntentFilter("Msg"));
    if (Settings.Secure.getString(getContentResolver(),"enabled_notification_listeners").contains(getApplicationContext().getPackageName()))
    {
    //service is enabled do something
    }
    else
    {
    //service is not enabled try to enabled by calling...
    getApplicationContext().startActivity(new Intent(
    "android.settings.ACTION_NOTIFICATION_LISTENER_SETTINGS"));
    }

    ReplyDelete

 

Copyright @ 2013 Android Developers Blog.