Monday 6 April 2015

Communication between Service and Activity in Android.

Communicating Between A Service And An Activity


Often a service simply executes in its own thread, independently of the activity that calls it.
This doesn’t pose any problem if you simply want the service to perform some tasks periodically and the activity does not need to be notified of the status of the service.

For example, you may have a service that periodically logs the geographical location of the device to a database.
In this case, there is no need for your service to interact with any activities, because its main purpose is to save the coordinates into a database.
However, suppose you want to monitor for a particular location. When the service logs an address that is near the location you are monitoring, it might need to communicate that information to the activity. In this case, you would need to devise a way for the service to interact with the activity.
The following example demonstrates how a service can communicate with an activity using a BroadcastReceiver.

Invoking an Activity from a Service

1 . Using the same project created in the previous post, add the following statements in bold to the MyIntentService.java file:

package ​com.emergingandroidtech.Services;
import​ java.net.MalformedURLException;
import ​java.net.URL;
import​ android.app.IntentService;
import​ android.content.Intent;
import ​android.util.Log;

public​ class ​MyIntentService ​extends​ IntentService​
{
​​​​public ​MyIntentService()​
{
​​​​​​​​super(“MyIntentServiceName”);
​​​​}
​​​​
@Override ​​
​​protected​ void​ onHandleIntent(Intent ​intent)
​{
​​​​​​​​try​
{
​​​​​​​​​​​​int ​result​= ​​​​​​​​​​​​​​​​DownloadFile(new​URL(“http://www.amazon.com/somefile.pdf”)); ​​
​​​​​​​​​​Log.d(“IntentService”,​“Downloaded​“​+​result​+​“​bytes”);
​​​​​​​​​​​​
//---send a broadcast to inform the activity
​​​​​​​​​​​​// that the file has been downloaded--- ​​​
​​​​​​​​​Intent broadcastIntent = new Intent(); ​​​​​​​​​​​​broadcastIntent.setAction(“FILE_DOWNLOADED_ACTION”); ​​​​​​​​​​​​getBaseContext().sendBroadcast(broadcastIntent);
​​​​​​​​}
​catch​(MalformedURLException​ e)​
{
​​​​​​​​​​​​e.printStackTrace(); ​​​
​​​​​}
​​​​}
​​​​
private ​int ​DownloadFile(URL ​url)
​{
​​​​​​​​try
​{
​​​​​​​​​​​​//---simulate​ taking ​some​time​ to ​download​ a ​file--- ​
​​​​​​​​​​​Thread.sleep(5000);
​​​​​​​​}
​catch​(InterruptedException ​e)​
{
​​​​​​​​​​​​e.printStackTrace();
​​​​​​​​}
​​​​​​​​return​ 100;
​​​​}
}

2 . Add the following statements in bold to the MainActivity.java file: 

package ​com.emergingandroidtech.Services;
import​ android.app.Activity;
import​ android.content.BroadcastReceiver;
import​ android.content.Context;
import​ android.content.Intent;
import​ android.os.Bundle;
import​ android.view.View;
import​ android.widget.Button;
import ​android.widget.Toast;
import android.content.IntentFilter;

public ​class ​MainActivity ​extends ​Activity​
{
​IntentFilter intentFilter;
​​​​
/**​ Called ​when ​the​ activity ​is ​first​ created.​*/
​​​​@Override
​​​​public ​void ​onCreate(Bundle ​savedInstanceState)​
{
​​​​​​​​super.onCreate(savedInstanceState); ​​
​​​​​​setContentView(R.layout.main);
​​​​​​​​
//---intent to filter for file downloaded intent--- ​​​
​​​​​intentFilter = new IntentFilter(); ​​
​​​​​​intentFilter.addAction(“FILE_DOWNLOADED_ACTION”);
​​​​​​​​
//---register the receiver---
​​​​​​​​registerReceiver(intentReceiver, intentFilter);
​​​​​​​​
Button ​btnStart​=​(Button)​findViewById(R.id.btnStartService);
​​​​​​​​btnStart.setOnClickListener(new​ View.OnClickListener()​
{ ​​​​​​​​​​​​
public ​void ​onClick(View​ v)​
{
​​​​​​​​​​​​​​​​//startService(new​Intent(getBaseContext(),​MyService.class)); ​​​
​​​​​​​​​​​​​startService(new​Intent(getBaseContext(),​MyIntentService.class));
​​​​​​​​​​​​}
​​​​​​​​});
​​​​​​​​
Button​ btnStop​=​(Button)​findViewById(R.id.btnStopService);
​​​​​​​​btnStop.setOnClickListener(new ​View.OnClickListener()
​{
​​​​​​​​​​​​public ​void ​onClick(View​ v)​
{
​​​​​​​​​​​​​​​​stopService(new​Intent(getBaseContext(),​MyService.class)); ​​
​​​​​​​​​​}
​​​​​​​​});
​​​​}
​​​​
private BroadcastReceiver intentReceiver = new BroadcastReceiver()
{
​​​​​​​​@Override
​​​​​​​​public void onReceive(Context context, Intent intent)
{
​​​​​​​​​​​​Toast.makeText(getBaseContext(), “File downloaded!”, ​​​​​​​​​​​​​​​​​​​​Toast.LENGTH_LONG).show(); ​​​​
​​​​}
​​​​};
}

3 . Click the Start Service button. After about five seconds, the Toast class will display a message indicating that the file has been downloaded.

How It Works 

To notify an activity when a service has finished its execution, you broadcast an intent using the sendBroadcast() method:

​​​​@Override
​​​​protected ​void ​onHandleIntent(Intent​ intent)
​{
​​​​​​​​try
​{
​​​​​​​​​​​​int ​result​= ​​​​​​​​​​​​​​​​DownloadFile(new​ URL(“http://www.amazon.com/somefile.pdf”));
​Log.d(“IntentService”,​“Downloaded​“​+​result​+​“​bytes”);
​​​​​​​​​​​​
//---send a broadcast to inform the activity ​​
​​​​​​​​​​// that the file has been downloaded--- ​​​​
​​​​​​​​Intent broadcastIntent = new Intent(); ​​​​​​​​​​​​broadcastIntent.setAction(“FILE_DOWNLOADED_ACTION”); ​​​​​​​​​​​​getBaseContext().sendBroadcast(broadcastIntent); ​​
​​​​​​}​
catch​(MalformedURLException ​e)​
{
​​​​​​​​​​​​e.printStackTrace(); ​​
​​​​​​}
​​​​}

The action of this intent that you are broadcasting is set to “FILE_DOWNLOADED_ACTION”, which means any activity that is listening for this intent will be invoked.
Hence, in your MainActivity.java file, you listen for this intent using the registerReceiver() method from the IntentFilter class:
​​​​
@Override
​​​​public ​void​ onCreate(Bundle​ savedInstanceState)
​{
​​​​​​​​super.onCreate(savedInstanceState);
​​​​​​​​setContentView(R.layout.main);
​​​​​​​​
//---intent to filter for file downloaded intent--- ​​​
​​​​​intentFilter = new IntentFilter(); ​​
​​​​​​intentFilter.addAction(“FILE_DOWNLOADED_ACTION”); ​​​
​​​​​
//---register the receiver---
​​​​​​​​registerReceiver(intentReceiver, intentFilter);
 ​​​​​​​​... ​​​​​​​​... ​​​​}

When the intent is received, it invokes an instance of the BroadcastReceiver class that you have defi ned:

​​​​private ​BroadcastReceiver ​intentReceiver​=​new ​BroadcastReceiver()​
{
​​​​​​​​@Override ​​
​​​​​​public ​void ​onReceive(Context​ context,​Intent​ intent)​
{ ​
​​​​​​​​​​​Toast.makeText(getBaseContext(),​“File​downloaded!”, ​​​​​​​​​​​​​​​​​​​​Toast.LENGTH_LONG).show();
​​​​​​​​} ​
​​​};
}

In this case, you displayed the message “File downloaded!” Of course, if you need to pass some data from the service to the activity, you can make use of the Intent object.

No comments:

Post a Comment