Android Tips — Activity and Service


An Activity and Service are the basic building blocks for an Android app. Usually, the Activity handles the User Interface (UI) and interactions with the user, while the service handles the tasks based on the user input. If you are new to Android development, it can be confusing at times when to use an Activity or a Service. My goal in this post is to go over briefly, what an Activity and Service are and when you should use them.

 


What Is an Activity

An activity is a single, focused thing that the user can do. It is the foreground task that is right in front of the user. Almost all activities interact with the user, so the Activity class creates a window for you to place your UI by loading a UI layout.

 

How to Interact with User

The way an Activity interacts with a user is by responding to events. The UI elements in your layout are often bonded to the Activity through functions or methods. For example, your UI has a TextView to show some static text and you want to change it when the user presses a button. For this to work your Button must bind to a function in your activity class and it will invoke that function every time it is pressed. The function will set the new text for the TextView by interacting with the reference of the instanced TextView.

 

Summary

  • Activity presents the UI to the user and handles interaction from the user
  • UI elements can bind to functions in the Activity so that the Activity can respond back to the user

 

For more details on working with Activity, you can check out my post about Activity Lifecycle.

 

When to Use Activity

You will likely be using Activities if your app depends on user inputs. The activity displays the UI and handles any user inputs, which means your app likely have a few activities. A simple rule to go by is that if UI is involved then you want to use an Activity. If UI is not necessary then a Service might be better for your need.

 

What Is a Service

A Service in Android is an application component that can perform long-running operations in the background. This means that a Service does not provide a UI. A service can run independently meaning that after your app starts the service, it can run even when your app is no longer in focus.

 

A Service provides great flexibility by having three different types. They are Foreground, Background, and Bound.

 

Foreground

A foreground service performs operations that is noticeable to the user. For example, a foreground service would be playing audio. A foreground service continues to run even when the user is not interacting with your app. It is important to note that foreground services must display a status bar icon.

 

Background

A background service performs an operation that is not directly noticeable by the user. For example, a service that compacts its storage or updates a database.

 

Bound

A service is bound when an application component binds to it through the bindService() function. Bound service offers a client-server interface that allows an application component to interact with the service, send requests, receive requests, and even do so with interprocess communication (IPC).

 

Unlike other types of services, a bound service runs as long as another application service is bound to it. For example, multiple components can bind to the service at once, but when all the components unbind, the service is destroyed.

 

Persistent Service

In addition, you can specify if a service is persistent or not. If a service is persistent (Sticky), then if the Android system at any point kills the service’s process, it will mark the service for restart as soon as resources are available. If the service is not persistent (Non-sticky), then once the service’s process is killed while running, it will not be marked for restart. In order to define whether a service is sticky or not, you must override the “onStartCommand” function to return the flag for Sticky or Non-sticky.

 

When to Use Service

You will likely use a service when you want to do something that does not involve UI and needs it to run whether your app is running or not. For example, if you want to play audio a service would be a choice because the audio will still play when the user opens another app.

 

Using Activity and Service Together

Activity and Service communication with broadcast

There are two simple ways for you to use an Activity and Service together. One way is to create a bound service and bind a component in your activity to the service acting as a communication channel. Another way is to use the Android Broadcast System, which sends out a broadcast intent system-wide. For this to work, you will need to have your own set of actions in your app, which only your app will understand. In your activity class, you will register a broadcast receiver that will listen for any of the actions pertaining to your app. Since an intent can carry data, you can communicate data back and forth between an Activity and Service through this method.

 

Here is an example of an Activity and Service structured to listen to each other’s broadcasts and process the request:

 

public class MyAppActivity extends Activity {
	private static final String ACTION_SUPER_AWESOME_TASK_1 = "my.app.action.super.awesome.task1";
	private static final String ACTION_SUPER_AWESOME_TASK_2 = "my.app.action.super.awesome.task2";
	private static final String ACTION_SUPER_AWESOME_TASK_1_FOR_SERVICE = "my.app.action.super.awesome.task1.service";
	private static final String ACTION_SUPER_AWESOME_TASK_2_FOR_SERVICE = "my.app.action.super.awesome.task2.service";
	
