Java Question How to create library that extends Service and has Abstract Public Methods

barx

Well-Known Member
Licensed User
Longtime User
OK, I'm having a look at creating a library for the new notification feature found in Android 4.3. NotificationListenerService. Obviously, being brand new there isn't much info about for it yet in the way of examples and tutorials.
The only tutorial I can find is This

I don't have a massive amount of library experience. I cannot for the life of me think how to implement this.

As a side note the .getActiveNotifications method returns an array of type StatusBarNotification[]. Obviously, we don't have this type in B4A and I have no idea how to create this type to be used. My thought was to iterate the array in the library and build a List of Maps to return. Which would be better?

Any ideas, hints and tips, on this would be great.

Or if anyone else feels like doing it (as once the back bone is done, there are only a few methods to build) ;););)
 

thedesolatesoul

Expert
Licensed User
Longtime User
Looks easy (just kidding!)
Okay, I scrapped my first response.
Second attempt (pretty much what the example does),
- Create NLService that extends NotificationListenerService inside the library.
- Instead of a dynamic receiver, define a static receiver in the manifest.
- In the events onNotificationPosted, use an intent to call another service or activity (and check their onResume)

About the side note, StatusBarNotification also implements getNotification which is all you need to expose? I would not use a map, but rather a NotificationObjectWrapper or something like that.
 

barx

Well-Known Member
Licensed User
Longtime User
in English man, in English!
 

barx

Well-Known Member
Licensed User
Longtime User
... maybe you can FreeLance it for me ;)
lol
I will give it a crack when I get a few minutes.

Thanks buddy
 

bitstra

Member
Licensed User
Longtime User
Hi @thedesolatesoul, Hi @barx,

tried to make a lib as described in samplecode (link in pos #1).

compiled the lib with service class NLservice successfull in eclipse.
defined static receiver in manifest xml... O.K.

can checkin my app for Notificationservice in Setup->security.

but my app crashes right on start, if I make a 'Dim NLs as NLService' in a ba-service-module or activit of m app.

any tipps ???


regards and thanx

bitstra


Java-Code (android API level 18...; some remarks '//' are results of my tests):
B4X:
package de.esolutions4you.nlservice;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.service.notification.NotificationListenerService;
import android.service.notification.StatusBarNotification;
import android.util.Log;
import anywheresoftware.b4a.BA;
import anywheresoftware.b4a.BA.ShortName;
import anywheresoftware.b4a.BA.Version;
import anywheresoftware.b4a.BA.Author;
import anywheresoftware.b4a.BA.Events;

@Version(1.5f)
@ShortName("NLService")

public class NLService extends NotificationListenerService {

    //private BA ba=null;
    //private String eventName="";  
    private String TAG = this.getClass().getSimpleName();
    private NLServiceReceiver nlservicereciver;
    @Override
    public void onCreate() {
        super.onCreate();
        //nlservicereciver = new NLServiceReceiver();
        //IntentFilter filter = new IntentFilter();
                        
        //filter.addAction("de.esolutions4you.bubblelauncher.srvnotificationlistener");
        //registerReceiver(nlservicereciver,filter);
    }
    @Override
    public void onDestroy() {
        super.onDestroy();
        //unregisterReceiver(nlservicereciver);
    }
    @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.esolutions4you.bubblelauncher.srvnotificationlistener");
        i.putExtra("notification_event","onNotificationPosted :" + sbn.getPackageName() + "n");
        sendBroadcast(i);
    }
    @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.esolutions4you.bubblelauncher.srvnotificationlistener");
        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("clearall")){
                    NLService.this.cancelAllNotifications();
            }
            else if(intent.getStringExtra("command").equals("list")){
                Intent i1 = new  Intent("de.esolutions4you.bubblelauncher.srvnotificationlistener");
                i1.putExtra("notification_event","=====================");
                sendBroadcast(i1);
                int i=1;
                for (StatusBarNotification sbn : NLService.this.getActiveNotifications()) {
                    Intent i2 = new  Intent("de.esolutions4you.bubblelauncher.srvnotificationlistener");
                    i2.putExtra("notification_event",i +" " + sbn.getPackageName() + "n");
                    sendBroadcast(i2);
                    i++;
                }
                Intent i3 = new  Intent("de.esolutions4you.bubblelauncher.srvnotificationlistener");
                i3.putExtra("notification_event","===== Notification List ====");
                sendBroadcast(i3);
            }
        }
    }

}
 

warwound

Expert
Licensed User
Longtime User
@bitstra

As desolatesoul said you wouldn't Dim an instance of the service.
First you need to add the service to your project's manifest, look at the tutorial again.
You need to add something like:

B4X:
<service android:name="de.esolutions4you.nlservice.NLService"
android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE">
<intent-filter>
<action android:name="android.service.notification.NotificationListenerService" />
</intent-filter>
</service>

With a bit of luck your NLService will now receive Broadcasts when notification stuff happens.

Martin.
 

bitstra

Member
Licensed User
Longtime User
O.K.

I've tried to follow your suggestions...

-the packagename in java code for NLService is now 'de.esolutions4you.bubblelauncher' - the same packagename as in my whole b4a-project .

-checked the NLService in libs-Tab(b4a-IDE)

-made no more Dim for the lib

-edited the manifest.xml in manifest editor:

B4X:
<service android:name="de.esolutions4you.bubblelauncher.NLService"
                android:label="Bubble Launcher"
                android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE">
            <intent-filter>
            <action android:name="android.service.notification.NotificationListenerService" />
            </intent-filter>
</service>

and for the static receiver in manifest xml:

