Communicating From Services

Sometimes we need to get updates or data from our service to our activity/fragment in real time and then update the UI accordingly or perform some operation on the data received.We can accomplish this using below approaches-

Pending Intent

Communication between service and Activity can be done using PendingIntent.For that we can use createPendingResult() which creates a new PendingIntent object which you can hand to service to use and to send result data back to your activity inside onActivityResult(int, int, Intent) callback.Since a PendingIntent is Parcelable , and can therefore be put into an Intent extra,your activity can pass this PendingIntent to the service.The service, in turn, can call send() method on the PendingIntent to notify the activity via onActivityResult of an event.

Activity

public class PendingIntentActivity extends AppCompatActivity
{
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

PendingIntent pendingResult = createPendingResult(
100, new Intent(), 0);
Intent intent = new Intent(getApplicationContext(), PendingIntentService.class);
intent.putExtra("pendingIntent", pendingResult);
startService(intent);

}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == 100 && resultCode==200) {
Toast.makeText(this,data.getStringExtra("name"),Toast.LENGTH_LONG).show();
}
super.onActivityResult(requestCode, resultCode, data);
}
}

Service

public class PendingIntentService extends Service {

    private static final String[] items= { "lorem", "ipsum", "dolor",
            "sit", "amet", "consectetuer", "adipiscing", "elit", "morbi",
            "vel", "ligula", "vitae", "arcu", "aliquet", "mollis", "etiam",
            "vel", "erat", "placerat", "ante", "porttitor", "sodales",
            "pellentesque", "augue", "purus" };
    private PendingIntent data;

    @Override
    public void onCreate() {
        super.onCreate();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {

        data = intent.getParcelableExtra("pendingIntent");

        new LoadWordsThread().start();
        return START_NOT_STICKY;
    }

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
    }

    class LoadWordsThread extends Thread {
        @Override
        public void run() {
            for (String item : items) {
                if (!isInterrupted()) {

                    Intent result = new Intent();
                    result.putExtra("name", item);
                    try {
                        data.send(PendingIntentService.this,200,result);
                    } catch (PendingIntent.CanceledException e) {

                        e.printStackTrace();
                    }
                    SystemClock.sleep(400);

                }
            }
        }
    }
}

Event Bus

You can have the service raise events which activities or fragments can listen for and respond to using Event Bus.Event Bus can be integrated using this library which is explained here.

Activity

public class EventBusActivity extends AppCompatActivity {

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

Intent intent = new Intent(getApplicationContext(), EventBusService.class);
startService(intent);

}

@Override
protected void onStart() {
super.onStart();
EventBus.getDefault().register(this);

}

@Override
protected void onStop() {
super.onStop();
EventBus.getDefault().unregister(this);

}

@Subscribe(threadMode = ThreadMode.MAIN)
public void onWordEvent(WordEvent event) {
Toast.makeText(this,event.getWord(),Toast.LENGTH_SHORT).show();

};

}

Event

public class WordEvent {

    private String word;

    public WordEvent(String word) {
        this.word = word;
    }

    public String getWord() {
        return (word);
    }
}

Service

public class EventBusService extends Service {

private static final String[] items= { "lorem", "ipsum", "dolor",
"sit", "amet", "consectetuer", "adipiscing", "elit", "morbi",
"vel", "ligula", "vitae", "arcu", "aliquet", "mollis", "etiam",
"vel", "erat", "placerat", "ante", "porttitor", "sodales",
"pellentesque", "augue", "purus" };

@Override
public void onCreate() {
super.onCreate();
}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {

new LoadWordsThread().start();
return START_NOT_STICKY;
}

@Override
public IBinder onBind(Intent intent) {
return null;
}

@Override
public void onDestroy() {
super.onDestroy();
}

class LoadWordsThread extends Thread {
@Override
public void run() {
for (String item : items) {
if (!isInterrupted()) {

EventBus.getDefault().post(
new WordEvent(item));
SystemClock.sleep(400);

}
}
}
}
}

Messenger

Messenger references to a Handler, which others can use to send messages to it.Messenger is parcelable ,and can therefore be put into an Intent extra,so your activity can pass this Messenger to the service.Service will populate Message object with whatever data needs to be send.Whenever an event needs to be send to the activity,we need to call send() on Messenger supplying the Message object as parameter.The Handler inside activity will receive the message via handleMessage() , on the main application thread, and so can update the UI or perform necessary operation.

Activity