	private final BroadcastReceiver myActionReceiver = new BroadcastReceiver() {
		@Override
		public void onReceive(Context context, Intent intent) {
			switch(intent.getAction()) {
				case ACTION_SUPER_AWESOME_TASK_1_FOR_SERVICE:
					// do task 1 request for service
					break;
				case ACTION_SUPER_AWESOME_TASK_2_FOR_SERVICE:
					// do task 2 request for service
					break;
				default:
					// do nothing
					break;
			}
		}
	};

	private void setActionFilters() {
		IntentFilter filter = new IntentFilter();

		filter.addAction(ACTION_SUPER_AWESOME_TASK_1_FOR_SERVICE);
		filter.addAction(ACTION_SUPER_AWESOME_TASK_2_FOR_SERVICE);

		registerReceiver(myActionReceiver, filter);
	}

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);

		setActionFilters();
		
		Intent start_service_intent = new Intent(this, MyAppService.class);
		startService(start_service_intent);
	}

	/**
	 * function: invokeAction1
	 * This method gets invoke when the user wants to perform action 1. For this example, this method is invoke when a button for task 1 is pressed.
	 */
	public void invokeAction1(View view) {
		Intent intent = new Intent();
		intent.setAction(ACTION_SUPER_AWESOME_TASK1);
		String msg = "Hello World";
		// add any data if necessary
		// intent.putExtra("data", msg);
		//
		sendBroadcast(intent);
	}
}
public class MyAppService extends Service {
	private static final String ACTION_SUPER_AWESOME_TASK_1 = "my.app.action.super.awesome.task1";
	private static final String ACTION_SUPER_AWESOME_TASK_2 = "my.app.action.super.awesome.task2";
	private static final String ACTION_SUPER_AWESOME_TASK_1_FOR_SERVICE = "my.app.action.super.awesome.task1.service";
	private static final String ACTION_SUPER_AWESOME_TASK_2_FOR_SERVICE = "my.app.action.super.awesome.task2.service";
	
	private final BroadcastReceiver myBroadcastReceiver = new BroadcastReceiver() {
		@Override
		public void onReceive(Context context, Intent intent) {
			switch (intent.getAction()) {
				case ACTION_SUPER_AWESOME_TASK_1:
					// do task 1 request from Activity
					break;
				case ACITON_SUPER_AWESOME_TASK_2:
					// do task 2 request from Activity
					break;
				default:
					// do nothing
					break;
			}
		}
	}

	private void setListenFilters() {
		IntentFilter filter = new IntentFilter();

		filter.addAction(ACTION_SUPER_AWESOME_TASK_1);
		filter.addAction(ACTION_SUPER_AWESOME_TASK_2);

		registerReceiver(myBroadcastReceiver, filter);
	}

	@Override
	public void onCreate() {	
		// set up
		
		setListenFilters();
	}

	/**
	 * This method is called before the service starts to determine how the Android system will treat this service if its process gets killed.
	 *
	 * @return int:	flag indicating how the service will run (STICKY or NON_STICK)
	 */
	@Override
	public int onStartCommand(Intent intent, int flag, int start_id) {
		// run service as not sticky; once service process is terminated stay terminated
		return Service.START_NOT_STICKY;
	}

	@Override
	public IBinder onBind(Intent intent) {
		// do not provide binding; so return null
		return null;
	}
}

 


 

I hope you found this post helpful. If you found this post helpful, share it with others so they can benefit too.

 

Do you find yourself using Activities or Services more? How often do you find that you need to use both? What are some of the problems that you have working with Activities and Services?

 

Leave a comment or send me an email at steven@brightdevelopers.com. To stay in touch, follow me on Twitter.


About Steven To

Steven To is a software developer that specializes in mobile development with a background in computer engineering. Beyond his passion for software development, he also has an interest in Virtual Reality, Augmented Reality, Artificial Intelligence, Personal Development, and Personal Finance. If he is not writing software, then he is out learning something new.