Call a notification listener inside a background service in android studio

10.7k views Asked by At

I have a background service running and a notification listener. I want to call the notification listener from the background service and it does not seem to work. I have below my classes. 1. Main activity starts the service 2.MyService is the background service running 3. NLService is the notification listeners service I want to call inside the MyService

MainActivity.java

package com.example.notifyservice;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.support.v4.content.LocalBroadcastManager;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;

import com.example.eg.intentserviceexample.R;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        //setting button click
        findViewById(R.id.btn_start_service).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                //Creating an intent for sending to service
                Intent intent = new Intent(getApplicationContext(), MyService.class);

                intent.putExtra("id", 101);
                intent.putExtra("msg", "hi");

                //starting service
                startService(intent);
            }
        });
    }

    @Override
    protected void onStart() {
        super.onStart();

        //register broadcast receiver for the intent MyTaskStatus
        LocalBroadcastManager.getInstance(this).registerReceiver(MyReceiver, new IntentFilter("MyServiceStatus"));
    }


    //Defining broadcast receiver
    private BroadcastReceiver MyReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {

            String message = intent.getStringExtra("serviceMessage");

            Toast.makeText(MainActivity.this, "Received : " + message, Toast.LENGTH_SHORT).show();
        }
    };




    @Override
    protected void onStop() {
        super.onStop();

        LocalBroadcastManager.getInstance(this).unregisterReceiver(MyReceiver);
    }

}

MyService.java

package com.example.notifyservice;

import android.app.IntentService;
import android.content.BroadcastReceiver;
        import android.content.Context;
        import android.content.Intent;
        import android.support.v4.content.LocalBroadcastManager;
        import android.util.Log;
        import android.widget.TextView;

public class MyService extends IntentService {
    private TextView txtView;
    private NotificationReceiver nReceiver;
    public MyService() {
        super(MyService.class.getName());
    }

    @Override
    protected void onHandleIntent(Intent intent) {


        //retrieving data from the received intent
        int id = intent.getIntExtra("id",0);
        String message = intent.getStringExtra("msg");

        Log.i("Data  ", "id : "+id+" message : "+ message );
        //-----------------------------------------------


        //Do your long running task here

        Intent i = new Intent("com.example.notifyservice.NOTIFICATION_LISTENER_SERVICE_EXAMPLE");

        i.putExtra("command","list");
        sendBroadcast(i);
        //------------------------------------------------

       /* //Broadcasting some data
        Intent myIntent = new Intent("MyServiceStatus");
        myIntent.putExtra("serviceMessage", "Task done");


        // Send broadcast
        LocalBroadcastManager.getInstance(this).sendBroadcast(myIntent);*/

    }
    class NotificationReceiver extends BroadcastReceiver {

        @Override
        public void onReceive(Context context, Intent intent) {
            String temp = intent.getStringExtra("notification_event") + "\n" + txtView.getText();
            txtView.setText(temp);
        }
    }
}

NLService.java

package com.example.notifyservice;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Build;
import android.os.Bundle;
import android.service.notification.NotificationListenerService;
import android.service.notification.StatusBarNotification;
import android.support.annotation.RequiresApi;
import android.util.Log;

@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
public class NLService extends NotificationListenerService {

    private String TAG = this.getClass().getSimpleName();
    private NLServiceReceiver nlservicereciver;
    @Override
    public void onCreate() {
        super.onCreate();
        nlservicereciver = new NLServiceReceiver();
        IntentFilter filter = new IntentFilter();
        filter.addAction("com.example.notify.NOTIFICATION_LISTENER_SERVICE_EXAMPLE");
        registerReceiver(nlservicereciver,filter);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        unregisterReceiver(nlservicereciver);
    }

    @Override
    public void onNotificationPosted(StatusBarNotification sbn) {

        String pack = sbn.getPackageName();

        String text = "";
        String title = "";
        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT) {
            Bundle extras = sbn.getNotification().extras;
            text = extras.getCharSequence("android.text").toString();
            title = extras.getString("android.title");
        }

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

    }

    @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("com.example.notify.NOTIFICATION_LISTENER_EXAMPLE");
        i.putExtra("notification_event","onNotificationRemoved :" + sbn.getPackageName() + "\n");

        sendBroadcast(i);
    }

    class NLServiceReceiver extends BroadcastReceiver{

        @Override
        public void onReceive(Context context, Intent intent) {

           if(intent.getStringExtra("command").equals("list")){
                Intent i1 = new  Intent("com.example.notify.NOTIFICATION_LISTENER_EXAMPLE");
                i1.putExtra("notification_event","=====================");
                sendBroadcast(i1);
                int i=1;
                for (StatusBarNotification sbn : NLService.this.getActiveNotifications()) {
                    Intent i2 = new  Intent("com.example.notify.NOTIFICATION_LISTENER_EXAMPLE");
                    i2.putExtra("notification_event",i +" " + sbn.getPackageName() + "\n");
                    sendBroadcast(i2);
                    i++;
                }
                Intent i3 = new  Intent("com.example.notify.NOTIFICATION_LISTENER_EXAMPLE");
                i3.putExtra("notification_event","===== Notification List ====");
                sendBroadcast(i3);

            }

        }
    }

}

