1

Suppose I have one activity , MainActivity and one service MyService in my android studio project.

MainActivity.class

Toast.makeText(this,"Point 1",Toast.LENGTH_SHORT).show();
startService( new Intent(this,MyService.class) ) ;
Toast.makeText(this,"Point 3",Toast.LENGTH_SHORT).show();

MyService.class

Toast.makeText(this,"Point 2",Toast.LENGTH_SHORT).show();

The flow of execution is Point 1 -> Point 3 -> Point 2 & not 1->2->3

Since service runs in main ui thread only , so what actually happens in background ? since all 3 points execute on same thread .

EDIT:

What can I do to make execution like 1->2->3 ?

Using a static variable in MyService(and setting a value there) and importing that variable in MainActivity to check if service has been started successfully ,doesnt work( causes ANR- reason: Starting .MyService ).

In MainActivity

while(! staticvar.hasBeenSetInMyService){ }

It gets stuck in endless while loop . So is the static variable never updated in MainActivity or MyService's onStartCommand() doesnt get executed ??

Akhil
  • 41
  • 1
  • 9
  • 2
    `startService` is an asynchronous function in a way that it does not wait for the service to be completely started. It basically fires the provided intent and then the function is done. Although the service indeed runs on the main thread, it is very likely that the Android system is doing some work before the service is actually started and most likely that takes place on a background thread – 0xDEADC0DE Jan 19 '18 at 13:41
  • @0xDEADC0DE, why don't you put that as an answer? – azizbekian Jan 19 '18 at 15:56
  • @0xDEADC0DE I have updated my question . Mind looking at it ? – Akhil Jan 19 '18 at 16:24
  • @Akhil; Now you're blocking the main thread, probably preventing the service to start. This explains your ANR. If you must have the flow you're describing, binding to your service might be a solution. You can find information for it here: https://developer.android.com/guide/components/bound-services.html – 0xDEADC0DE Jan 22 '18 at 07:07

1 Answers1

1

There are several ways to let components exchange information. In your case, the Activity could register a BroadcastReceiver with the LocalBroadcastManager before starting the Service.

private BroadcastReceiver myReceiver = new BroadcastReceiver(){
    public void onReceive(Context context, Intent intent) {
        Toast.makeText(context,"Received broadcast from Service",Toast.LENGTH_SHORT).show();
        MainActivity.this.doPointThree(); 
    }
}

The Activity has to register and (never forget!) unregister the BroadcastReceiver, but I won't go into details here and link instead to this post on Stack Overflow.Let's just assume the BroadcastReceiver will be registered with an

IntentFilter if = new IntentFilter();
if.addAction("your.package.com.POINT_2");

The Service on the other hand can send a local broadcast once it has reached "Point 2".

Intent intent = new Intent();
intent.setAction("your.package.com.POINT_2");
LocalBroadcastManager.getInstance().sendBroadcast(intent);

This local broadcast will trigger the BroadcastReceiver's onReceive()

Please note that I'm talking about local broadcasts as opposed to system wide, inter-app broadcasts. Local broadcasts are easy on the system and totally private to your app.

Bö macht Blau
  • 12,820
  • 5
  • 40
  • 61
  • I do know about local broadcasts . But the fact is that I was looking for an alternate solution for this . Is there any other way for this ? Thanks ! – Akhil Jan 20 '18 at 11:18
  • 1
    @Akhil - if you don't like BroadcastReceivers then I think you also won't like using a bound `Service` and `Handler`s (for incoming `Message`s). One other option would be a kind of Observer solution where the Observer could be a field of the Application class. The Activity would have to register as Listener with this Observer. And, last not least, there are various EventBus solutions available, e.g. Otto EventBus – Bö macht Blau Jan 20 '18 at 19:55