1. Introduction
Service performs non UI tasks on the background indefinitely !!!!. It can perform network I/O , play music and etc.
Application can start a service, the service will continue running ever after the user has switched to another application
Service can take two forms :
Started
- service is started when an application component e.g. Activity perform startService. Once started it continue running indefinitely even if the component is destroyed
- It is possible to stop the service (true for Service false for IntentService)
Bounded
- A service is bounded when a component calls bindService
- a bound service offers IPC
- a bound service runs as long as it's bounded component runs
By default the service run on the hosting process main thread. You can create a thread and run the service on it's context
2. Basics
To create a service you subclass Service.
Important methods to override :
- onStartCommand - called when startService is called
- onBind - called when bindService is called
- onCreate - called when the service is created. Called once
- onDestroy - the system calls this when the service is no longer needed and is being destroyed. Use it for cleans up
Stoping service scenarios :
- The system will stop service only when it's resources are running low and it need them for the application which are in user focus.
- Bounded service have slim odds to be killed in case their bounded activity is in user focus.
- If a service is declared to run in the foreground then most likely is will not be killed
- A service doing long operation will get lower position in the background list and is most likely be killed. It will be restarted as soon as system resources are available !!!
Manifest
You need to declare the service inside AndroidMwnifest.xml
<application
....
<service android:name=".MyService" />
</application>
Set the service attribue android:exported to false in case you want that only your application will use it.
Create a started service
As pointed before it is done by calling startService.
The service can be stoped in two ways :
- self stoping - calling stopSelf
- stop by the app - stopService
startService pass Intent which is consumed by onStartCommand callback
You can extend two classes :
Service
- This is the base class for all services
- It is important to create inside the service a thread which handles the service work in case the work blocks the main thread
IntentService
- This is subclass of Service.
- It uses a worker thread to do the work
- All you need to do is implement onHandleIntent which is called per startService !!
- The service stop itself when the work is done.
- stopService does not work !!
Create a bounded Service
As pointed before it is done by calling bindService.
This post does not elaborate on this option.
Managing the life cycle of the service
Following is the life cycle of a service.
You can implement the callbacks. Unlike activity there is no need to call superclass
3. Source sample
TryService.zip
The sample show the use of
- Service + worker thread
- IntentService
MainActivity.java
The service is run using startService.
stopService works for Service not IntentService
package nathan.krasney.nynkmobile.tryservice; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.view.View; import android.widget.RadioButton; import android.widget.RadioGroup; import android.widget.Toast; public class MainActivity extends Activity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } public void myClickHandlerStart(View v) { RadioGroup radioGroup = (RadioGroup) findViewById(R.id.radioGroupServices); int selectedId = radioGroup.getCheckedRadioButtonId(); RadioButton radioButton = (RadioButton) findViewById(selectedId); if(radioButton.getText().equals("Service") ) { service = new Intent(this, MyService.class); } else if(radioButton.getText().equals("IntentService")) { service = new Intent(this, MyIntentService.class); } if(service != null) { this.startService(service); } } public void myClickHandlerStop(View v) { boolean bRes = this.stopService(service); if(bRes){ Toast.makeText(this, "stopService Success", Toast.LENGTH_SHORT).show(); } else{ Toast.makeText(this, "stopService Failure", Toast.LENGTH_SHORT).show(); } } Intent service; }
MyIntentService.java
InentService - onHandleIntent is called per startService
package nathan.krasney.nynkmobile.tryservice; import android.app.IntentService; import android.app.Notification; import android.app.NotificationManager; import android.content.Context; import android.content.Intent; import android.widget.Toast; public class MyIntentService extends IntentService { public MyIntentService() { super("MyIntentService");//name of class } @SuppressWarnings("deprecation") @Override protected void onHandleIntent(Intent intent) { // Normally we would do some work here, like download a file. Toast.makeText(this, "onHandleIntent", Toast.LENGTH_SHORT).show(); mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); Notification notification = CUtils.prepareNotification(mNotificationManager, getApplicationContext(),this,MyIntentService.class); synchronized (this) { try { wait(5000); mNotificationManager.notify(HELLO_ID, notification); } catch (Exception e) { } } } private static final int HELLO_ID = 1; NotificationManager mNotificationManager; }
MyService.java
A worker thread is created to handle the work which otherwise will be done on the main thread. This is not must e.g. in case you have a listener and it's work is perfomed in some async way then there is no need to create here a worker thread
package nathan.krasney.nynkmobile.tryservice; import android.app.Notification; import android.app.NotificationManager; import android.app.Service; import android.content.Context; import android.content.Intent; import android.os.IBinder; import android.widget.Toast; public class MyService extends Service { @Override public void onCreate() { // Start up the thread running the service. Note that we create a // separate thread because the service normally runs in the process's // main thread, which we don't want to block. m_bshouldContinue=true; new Thread(new Runnable() { public void run() { int i=0; mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); Notification notification = CUtils.prepareNotification(mNotificationManager, getApplicationContext(), MyService.this.getBaseContext(),MyService.class); while (m_bshouldContinue) { synchronized (this) { try { wait(5000); mNotificationManager.notify(HELLO_ID, notification); } catch (Exception e) { } } } } }).start(); } @Override public int onStartCommand(Intent intent, int flags, int startId) { Toast.makeText(this, "service starting", Toast.LENGTH_SHORT).show(); // If we get killed, after returning from here, restart return START_STICKY; } @Override public IBinder onBind(Intent intent) { // We don't provide binding, so return null return null; } @Override public void onDestroy() { m_bshouldContinue=false; Toast.makeText(this, "service done", Toast.LENGTH_SHORT).show(); } private static final int HELLO_ID = 1; NotificationManager mNotificationManager; boolean m_bshouldContinue; }
Run the application to create
click the start after few second you will see the notification
Click Stop service and you will see a toast about success
Restart the application ,click on the radio button of IntentService then click Start Service
Click on Stop Service , you will get failure , that because stopService can not stop IntentService. The service stops when the work is finished
The following app was published using this post.
Nathan
No comments:
Post a Comment