1

I have (what I am sure is a simple) problem with Lollipop and explicit intents. I have built an app that communicates over a bluetooth connection to a printer - this works fine on anything below Lollipop.

I've checked various other answers and the Android documentation but cannot see any difference between the way that they create an explicit intent to the way I have done so.

The error from logcat is the following:

03-02 14:35:43.471: E/AndroidRuntime(28094): FATAL EXCEPTION: main
03-02 14:35:43.471: E/AndroidRuntime(28094): Process: com.example.app, PID: 28094
03-02 14:35:43.471: E/AndroidRuntime(28094): java.lang.RuntimeException: Error receiving broadcast Intent { act=printing flg=0x10 (has extras) } in com.example.app.AppName$1@351d4863
03-02 14:35:43.471: E/AndroidRuntime(28094):    at android.app.LoadedApk$ReceiverDispatcher$Args.run(LoadedApk.java:969)
03-02 14:35:43.471: E/AndroidRuntime(28094):    at android.os.Handler.handleCallback(Handler.java:739)
03-02 14:35:43.471: E/AndroidRuntime(28094):    at android.os.Handler.dispatchMessage(Handler.java:95)
03-02 14:35:43.471: E/AndroidRuntime(28094):    at android.os.Looper.loop(Looper.java:155)
03-02 14:35:43.471: E/AndroidRuntime(28094):    at android.app.ActivityThread.main(ActivityThread.java:5696)
03-02 14:35:43.471: E/AndroidRuntime(28094):    at java.lang.reflect.Method.invoke(Native Method)
03-02 14:35:43.471: E/AndroidRuntime(28094):    at java.lang.reflect.Method.invoke(Method.java:372)
03-02 14:35:43.471: E/AndroidRuntime(28094):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1028)
03-02 14:35:43.471: E/AndroidRuntime(28094):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:823)
03-02 14:35:43.471: E/AndroidRuntime(28094): Caused by: java.lang.IllegalArgumentException: Service Intent must be explicit: Intent { act=printing flg=0x10 (has extras) }
03-02 14:35:43.471: E/AndroidRuntime(28094):    at android.app.ContextImpl.validateServiceIntent(ContextImpl.java:1786)
03-02 14:35:43.471: E/AndroidRuntime(28094):    at android.app.ContextImpl.stopServiceCommon(ContextImpl.java:1844)
03-02 14:35:43.471: E/AndroidRuntime(28094):    at android.app.ContextImpl.stopService(ContextImpl.java:1805)
03-02 14:35:43.471: E/AndroidRuntime(28094):    at android.content.ContextWrapper.stopService(ContextWrapper.java:520)
03-02 14:35:43.471: E/AndroidRuntime(28094):    at com.example.app.AppName$1.onReceive(ExampleClass.java:530)
03-02 14:35:43.471: E/AndroidRuntime(28094):    at android.app.LoadedApk$ReceiverDispatcher$Args.run(LoadedApk.java:950)
03-02 14:35:43.471: E/AndroidRuntime(28094):    
... 8 more

I call this function from 3 other activities so have put it in it's own class and call it by doing the following:

// In the activity I call it from
ExampleClass example = new Example(this);
example.print(); // Function in the example class

Then in this print function:

IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(PRINT_ACTION);
ctx.registerReceiver(intentReciever, intentFilter); // Where ctx is the context                 
Intent i = new Intent(ctx, printerService.class);
i.putExtras(bundle);
ctx.startService(i); // Start the relevant service

The android documentation:

Intent downloadIntent = new Intent(this, DownloadService.class); downloadIntent.setData(Uri.parse(fileUrl)); startService(downloadIntent);

Apart from the setData and putExtras, I cannot see any difference.

And in the same class as the above (the broadcast receiver):

private BroadcastReceiver intentReciever = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        context.unregisterReceiver(intentReciever);
        context.stopService(intent); // If I remove this, I get multiple returns, but if I leave it - it crashes :(
    }
};

In the printerClass.class (intentService) file I have:

Intent broadcastIntent = new Intent();
broadcastIntent.setAction(ExampleClass.PRINT_ACTION);
broadcastIntent.putExtras(ReceivedBundle); // Put all the received data back in and send back!
getBaseContext().sendBroadcast(broadcastIntent);

To me, this looks like the service is already explicit but obviously not!

The issue looks to be at the point of return but I am so lost its unreal! any help with this would be massively appreciated.

manlio
  • 18,345
  • 14
  • 76
  • 126
  • You need to pass `context` in `stopService()` – Apurva Mar 02 '15 at 15:33
  • @Apurva, thanks - but how would one do this? Would `context.stopService(intent);` pass the context? – theGuyWithCows Mar 02 '15 at 15:41
  • Possible duplicate of [Android L (API 21) - java.lang.IllegalArgumentException: Service Intent must be explicit](https://stackoverflow.com/questions/27183164/android-l-api-21-java-lang-illegalargumentexception-service-intent-must-be) – rds Oct 16 '17 at 13:02

1 Answers1

0

Your onReceive() method does this:

public void onReceive(Context context, Intent intent) {
    context.unregisterReceiver(intentReciever);
    context.stopService(intent); // If I remove this, I get multiple returns, but if I leave it - it crashes :(
}

This calls stopService() using the Intent that the BroadcastReceiver is started with (the broadcast Intent). If you look at your code that creates the broadcast Intent, it looks like this:

Intent broadcastIntent = new Intent();
broadcastIntent.setAction(ExampleClass.PRINT_ACTION);
broadcastIntent.putExtras(ReceivedBundle);

This Intent has only an ACTION and EXTRAS. It is an implicit Intent, not an explicit Intent.

NOTE: This "works" on other platforms because it isn't actually stopping your Service at all. The code that calls stopService() is just doing nothing because there is no Service that responds to the Intent.

On Android 5, the call to stopService() is throwing an exception due to the tightening of security regarding implicit Intent for Services.

David Wasser
  • 93,459
  • 16
  • 209
  • 274
  • I have removed the `context.stopService(intent)` and this does seem to have stopped the crashing. Thanks for you help. – theGuyWithCows Mar 04 '15 at 10:05
  • Are you sure about your NOTE? I've tested it on Android 4.4 and the service is stopped and destroyed quite happily. In my case it's foreground service. – Boris Treukhov Jan 29 '16 at 18:28