36

I have a particular situation: a service started by a broadcast receiver starts an activity. I want to make it possible for this activity to communicate back to the service. I have chosen to use AIDL to make it possible. Everything seems works good except for bindService() method called in onCreate() of the activity. bindService(), in fact, throws a null pointer exception because onServiceConnected() is never called while onBind() method of the service is. Anyway bindService() returns true. The service is obviously active because it starts the activity. I know that calling an activity from a service could sound strange, but unfortunately this is the only way to have speech recognition in a service.

Thanks in advance

Matroska
  • 6,885
  • 14
  • 63
  • 99

12 Answers12

61

I've just experienced another version of this problem, with the same symptom of onServiceConnected(...) not being called. The cause was different in my case.

You must make sure to have a service declaration in your AndroidManifest.xml within the application tag - this was the root of the problem for me.

<application android:name=".YourAppTitle" android:icon="@drawable/icon" android:label="@string/app_name">
    <activity android:name=".Main" android:label="@string/app_name">
    </activity>
    <service android:name="YourService" />
</application>

There's an extra complication if you're using a separate Android library within Eclipse - adding this Service tag only seems to fix the issue if the referenced service is in the same package as the manifest; i.e. if your app is in package a.b.c and this is where AndroidManifest.xml resides, then 'YourService' must also be in package a.b.c. (manually copied from another library, if necessary) or else the <service..> tag may/will be ignored and onServiceConnected(...) still won't be called.

This was the case for my project even though I used a suitable import statement for the Service in my code. Eclipse showed no error, so the import was correctly identifying the class from another library in the Eclipse workspace.

HTH

KomodoDave
  • 7,239
  • 10
  • 60
  • 92
  • My service is in a library and I have this problem—do you have to create a new service that inherits the old one? – Andrew Wyld Apr 24 '12 at 15:39
  • I've got a library project containing a billing service that I want to keep largely identical in a bunch of child projects; I have modified this to be abstract and made a service that inherits it in the sub project, but I get the same error as previously. To be clear, does the `bindService(...)` call have to come FROM the inherited `Service` or can it be in the abstract parent? And do you know the root cause of this problem? – Andrew Wyld Apr 24 '12 at 16:27
  • What I've written is all the info I have I'm afraid; I've ceased Android development through frustration with the API and firmware bugs since posting last year. – KomodoDave Apr 25 '12 at 13:49
  • I found that the error was actually caused because the service hadn't had `attachBaseContext(Context)` called on it. At any rate, including that call fixed the error. – Andrew Wyld Apr 26 '12 at 14:01
  • @KomodoDave Thanks a trillion, you saved me my day. I followed an official tutorial here http://developer.android.com/guide/components/bound-services.html#Binder without first learning about Service. Common mistake of impatience newbies, I guess. :D:D:D – Max Mar 16 '13 at 23:19
  • when copying the code, the line is forgotten in AndroidManifest.xml – vitalinvent Jul 06 '21 at 12:19
  • saved me.. initially the service was binding well then i decided to create an abstract service and implement a new concrete service, and forgot to add it into AndroidManifest. It doesn't give any error at all just does nothing! – Bruce Mar 22 '22 at 11:22
56

After hours and hours of trying to figure this out, the issue is that the examples that show the creation of the service, don't include the onBind method or they have the following sample code or it generates this for you:

public IBinder onBind(Intent intent) {
    // TODO Auto-generated method stub
    return null;
}

This causes the onServiceConnected method to fail or never actually get executed. The fix is VERY simple, which is the following:

public IBinder onBind(Intent intent) {
    return mBinder;
}

Where you could create a simple binder such as the following to return:

private final IBinder mBinder = new LocalBinder();
public class LocalBinder extends Binder {
    public ConferenceService getService() {
    return ConferenceService.this;
  }
}
DustinB
  • 11,037
  • 5
  • 46
  • 54
Brad Brown
  • 561
  • 1
  • 4
  • 3
  • 3
    Thanks, Brad, saved me some time here! I had two issues, the one you point out here as well as not having the service defined in manifest file. I found that checking status of bindService() is important, too. – DustinB Oct 28 '11 at 17:33
  • This is documented here: http://developer.android.com/guide/components/bound-services.html#Binder – Rolf Aug 21 '14 at 14:47
25

The onServiceConnected event was never being called in my application.

The problem was that I had the service name defined in my Application Manifest as:

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

Once I changed it to the full class name it worked:

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

Update: You can also have use a relative class name:

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

Specify the class name using its full com.example.MyServiceClass instead of just MyServiceClass.