B4X:
        <receiver     
            android:name="de.esolutions4you.bubblelauncher.nlservice$nlservice_BR"
            android:enabled="true">
            <intent-filter>
                <action android:name="de.esolutions4you.bubblelauncher.NLS_RUN" />
            </intent-filter>
        </receiver>

and fired a sendBroadcastIntent() in my main service code module:

B4X:
    Dim p As Phone
    Dim iBR As Intent
    iBR.Initialize("de.esolutions4you.bubblelauncher.NLS_RUN","")
    iBR.PutExtra("command","list")
    p.SendBroadcastIntent(iBR)

Now my app starts and seem to fire the SendBroadcastIntent - and now it crashes:

B4X:
PackageAdded: package:de.esolutions4you.bubblelauncher
** Activity (main) Create, isFirst = true **
** Activity (main) Resume **
** Service (srvfloatapp) Create **
** Service (srvfloatapp) Start **
** Activity (main) Pause, UserClosed = true **
java.lang.RuntimeException: Unable to instantiate receiver de.esolutions4you.bubblelauncher.nlservice$nlservice_BR: java.lang.ClassNotFoundException: Didn't find class "de.esolutions4you.bubblelauncher.nlservice$nlservice_BR" on path: DexPathList[[zip file "/data/app/de.esolutions4you.bubblelauncher-1.apk"],nativeLibraryDirectories=[/data/app-lib/de.esolutions4you.bubblelauncher-1, /vendor/lib, /system/lib]]
    at android.app.ActivityThread.handleReceiver(ActivityThread.java:2425)
    at android.app.ActivityThread.access$1500(ActivityThread.java:148)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1339)
    at android.os.Handler.dispatchMessage(Handler.java:99)
    at android.os.Looper.loop(Looper.java:137)
    at android.app.ActivityThread.main(ActivityThread.java:5151)
    at java.lang.reflect.Method.invokeNative(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:525)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:737)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
    at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.ClassNotFoundException: Didn't find class "de.esolutions4you.bubblelauncher.nlservice$nlservice_BR" on path: DexPathList[[zip file "/data/app/de.esolutions4you.bubblelauncher-1.apk"],nativeLibraryDirectories=[/data/app-lib/de.esolutions4you.bubblelauncher-1, /vendor/lib, /system/lib]]
    at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:53)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:501)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:461)
    at android.app.ActivityThread.handleReceiver(ActivityThread.java:2420)
    ... 10 more


The qualified error can be found at: 'Caused by...' ... class not found...


So my question is:

How I have to insert/link my Eclipse compiled Library 'NLService.jar' into my project???


Any help possible?

thanx and regards

bitstra
 

thedesolatesoul

Expert
Licensed User
Longtime User
You only need one receiver i.e.
<action android:name="android.service.notification.NotificationListenerService" />

No need to add the other receiver for: <action android:name="de.esolutions4you.bubblelauncher.NLS_RUN" />

So when a new notification runs, your service is fired automatically. I dont think you need the other NLServiceReceiver
 

bitstra

Member
Licensed User
Longtime User
Thank You @thedesolatesoul, @warwound!

tried also the last suggestion - but no luck!

Logcat after reboot tells me ... class not found... for NLService, so I guess, the lib can't be loaded in my project.
(BTW: till today I thought I have to Dim & Initialize every lib(jar), that's bound to a b4a-project...)

Will try now to compile a complete helper app in eclipse that fires intents to my Bubble Launcher app, when notifications are posted, canceld and so on.

I hope, that's a way to make things working in my project.

Thank you both for your time... - and also thank You @barx for finding the sample java project!


regards
 

warwound

Expert
Licensed User
Longtime User
Take your compiled library .jar file and open with a program such as WinRAR.
Browse through the folders - the folders are arranged as package names.
Can you find the missing class:

B4X:
de/esolutions4you/bubblelauncher/NLService.class

Martin.
 

bitstra

Member
Licensed User
Longtime User
Thanx Martin,

will have a look into that...

Edit:

Yes the missed class is included in the jar-file...
the library jar file is attached as zip-file below...

Ah moment I see a 'NLService$NLServiceReceiver.class' in there.
But I've used 'NLService$NLService_BR' till now...

may be a simple syntax error?!

testing ones more...


Edit2: nope! same behavior...:(
 

Attachments

  • NLService.jar.zip
    3.4 KB · Views: 313
Last edited:

bitstra

Member
Licensed User
Longtime User
O.K.

I've made a small helper java app (first time used android studio :)), which can be installed hidden from App Drawer/launcher.
This App fires the intents for posted and canceled notifications to any app, which has the fitting Broadcast Receiver registered.
Works perfect for my needs.

If anyone is interested in that , I can publish that here with a small documentation...


regards and thanx


bitstra
 

bitstra

Member
Licensed User
Longtime User
@barx

Could you try out this library? I have no idea if it will work or not.

Regards,
Tomas

Hi @XverhelstX,

I hope, it's O.K. when I tried that...

Your Lib has the same behavior like my first own test-lib. The app crashes after starting the service...
Log(initialize) runs and than it crashes (in emulator 4.3 and on real device 4.3)...

because of this behavior I use my Java-helperapp with all possibilities of the NOTIFICATION_LISTENER_SERVICE.

You should install android API level 18, so you can test it on emulator. Emu runs fine here on a Macbook Pro with VMware/Windows 8 and latest adt api18.

thanx for your work

bitstra
 

bluedude

Well-Known Member
Licensed User
Longtime User
It starts up and gets initialized but it does not do anything when notifications are received. What is Filteraction exactly doing? Does it look for notifications for certain packages?
 

bluedude

Well-Known Member
Licensed User
Longtime User
Would be interested to see that. Is it a B4A library contained in a service?
 
Top