23

My Application uses a service that is started by a BOOT_COMPLETE BroadcastReceiver, in run i'm getting an error

my code:

public class projet extends BroadcastReceiver { 
 public void onReceive(Context context, Intent intent) { 

  intent = new Intent(context, ScreenshotService.class);
  intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
  context.bindService(intent, aslServiceConn, Context.BIND_AUTO_CREATE);
}
}

error:

java.lang.RuntimeException: Unable to start receiver com.example.projet: android.content.ReceiverCallNotAllowedException: BroadcastReceiver components are not allowed to bind to services
yasso
  • 303
  • 1
  • 5
  • 11
  • http://skillgun.com/question/538/android/receivers/what-will-happen-if-broad-cast-receiver-binds-to-binder-service-is-there-any-problem – Durai Amuthan.H Jun 22 '14 at 16:42
  • Just simple. I created an empty Activity (non UI, just onCreate() for Bind service) and finish(). In Broadcast > Start Activity with Bundle (if needed). Problem's resolved. – hungtdo Oct 20 '17 at 18:41

8 Answers8

30

One should not bind a service from Broadcast receiver. The reason is broadcast receivers are light weight components, where it has to finish its functionality with in not more than 10 seconds maximum. Else android may forcefully kill your receiver. Binding (establishing connection to) a service may take more than 10 seconds in some worst cases, that's why android won't allow it.

Rules for Broadcast Receivers:

  1. Broadcast receivers will not have any UI(mostly) and it will have only background logic.
  2. Broadcast receivers will have the maximum time limit of 10 sec to finish its functionality otherwise it will crash.
  3. You should not do long running operations or asynchronous operations in the receiver. Example: a. Preparing SD card. b. Uploading / Downloading files from internet. c. Creating Db files. d. Binding to services
  4. Do not show dialog to the user in broadcast receiver. (this is asynchronous operation)
  5. You can use “ toast” or “Notifications”.
  6. Don’t write any heavy functionalities.

Ref taken from developer android

F43nd1r
  • 7,690
  • 3
  • 24
  • 62
user1923551
  • 4,684
  • 35
  • 29
  • 5
    Good answer! You can however START a service from a broadcast receiver. – Eran Katsav Dec 29 '15 at 21:06
  • Just simple. I created an empty Activity (non UI, just onCreate() for Bind service) and finish(). In Broadcast > Start Activity with Bundle (if needed). Problem's resolved. – hungtdo Oct 20 '17 at 18:41
15

If you know that the Service is running you can aquire its Binder with BroadcastReceiver.peekService(Context, Intent) method (See peekService docs).

But, as it is already said in the other answers, it is not allowed to bind a Service from within a BroadcastReceiver.

Tomasz Gawel
  • 8,379
  • 4
  • 36
  • 61
  • 4
    Note that `peekService` seems to return `null` when the service is not running or the service is not already bound to by something else. – Sam Feb 18 '15 at 12:17
  • 1
    @Sam This is exactly what I wrote. Pay attention to the words "If you know that the Service is running". – Tomasz Gawel Feb 18 '15 at 12:51
  • 1
    No it's not; you didn't mention that it returns `null` on failure, and you didn't mention that it fails if the service is running but not already bound to something else. – Sam Feb 18 '15 at 20:33
6

Best way is to first start an IntentService from BroadcastReceiver.onReceive() using:

context.StartService(new Intent(context, YourIntentService.class));

Then in the IntentService.onHandleIntent():

@Override
protected void onHandleIntent(Intent intent) {
    mContext = getApplicationContext();
    mContext.bindService(new Intent("com.ServiceToBind.BIND"), yourConnection, Context.BIND_AUTO_CREATE);
}
Eric
  • 16,397
  • 8
  • 68
  • 76
gaurav414u
  • 812
  • 13
  • 22
  • 1
    Make your life easy. :-) – gaurav414u Apr 14 '15 at 06:21
  • Hey, the guy who downvoted my reply. Can you please explain, what didnt you like about this? This was the best possible way I could think of and in fact I am using this code in my app. So, the code is even tested and proven to be working. – gaurav414u Mar 10 '16 at 15:32
  • 1
    My bad. Ya, its an intentService. Thanks @Eric – gaurav414u Mar 29 '16 at 06:50
  • do you have to worry about unbinding after the IntentService did whatever it had to with the service ? – Someone Somewhere Aug 16 '19 at 18:56
  • Worked like charm for me. Thank you. It is unfortunate that Google decided to deprecate `IntentService` in API level 30. They suggest to use `WorkManager` instead. But I am not sure if the same results can be achieved using `WorkManager`. Any idea? – W.M. Oct 09 '21 at 20:23
2

Problem

BroadcastReceivers are not allowed to be bound to a Service as the other answers here have indicated.

Solution

A simple solution I used is to forward the Intent received by the BroadcastReceiver to the service you originally wanted to bind to, then implement some code in that service's onStartCommand() method to handle it.

Eric
  • 16,397
  • 8
  • 68
  • 76
0

read http://developer.android.com/reference/android/content/BroadcastReceiver.html, section Receiver Lifecycle

pskink
  • 23,874
  • 6
  • 66
  • 77
0

According to bindService documentation:

Note: this method can not be called from a BroadcastReceiver component. A pattern you can use to communicate from a BroadcastReceiver to a Service is to call startService(Intent) with the arguments containing the command to be sent, with the service calling its stopSelf(int) method when done executing that command.

What I did: (Not sure if it works in all cases) You can create a Service and start that service in your BroadcastReceiver. Inside your service onCreate() method, you can call a method from another class who is in charge of binding. You can pass the context from service to that class and use it like this: ctx.bindService(...)

0

BroadcastReceiver cann't bindService. You can get a good solution in the following URL:

Android - Start service on boot

Community
  • 1
  • 1
qin hao
  • 43
  • 6
0

Just simple. Opt 1: I created an empty Activity (non UI, just onCreate() for Bind service) and finish(). In Broadcast > Start Activity with Bundle (if needed). Problem's resolved.

Opt 2: The same way above options but using an Service instead of Activity. Get event Broadcast > Start a new Service > Bind to existing Service you want to bind.

hungtdo
  • 661
  • 7
  • 15