The bacgkround service starts but does not see the NLSErvice. Any help will be much appreciated!

Edit the manifest too:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.eg.intentserviceexample">
    <uses-sdk android:minSdkVersion="18"
        android:targetSdkVersion="18"
         />
    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name="com.example.notifyservice.MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>


        <service
            android:name="com.example.notifyservice.MyService"
            android:exported="false"/>

        <service android:name="com.example.notifyservice.NLService"
            android:label="@string/app_name"
            android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE">
            <intent-filter>
                <action android:name="android.service.notification.NotificationListenerService" />
            </intent-filter>
        </service>

    </application>

</manifest>
2

There are 2 answers

1
kyripapa On BEST ANSWER

So what I did wrong is that I tried to create 2 services. Instead I only needed one. Here is the code that works. What it simply does is starting the bacgrkound service and counts the notifications.When you click report it shows all the notifications, even if the user has close the app. I have put extra code for making a notification after 5 notifications.

MainActivity.java
package com.example.notifyservice;

import android.app.NotificationManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.support.v4.app.NotificationCompat;
import android.support.v4.content.LocalBroadcastManager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Toast;

import java.util.Timer;
import java.util.TimerTask;


public class MainActivity extends AppCompatActivity {

/*
    protected final Timer myTimer = new Timer("MainActivityTimer", false);
*/

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // FIRST OF ALL
        // START SERVICE AS STICKY - BY EXPLICIT INTENT
        // to prevent being started by the system (without the sticky flag)
        Intent intent = new Intent(getApplicationContext(), NLService.class);

        // TODO: to be removed
        intent.putExtra("id", 101);
        intent.putExtra("msg", "hi");

        //starting service


        startService(intent);


        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Intent i = new Intent("android.settings.ACTION_NOTIFICATION_LISTENER_SETTINGS");
        startActivity(i);
        //setting button click
        findViewById(R.id.btn_start_service).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                // Ask service (async) for its status (manually after the main activity was paused or closed and missed some NLService's broadcasts)
                // the background service is sticky and the counters(added/removed) are not reset.

                //Creating an intent for sending to service
                //Intent intent = new Intent(getApplicationContext(), MyService.class);
                Intent intent = new Intent(getApplicationContext(), NLService.class);
                intent.putExtra("command", "get_status");
                //starting service
                startService(intent);

            }
        });
    }

    @Override
    protected void onStart() {
        super.onStart();

        // register broadcast receiver for the intent MyTaskStatus
        LocalBroadcastManager.getInstance(this).registerReceiver(MyReceiver, new IntentFilter(NLService.ACTION_STATUS_BROADCAST));


    }


    //Defining broadcast receiver
    private BroadcastReceiver MyReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            Log.i("MainActivity", "Broadcast Recieved: "+intent.getStringExtra("serviceMessage"));
            String message = intent.getStringExtra("serviceMessage");
            Toast.makeText(MainActivity.this, message, Toast.LENGTH_SHORT).show();
        }
    };




    @Override
    protected void onStop() {
        super.onStop();

        LocalBroadcastManager.getInstance(this).unregisterReceiver(MyReceiver);
    }

}

NLService.java

package com.example.notifyservice;

import android.app.IntentService;
import android.app.NotificationManager;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Build;
import android.service.notification.NotificationListenerService;
import android.service.notification.StatusBarNotification;
import android.support.annotation.RequiresApi;
import android.support.v4.app.NotificationCompat;
import android.support.v4.content.LocalBroadcastManager;
import android.util.Log;

// @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
public class NLService extends NotificationListenerService {

    public static final String ACTION_STATUS_BROADCAST = "com.example.notifyservice.NLService_Status";

    private String TAG = this.getClass().getSimpleName();
    private NLServiceReceiver nlservicereciver;

    /**
     * The number of notifications added (since the service started)
     */
    private int nAdded=0;
    /**
     * The number of notifications removed (since the service started)
     */
    private int nRemoved=0;
    int temp = 5;

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        //retrieving data from the received intent
        if(intent.hasExtra("command")) {
            Log.i("NLService", "Started for command '"+intent.getStringExtra("command"));
            broadcastStatus();
        } else if(intent.hasExtra("id")) {
            int id = intent.getIntExtra("id", 0);
            String message = intent.getStringExtra("msg");
            Log.i("NLService", "Requested to start explicitly - id : " + id + " message : " + message);
        }
        super.onStartCommand(intent, flags, startId);