IanGSY
  • 3,664
  • 1
  • 22
  • 40
  • Thanks. In my case using "MyService" is sufficient, but with the craziness of programming in Java, I guess this might be a safer (or safest) option whenever I implement a service. – Max Mar 16 '13 at 23:21
  • 3
    actually you need to put in ".MyService" not the full one unless it's outside the package. – Archimedes Trajano Jul 22 '13 at 03:10
  • 1
    I don't exactly understand why but this is absolutely true! This answer just fixed my problem. –  Jan 16 '14 at 14:31
14

I can't make up the exact problem out of your description, so I'm going to guess here!

How can bindService() throw a NullPointerException? The only way this could (/should) happen is when you don't supply a Service or a ServiceConnection listener.

bindService() can't throw a NullPointerException because onServiceConnected() isn't called. The call to onServiceConnected() is a product of bindService().

So I guess you are calling a AIDL method, before the Service has actually bonded?

MrSnowflake
  • 4,724
  • 3
  • 29
  • 32
  • 1
    yes sorry, I understand the problem could be explained better. NullPointerException is thrown because the remote interface is never filled as remote = IRemoteService.Stub.asInterface(service); in onServiceConnected() is never called. Should bindService trigger the onServiceConnected immediately? – Matroska Mar 21 '10 at 13:28
  • 4
    `onServiceConnected()` should not be called __immediately__, there will probably be a small delay. – MrSnowflake Mar 21 '10 at 18:13
  • You are right! The method is not called immediately. That was my problem. – Matroska Mar 21 '10 at 20:56
  • @Matroska but how call that immediately? I am also having the same problem with the `NullPointerException` and can't seem to get rid of it – noloman Jul 20 '11 at 10:34
11

One more thing is that if you are calling bindservice method inside the oncreate method then the onserviceconnected is called after the oncreate method is finished.

So any references to the interface functions before the oncreate ends (or before onserviceconnected is called) shows null pointer exception.

doubleDown
  • 8,048
  • 1
  • 32
  • 48
Abhijeet
  • 111
  • 1
  • 2
  • This was exactly the problem I was running into, I was calling bind(... within onCreate and had no idea why the service ALWAYS returned null, thank you!! – Sauron Apr 29 '15 at 00:56
5

Yet another cause to the original question might be that the service isn't already running and you are passing 0 as flag to bindService. Like so:

bindService(intent, serviceConnection, 0);

When what you are looking for would be:

bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE);
pakerfeldt
  • 1,491
  • 1
  • 14
  • 23
2

If someone's still looking for the answer after trying all others then this might help.. onServiceConnected() is not called immediately after bindService(...). it takes few seconds. So if you are receiving some value from the onServiceConnected() and you have to use it somewhere else in onCreate or onStart it will throw a NullPointerException because of the delay. So if you can shift that line of code which needs the value from onCreate or onStart, inside onServiceConnected(){......}, below the line of declaration of the value that you need then it might work.

Rohan majhi
  • 121
  • 1
  • 4
1

There can be another explanation, not a very frequent situation, but I managed to get into it and lose 2 hours to solve it.

So what I did was that I wanted to reuse the bundle from the intent received by the onBind method. But I went for the lazy version and changed the class of the intent. Apparently this causes the onServiceConnected not to get called. Probably because the system keeps a reference to the intent and uses it when calling onServiceConnected.

In conclusion don't change the intent you receive in onBind.

Stefan Alexandru
  • 563
  • 1
  • 5
  • 18
1

I also encountered the same problem. And minutes later I found that my code had absolutely no problem. It was the manifest file that had the issue. Earlier I was declaring the service with its name only.

<service android:name=".MyBoundService"/>

Change it to the full name with the package name

<service android:name="com.pb.servicedemo.MyBoundService"/>

This way you will be able to see your service bound to the activity.

priyanka.b
  • 91
  • 1
  • 2
0

I was calling bind with an empty Intent - getContext().bindService(new Intent(), mConnection, Context.BIND_AUTO_CREATE). I have to make the intent more specific to indicate which service I want to bind to. This is obviously a code error, but the Logcat output was unfortunately not clear enough.

Gallal
  • 4,267
  • 6
  • 38
  • 61
0

You Must Wait To Complete onCreate() method. Example: Set Your Buy Service in Buttom:

Button button_useservice=findViewById(R.id.button_useservice);
            button_useservice.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    UsinService();
                }
            });
0

I just spent a lot of time on this one, and since in my case it was neither of the above answers I'll just lay out another possible scenario:

This happened to me when I was using a kotlin.coroutines.Deferred object to represent my bound service, and I blocked the thread that onServiceConnected should be called on when I called await() on this object.

So basically - don't block the main thread waiting for onServiceConnected to be called, or it won't be able to be called...

yonix
  • 11,665
  • 7
  • 34
  • 52