public class MessengerCommunicationActivity extends AppCompatActivity {

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

Messenger messenger=new Messenger(new IncomingHandler());
Intent intent = new Intent(getApplicationContext(), MessengerCommunicationService.class);
intent.putExtra("messenger", messenger);
startService(intent);

}

class IncomingHandler extends Handler
{
@Override
public void handleMessage(Message msg) {

Bundle bundle = msg.getData();
String hello = (String) bundle.get("hello");

Toast.makeText(getApplicationContext(), hello, Toast.LENGTH_SHORT).show();

}
}
}

Service

public class MessengerCommunicationService extends Service {

Messenger data;
private static final String[] items= { "lorem", "ipsum", "dolor",
"sit", "amet", "consectetuer", "adipiscing", "elit", "morbi",
"vel", "ligula", "vitae", "arcu", "aliquet", "mollis", "etiam",
"vel", "erat", "placerat", "ante", "porttitor", "sodales",
"pellentesque", "augue", "purus" };

@Override
public void onCreate() {
super.onCreate();
}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {

data = intent.getParcelableExtra("messenger");
new LoadWordsThread().start();
return START_NOT_STICKY;

}

@Override
public IBinder onBind(Intent intent) {
return null;
}

@Override
public void onDestroy() {
super.onDestroy();
}

class LoadWordsThread extends Thread {
@Override
public void run() {

for (String item : items) {
if (!isInterrupted()) {

Message msg=Message.obtain();
Bundle bundle = new Bundle();
bundle.putString("hello", item);
msg.setData(bundle);
try {
data.send(msg);
} catch (RemoteException e) {
e.printStackTrace();
}
SystemClock.sleep(400);

}
}
}
}
}

Broadcast Intents

Service can send a broadcast which can be responded by the activity.The service can call sendBroadcast() supplying the intent in which broadcast message is wrapped.The activity can register a BroadcastReceiver via registerReceiver() .When the activity’s BroadcastReceiver receives the broadcast it can perform operation on the basis of intent data received.

Activity

public class BroadcastDemoActivity extends AppCompatActivity {

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

Intent intent = new Intent(getApplicationContext(), BroadCastService.class);
startService(intent);

}

BroadcastReceiver receiver=new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(BroadcastDemoActivity.this,intent.getStringExtra("name"),Toast.LENGTH_LONG).show();
}
};

@Override
protected void onStart() {
super.onStart();
LocalBroadcastManager.getInstance(BroadcastDemoActivity.this).registerReceiver(receiver,new IntentFilter("BroadCastDemo"));
}

@Override
protected void onStop() {
super.onStop();
LocalBroadcastManager.getInstance(BroadcastDemoActivity.this).unregisterReceiver(receiver);
}
}

Service

public class BroadCastService extends Service {

private static final String[] items= { "lorem", "ipsum", "dolor",
"sit", "amet", "consectetuer", "adipiscing", "elit", "morbi",
"vel", "ligula", "vitae", "arcu", "aliquet", "mollis", "etiam",
"vel", "erat", "placerat", "ante", "porttitor", "sodales",
"pellentesque", "augue", "purus" };

@Override
public void onCreate() {
super.onCreate();
}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {

new LoadWordsThread().start();
return START_NOT_STICKY;

}

@Override
public IBinder onBind(Intent intent) {
return null;
}

@Override
public void onDestroy() {
super.onDestroy();
}

class LoadWordsThread extends Thread {
@Override
public void run() {
for (String item : items) {
if (!isInterrupted()) {

Intent result = new Intent();
result.putExtra("name", item);
result.setAction("BroadCastDemo");
LocalBroadcastManager.getInstance(BroadCastService.this).sendBroadcast(result);
SystemClock.sleep(400);

}
}
}
}
}

 

Advertisements

4 thoughts on “Communicating From Services

    • I think you mean to ask what to use when..When you want to communicate from service to an Activity or Fragment which did NOT started the service then you can use Event Bus or Broadcast Intents since they can receive callback for an event in any activity or fragment wherever they are implemented.If you want to communicate from service to an activity/fragment which started the service then you can use Pending Intent or Messenger as they can be put into an Intent extra and passed to Service.

      Like

  1. Thank you for this great post! may I ask a question: which way is the most suitable if my activity is sending images (like camera preview at 20fps) to another service which do the background network uploading job? since this seems like a very intense communication, I wonder which way is the best choice. thank you!

    Like

Leave a Reply to androidlearnersite Cancel reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s