        // NOTE: We return STICKY to prevent the automatic service termination
        return START_STICKY;
    }

    private void broadcastStatus() {
        Log.i("NLService", "Broadcasting status added("+nAdded+")/removed("+nRemoved+")");
        Intent i1 = new  Intent(ACTION_STATUS_BROADCAST);
        i1.putExtra("serviceMessage","Added: "+nAdded+" | Removed: "+nRemoved);
        LocalBroadcastManager.getInstance(this).sendBroadcast(i1);
        // sendBroadcast(i1);

    }

    @Override
    public void onCreate() {
        super.onCreate();
        Log.i("NLService", "NLService created!");
        nlservicereciver = new NLServiceReceiver();
        IntentFilter filter = new IntentFilter();
        filter.addAction("com.example.notifyservice.NOTIFICATION_LISTENER_SERVICE_EXAMPLE");
        registerReceiver(nlservicereciver,filter);
        Log.i("NLService", "NLService created!");
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        unregisterReceiver(nlservicereciver);
        Log.i("NLService", "NLService destroyed!");
    }

    /* > API 21
    @Override
    public void onListenerDisconnected() {
        super.onListenerDisconnected();
        Log.w("NLService", "Notification listener DISCONNECTED from the notification service! Scheduling a reconnect...");
        // requestRebind(new ComponentName(this.getPackageName(), this.getClass().getCanonicalName()));
    }

    @Override
    public void onListenerConnected() {
        super.onListenerConnected();
        Log.w("NLService", "Notification listener connected with the notification service!");
    }
    */

    @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("com.example.notify.NOTIFICATION_LISTENER_EXAMPLE");
        i.putExtra("notification_event","onNotificationPosted :" + sbn.getPackageName() + "\n");
        sendBroadcast(i);

        nAdded++;

        if (nAdded == temp) {
            System.out.println("reached" + temp);
            temp = temp + 5;
            System.out.println(temp);
            NotificationManager nManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
            NotificationCompat.Builder ncomp = new NotificationCompat.Builder(this);
            ncomp.setContentTitle("Notification");
            ncomp.setContentText("Notification Listener Service Example");
            ncomp.setTicker("Notification Listener Service Example");
            ncomp.setSmallIcon(R.mipmap.ic_launcher);
            ncomp.setAutoCancel(true);
            nManager.notify((int)System.currentTimeMillis(),ncomp.build());
        }
        broadcastStatus();
    }

    @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("com.example.notify.NOTIFICATION_LISTENER_EXAMPLE");
        i.putExtra("notification_event","onNotificationRemoved :" + sbn.getPackageName() + "\n");

        sendBroadcast(i);

        nRemoved++;
        broadcastStatus();
    }

    class NLServiceReceiver extends BroadcastReceiver {

        @Override
        public void onReceive(Context context, Intent intent) {

            if(intent.getStringExtra("command").equals("list")){
                Intent i1 = new  Intent("com.example.notify.NOTIFICATION_LISTENER_EXAMPLE");
                i1.putExtra("notification_event","=====================");
                sendBroadcast(i1);
                int i=1;
                for (StatusBarNotification sbn : NLService.this.getActiveNotifications()) {
                    Intent i2 = new  Intent("com.example.notify.NOTIFICATION_LISTENER_EXAMPLE");
                    i2.putExtra("notification_event",i +" " + sbn.getPackageName() + "\n");
                    sendBroadcast(i2);
                    i++;
                }
                Intent i3 = new  Intent("com.example.notify.NOTIFICATION_LISTENER_EXAMPLE");
                i3.putExtra("notification_event","===== Notification List ====");
                sendBroadcast(i3);

            }

        }
    }

}
7
Pushpendra On

Did you defined your services in your manifest. For notification service you need to write permission also.

        <service
            android:name=".MyService"
            android:enabled="true"/>

        <service android:name=".NLService"
                 android:label="@string/app_name"
                 android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE">
            <intent-filter>
                <action android:name="android.service.notification.NotificationListenerService" />
            </intent-filter>
        </service>

if you want to show notification in that case you need to write this code also:

 NotificationManager nManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
            NotificationCompat.Builder ncomp = new NotificationCompat.Builder(this);
            ncomp.setContentTitle("My Notification");
            ncomp.setContentText("Notification Listener Service Example");
            ncomp.setTicker("Notification Listener Service Example");
            ncomp.setSmallIcon(R.mipmap.ic_launcher);
            ncomp.setAutoCancel(true);
            nManager.notify((int)System.currentTimeMillis(),ncomp.build());

or did you provide the notification access to your app? Go to your settings and check notification access to your app provided or not?

enter image description here