the whole content of Service will be covered in this article. We will analyze it around the following main knowledge points:
- Service brief overview
- Declaration of Service in manifest file
- Service startup service implementation method and its detailed explanation
- Three implementation methods of Service binding Service
- On the conversion between startup service and binding service
- Front desk service and notification sending
- The difference between Service and Thread
- Key points of managing the service life cycle
- Implicit startup problems and solutions above Android 5.0
- Implementation idea of ensuring that services are not killed
1. Brief overview of service
Service is an application component that can perform long-running operations in the background without user interface. The Service can be started by other application components (such as Activity). Once the Service is started, it will always run in the background. Even if the component (Activity) that starts the Service has been destroyed, it will not be affected. In addition, components can be bound to services to interact with them, or even perform interprocess communication (IPC). For example, services can handle network transactions, play music, execute file I/O or interact with content providers, all of which can be carried out in the background. Services are basically divided into two forms:
- Start state
when an application component (such as an Activity) starts a service by calling startService(), the service is in the "start" state. Once started, the service can run indefinitely in the background. Even if the component that started the service has been destroyed, it will not be affected. The service can be stopped unless it is called manually. The started service usually performs a single operation and will not return the result to the caller.
- Binding status
when the application component binds to the service by calling bindService(), the service is in the "binding" state. Binding service provides a client server interface, which allows components to interact with services, send requests, obtain results, and even use interprocess communication (IPC) to perform these operations across processes. The binding service runs only when it is bound to another application component. Multiple components can be bound to the service at the same time, but the service will be destroyed after all the components are unbound.
2. Statement of service in the list file
The specific startup status is divided into two types: androidservice (and Service), which are inherited by the base state XML, so before analyzing these two states, let's take a look at the Service in AndroidManifest.xml The declaration syntax in XML has the following format:
<service android:enabled=[ "true" | "false"] android:exported=[ "true" | "false"] android:icon= "drawable resource" android:isolatedProcess=[ "true" | "false"] android:label= "string resource" android:name= "string" android:permission= "string" android:process= "string" > . . . </service>
android:exported: indicates whether it can be implicitly called by other applications. Its default value is determined by whether there is an intent filter in the service. If there is an intent filter, the default value is true, otherwise it is false. If it is false, even if there is an intent filter match, it cannot be opened, that is, it cannot be implicitly called by other applications.
android:name: corresponding Service class name
android:permission: permission statement
android:process: whether it needs to run in a separate process. When it is set to android:process = ": remote", it represents that the Service runs in a separate process. Note that ":" is very important. It means to append the current package name before the current process name, so "remote" and ": remote" do not have the same meaning. The process name of the former is: remote, and the process name of the latter is: app packagename: remote.
android:isolatedProcess: setting true means that the service will run under a special process, which is separated from other processes in the system and does not have its own permissions. The only way to communicate with it is through the API of the service (bind and start).
android:enabled: whether it can be instantiated by the system. The default is true. Because the parent tag also has the enable attribute, the service can be activated only when both are true by default, otherwise it will not be activated.
ok ~, let's first understand these statements about the Service in the manifest file, and then analyze the Service startup Service and binding Service in detail
3.Service startup service
to create a Service first, you must create a subclass of Service (or use one of its existing subclasses, such as IntentService). In the implementation, we need to rewrite some callback methods to process the Service life cycle For some key processes, let's analyze which callback methods need to be rewritten through a simple case?
package com.zejian.ipctest.service; import android.app.Service; import android.content.Intent; import android.os.IBinder; import android.support.annotation.Nullable; /** * Created by zejian * Time 2016/9/29. * Description:service simple demo */ public class SimpleService extends Service { /** * Called only when the service is bound * Methods that must be implemented * @param intent * @return */ @Nullable @Override public IBinder onBind (Intent intent) { return null; } /** * When the service is created for the first time, the system will call this method to execute the one-time setup program (before calling onStartCommand() or onBind()). * If the service is already running, this method will not be called. This method is called only once */ @Override public void onCreate () { System.out.println( "onCreate invoke"); super.onCreate(); } /** * It will be called back every time the Service is started through the startService() method. * @param intent * @param flags * @param startId * @return */ @Override public int onStartCommand (Intent intent, int flags, int startId) { System.out.println( "onStartCommand invoke"); return super.onStartCommand(intent, flags, startId); } /** * Callback during service destruction */ @Override public void onDestroy () { System.out.println( "onDestroy invoke"); super.onDestroy(); } }
from the above code, we can see that SimpleService inherits the Service class and rewrites the onBind method. This method must be rewritten. However, since it is a Service in startup state at this time, this method does not need to be implemented and can return null. It is only necessary to implement this method and return an IBinder implementation class (which will be described in detail later), and then rewrites onCreate, onStartCommand onDestroy has three main life cycle methods, which are described as follows:
- onBind()
the system will call this method when another component wants to bind to a service (such as executing RPC) by calling bindService(). In the implementation of this method, an implementation class of IBinder interface must be returned for the client to communicate with the service. This method must be overridden whether it is in the startup state or binding state, but it returns null directly in the startup state.
- onCreate()
when the service is created for the first time, the system will call this method to execute the one-time setting program (before calling onStartCommand() or onBind()). If the service is already running, this method will not be called, it will only be called once
- onStartCommand()
the system will call this method when another component (such as Activity) requests to start the service by calling startService(). Once this method is executed, the service starts and can run indefinitely in the background. If you implement this method yourself, you need to stop the service by calling stopSelf() or stopService() after the service work is completed. (in the binding state, this method does not need to be implemented.)
- onDestroy()
the system will call this method when the service is no longer used and will be destroyed. The service should implement this method to clean up all resources, such as threads, registered listeners, receivers, etc. This is the last call received by the service.
let's test the calling sequence of Service startup status methods through Demo. The MainActivity code is as follows:
package com.zejian.ipctest; import android.content.Intent; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.view.View; import android.widget.Button; import com.zejian.ipctest.service.SimpleService; public class MainActivity extends AppCompatActivity implements View.OnClickListener { private Button startBtn; private Button stopBtn; @Override protected void onCreate (Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); startBtn= (Button) findViewById(R.id.startService); stopBtn= (Button) findViewById(R.id.stopService); startBtn.setOnClickListener( this); assert stopBtn != null; stopBtn.setOnClickListener( this); } @Override public void onClick (View v) { Intent it= new Intent( this, SimpleService.class); switch (v.getId()){ case R.id.startService: startService(it); break; case R.id.stopService: stopService(it); break; } } }
Remember to declare service in the manifest configuration file (the declaration method is similar to that of Activity):
<manifest ... > ... <application ... > <service android:name=".service.SimpleService" /> ... </application> </manifest>
from the code, you can start the service by using the startService(Intent intent) method. You only need to pass an Intent object, and specify the service to be started in the Intent object. The service started with the startService() method must be stopped with the stopService() method outside the service, and the stopSelf() method can be called inside the service to stop the current service. If you use the startService() or stopSelf() method to request to stop the service, the system will destroy the service as soon as possible. Once the service is started, the component will be destroyed without any attention. Once the service is started, the component will not work until it is in the state of being associated with the service. Once the service is started, it will be destroyed without any attention, Finally, call the stopService method. Base note: The Log screenshot is as follows:
it can be seen from the Log that when the startService method is called for the first time, onCreate method and onStartCommand method will be called successively, while when the startService method is called for many times, only onStartCommand method will be called. Finally, when we call stopService method to stop the Service, onDestory method will be called back, which is the execution cycle of the Service in the start state. Then we go back and further analyze onStartCommand (intent, int flags, int startid). This method has three incoming parameters, and their meanings are as follows:
onStartCommand(Intent intent, int flags, int startId)
Intent: when starting, the intent passed by the starting component, such as Activity, can use intent to encapsulate the required parameters and pass them to the Service
flags: indicates whether there is additional data when starting the request. The optional values are 0 and START_FLAG_REDELIVERY,START_FLAG_RETRY, 0 means no, and their specific meanings are as follows:
START_FLAG_REDELIVERY
This value represents the return value of onStartCommand method
START_REDELIVER_INTENT, and it will call the stopSelf method to stop the Service before the last Service is killed. Including START_REDELIVER_INTENT means that when the Service is killed by the system due to insufficient memory, it will rebuild the Service and call onStartCommand() through the last intent passed to the Service. At this time, the intent has a value.START_FLAG_RETRY
This flag means that when there is no return value after onStartCommand is called, it will try to call onStartCommand() again.
startId: indicates the unique ID of the current service. Used in combination with stopSelfResult (int startId), stopSelfResult can more safely stop the service according to the ID.
in fact, the return value int type of onStartCommand is the most noteworthy. It has three optional values, START_STICKY, START_NOT_STICKY,START_REDELIVER_INTENT, their specific meanings are as follows:
START_STICKY
when the Service is kill ed by the system due to insufficient memory and the memory is free again after a period of time, the system will try to re create the Service. Once the Service is created successfully, the onStartCommand method will be called back, but the Intent in it will be null, unless there is a suspended Intent, such as pending. This state is more suitable for media players or similar services that do not execute commands but run indefinitely and wait for jobs.START_NOT_STICKY
after the Service is kill ed by the system due to insufficient memory, the system will not try to re create the Service even if the system memory is free again. Unless the program calls startService again to start this Service, this is the safest option to avoid running the Service when it is unnecessary and when the application can easily restart all unfinished jobs.START_REDELIVER_INTENT
when the Service is kill ed by the system due to insufficient memory, it will rebuild the Service and call onStartCommand() through the last Intent passed to the Service. Any pending Intent will be passed in turn. And START_STICKY is different in that the passed Intent will be non empty, which is the Intent in the last call to startService. This value applies to services that actively execute jobs that should be restored immediately, such as downloading files.
since the onStartCommand method will be called every time the Service is started (calling startService), we can use Intent to pass the required parameters to the Service through this method, then process the events in the onStartCommand method, and finally select different Flag return values according to the needs to achieve more friendly control of the program. OK ~, the above is the analysis of the Service in the startup state. Then let's see how the Service in the binding state is handled?
4.Service binding service
binding Service is another variant of Service. When the Service is in the binding state, it represents the server in the client server interface. When other components (such as Activity) are bound to the Service (sometimes we may need to call the method in the Service from the Activity component. At this time, after the Activity is attached to the Service in the way of binding, we can easily connect the method to the specified method in the Service), components (such as Activity) can send requests to the Service (that is, the server) or call the method of the Service (the server), At this time, the bound Service (server) will receive information and respond, and can even perform inter process communication through the bound Service (i.e. IPC, which will be analyzed separately later). Different from starting the Service, the life cycle of the binding Service is usually only active when serving other application components (such as Activity) and will not run in the background indefinitely, that is, after the host (such as Activity) unbinds, the binding Service will be destroyed. So how to implement binding services? In fact, we must provide an implementation class of IBinder interface, which is used to provide the programming interface used by the client to interact with the Service. The interface can define the interface through three methods:
Extend Binder class
if the Service is dedicated to its own application, and the Service (server) runs in the same process as the client (common situation), the interface should be created by extending the Binder class and returning an instance of it from onBind(). After receiving Binder, the client can use it to directly access the public methods available in Binder implementation and Service. If our Service is only the background working thread of our own application, this method is preferred. The only reason why the interface is not created in this way is that the Service is called by other applications or different processes.Using Messenger
messenger can be translated into messenger. Through it, Message objects can be delivered in different processes (the Messager in the Handler, so the Handler is the basis of messenger). The data we need to deliver can be stored in the Message and then delivered between processes. If you need to make the interface work across different processes, you can use messenger to create an interface for the service, and the client can use the Message object to send commands to the service. At the same time, the client can also define its own messenger so that the service can return messages. This is the simplest way to implement interprocess communication (IPC), because messenger will create a queue containing all requests in a single thread, that is, Messenger processes messages sent by the client in a serial way, so we don't have to thread safety design the service.- Use AIDL
because messenger processes the messages sent by the client in a serial way, if a large number of messages are sent to the Service at the same time, the Service can still process them one by one, which is the disadvantage of messenger cross process communication. Therefore, if there are a large number of concurrent requests, Messenger will be unable to meet its needs, and aidl (android interface definition language) will come in handy, But in fact, the underlying implementation of messenger's cross process approach is aidl, but android system helps us package it into transparent messenger. Therefore, if we want the Service to handle multiple requests at the same time, we should use aidl. In this case, the Service must have multi-threaded processing capability and adopt thread safe design. To use aidl, you must create a to define the programming interface aidl file. The Android SDK tool uses this file to generate an abstract class that implements the interface and handles IPC, which can then be extended within the Service.
we can freely choose the above three implementation methods according to our needs, but it should be noted that most applications "will not" use AIDL to create binding services, because it may require multi-threaded processing capability and may increase the complexity of implementation. Therefore, AIDL is not suitable for most applications. This article does not intend to explain how to use AIDL (another article will be opened later to analyze AIDL). Next, we will analyze the use of extended Binder class and Messenger respectively.
4.1 extend Binder class
as described above, if our service is only used by local applications and does not need to work across processes, we can implement our own Binder class to allow clients to directly access the public methods in the service through this class. Its use and development steps are as follows
- 1. Create the BindService server, inherit from the Service, create an instance object that implements the IBinder interface in the class, and provide public methods for the client to call
- 2. Return this Binder instance from the onBind() callback method.
- 3. In the client, receive the Binder from the onServiceConnected() callback method and call the binding service using the provided method.
note: this method is only effective when the client and service are in the same application and process. For example, this method is very effective for music applications that need to bind the Activity to their own services that play music in the background. Another reason why the service and client must be in the same application is to facilitate the client to convert the returned object and call its API correctly. The service and client must also be in the same process, because this method does not perform any cross process marshalling.
the following is an example of extending Binder class. Let's take a look at the implementation of bindservice on the Service side java
package com.zejian.ipctest.service; import android.app.Service; import android.content.Intent; import android.os.Binder; import android.os.IBinder; import android.support.annotation.Nullable; import android.util.Log; /** * Created by zejian * Time 2016/10/2. * Description:Binding service simple instance -- server */ public class LocalService extends Service{ private final static String TAG = "wzj"; private int count; private boolean quit; private Thread thread; private LocalBinder binder = new LocalBinder(); /** * Create a Binder object and return it to the client, that is, the Activity, which provides an interface for data exchange */ public class LocalBinder extends Binder { // Declare a method, getService. (provided for client call) LocalService getService () { // Return the current object LocalService, so that we can call the public method of Service on the client side return LocalService. this; } } /** * Return the Binder class to the client */ @Nullable @Override public IBinder onBind (Intent intent) { return binder; } @Override public void onCreate () { super.onCreate(); Log.i(TAG, "Service is invoke Created"); thread = new Thread( new Runnable() { @Override public void run () { // count is incremented by 1 every second until quit is true. while (!quit) { try { Thread.sleep( 1000); } catch (InterruptedException e) { e.printStackTrace(); } count++; } } }); thread.start(); } /** * Public method * @return */ public int getCount (){ return count; } /** * Called when unbound * @return */ @Override public boolean onUnbind (Intent intent) { Log.i(TAG, "Service is invoke onUnbind"); return super.onUnbind(intent); } @Override public void onDestroy () { Log.i(TAG, "Service is invoke Destroyed"); this.quit = true; super.onDestroy(); } }
BindService class inherits from Service. In this class, a LocalBinder is created, which inherits from binder class. LocalBinder declares a getService method. The client can access this method to obtain the instance of LocalService object. As long as the client obtains the instance of LocalService object, it can call the public method of LocalService server, such as getCount method. It is worth noting that we return the binder object in onBind method, This object is the specific instance of LocalBinder, and the binder object will eventually be returned to the client. The client can interact with the server through the returned binder object. Next, let's look at the implementation of BindActivity on the client:
package com.zejian.ipctest.service; import android.app.Activity; import android.app.Service; import android.content.ComponentName; import android.content.Intent; import android.content.ServiceConnection; import android.os.Bundle; import android.os.IBinder; import android.util.Log; import android.view.View; import android.widget.Button; import com.zejian.ipctest.R; /** * Created by zejian * Time 2016/10/2. * Description:Binding service instance -- client */ public class BindActivity extends Activity { protected static final String TAG = "wzj"; Button btnBind; Button btnUnBind; Button btnGetDatas; /** * ServiceConnection Represents the connection to the service. It has only two methods, * onServiceConnected And onservice disconnected, * The former is called when the operator successfully connects to a service, while the latter is called when the connection is interrupted due to service crash or killing */ private ServiceConnection conn; private LocalService mService; @Override protected void onCreate (Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_bind); btnBind = (Button) findViewById(R.id.BindService); btnUnBind = (Button) findViewById(R.id.unBindService); btnGetDatas = (Button) findViewById(R.id.getServiceDatas); //Create binding object final Intent intent = new Intent( this, LocalService.class); // Open binding btnBind.setOnClickListener( new View.OnClickListener() { @Override public void onClick (View v) { Log.d(TAG, "Binding call: bindService"); //Call binding method bindService(intent, conn, Service.BIND_AUTO_CREATE); } }); // Unbind btnUnBind.setOnClickListener( new View.OnClickListener() { @Override public void onClick (View v) { Log.d(TAG, "Unbind call: unbindService"); // Unbind if(mService!= null) { mService = null; unbindService(conn); } } }); // get data btnGetDatas.setOnClickListener( new View.OnClickListener() { @Override public void onClick (View v) { if (mService != null) { // Get the data exposed by the Service by binding the Binder object passed by the Service Log.d(TAG, "Obtain data from the server:" + mService.getCount()); } else { Log.d(TAG, "It's not bound yet. Bind first,Unable to get data from the server"); } } }); conn = new ServiceConnection() { /** * The interface method interacting with the server is called back when binding the Service. This method obtains the IBinder object passed by the binding Service, * Through this IBinder object, the interaction between host and Service can be realized. */ @Override public void onServiceConnected (ComponentName name, IBinder service) { Log.d(TAG, "Bind successfully called: onServiceConnected"); // Get Binder LocalService. LocalBinder binder = (LocalService.LocalBinder) service; mService = binder.getService(); } /** * Called back when unbinding. But it is not called under normal circumstances. Its calling time is when the Service service is accidentally destroyed, * For example, this method is called automatically when the memory resources are insufficient. */ @Override public void onServiceDisconnected (ComponentName name) { mService= null; } }; } }
in the client, we created a ServiceConnection object, which represents the connection with the service. It has only two methods, onServiceConnected and onServiceDisconnected. Its meaning is as follows:
onServiceConnected(ComponentName name, IBinder service)
The system will call this method to pass the IBinder returned by the onBind() method of the service. Service is the IBinder implementation class object returned by the server. Through this object, we can call to obtain the LocalService instance object, and then call the public method of the server. ComponentName is a class that encapsulates the information of components (Activity, Service, BroadcastReceiver, or ContentProvider), such as package name, component description and other information. This parameter is rarely used.onServiceDisconnected(ComponentName name)
The Android system will call this method when the connection with the service is unexpectedly interrupted (for example, when the service crashes or is terminated). Note: when the client unbinds, the system "will never" call this method.
conn = new ServiceConnection() { @Override public void onServiceConnected (ComponentName name, IBinder service) { Log.d(TAG, "Bind successfully called: onServiceConnected"); // Get Binder LocalService. LocalBinder binder = (LocalService.LocalBinder) service; mService = binder.getService(); } @Override public void onServiceDisconnected (ComponentName name) { mService= null; } };
before onServiceConnected() is called back, we also need to bind the current Activity to the service LocalService. The binding service is through the bindService() method, and the unbindService() method is used to unbind the service. The two methods are resolved as follows:
bindService(Intent service, ServiceConnection conn, int flags)
This method performs the binding Service operation, in which Intent is the intention of the Service we want to bind (that is, LocalService), and ServiceConnection represents the connection with the Service. It has only two methods. As analyzed earlier, flags specifies whether to automatically create the Service during binding. 0 means not to create and bind automatically_ AUTO_ Create stands for automatic creation.unbindService(ServiceConnection conn)
This method performs the operation of unbinding. ServiceConnection represents the connection with the service. It has only two methods, which have been analyzed earlier.
After the Activity is bound to the LocalService through bindService(), ServiceConnection#onServiceConnected() will be called back and the LocalService instance object mService can be obtained. Then we can call the public method of the LocalService server. Finally, we need to declare the Service in the manifest file. The client layout file is implemented as follows:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation= "vertical" android:layout_width= "match_parent" android:layout_height= "match_parent"> <Button android:id= "@+id/BindService" android:layout_width= "wrap_content" android:layout_height= "wrap_content" android:text= "Binding server" /> <Button android:id= "@+id/unBindService" android:layout_width= "wrap_content" android:layout_height= "wrap_content" android:text= "Unbind" /> <Button android:id= "@+id/getServiceDatas" android:layout_width= "wrap_content" android:layout_height= "wrap_content" android:text= "Obtain service party data" /> </LinearLayout>
Base note: we run the program, click the binding service and click the binding service several times, then call the getCount() in LocalService for data, and then call the unbound method to remove the service. The results are as follows:
it can be seen from the Log that when we click bind Service for the first time, the onCreate() and onBind methods of the LocalService server will be called successively. At this time, the ServiceConnection#onServiceConnected() of the client is called and returns the LocalBinder object, and then the LocalBinder#getService method is called to return the LocalService instance object. At this time, the client holds the instance object of the LocalService, You can also call the declared public methods in the LocalService class at will. What is more noteworthy is that we call the bindService method many times to bind the LocalService server, while the onBind method of the LocalService is called only once, that is, the onBind method will be called back when the bindService is called for the first time. Then we click to get the data of the server. From the Log, we can see that we click three times and get three different data of the server through getCount(). Finally, click unbind. At this time, the onUnBind and onDestroy methods of LocalService are called back in turn, and only one unbinding is required for multiple bindings. This scenario also shows that the Service life cycle method calls in the binding state are onCreate(), onBind, onUnBind and onDestroy in turn. ok ~, the above is the binding callback method between the client and the server in the same process of the same application.
4.2 using Messenger
after understanding how to use the communication of the same process in IBinder application, we will then understand the communication between service and remote process (i.e. between different processes). The simplest way of communication between different processes is to use Messenger service to provide communication interface. In this way, we can perform interprocess communication (IPC) without using AIDL. Here are the main steps for using Messenger:
1. The service implements a Handler, which receives the callback of each call from the client
2.Handler is used to create Messenger object (reference to handler)
3.Messenger creates an IBinder service and returns it to the client through onBind()
4. The client uses IBinder to instantiate Messenger (the Handler referring to the service), and then uses messenger to send the Message object to the service
- 5. The service receives each Message in its Handler (in the handleMessage() method)
The following is a simple service example using Messenger interface. The server process is implemented as follows:
package com.zejian.ipctest.messenger; import android.app.Service; import android.content.Intent; import android.os.Handler; import android.os.IBinder; import android.os.Message; import android.os.Messenger; import android.util.Log; /** * Created by zejian * Time 2016/10/3. * Description:Messenger Server simple instance, server process */ public class MessengerService extends Service { /** Command to the service to display a message */ static final int MSG_SAY_HELLO = 1; private static final String TAG = "wzj" ; /** * Used to receive data passed from the client */ class IncomingHandler extends Handler { @Override public void handleMessage (Message msg) { switch (msg.what) { case MSG_SAY_HELLO: Log.i(TAG, "thanks,Service had receiver message from client!"); break; default: super.handleMessage(msg); } } } /** * Create Messenger and pass in the Handler instance object */ final Messenger mMessenger = new Messenger( new IncomingHandler()); /** * When binding a Service, this method is called and an implementation will be returned through mmsmessenger * IBinder Instance object of interface */ @Override public IBinder onBind (Intent intent) { Log.i(TAG, "Service is invoke onBind"); return mMessenger.getBinder(); } }
first, we also need to create a Service class MessengerService inherited from Service, and create an IncomingHandler object inherited from Handler to receive messages sent by the client process and process messages through its handleMessage(Message msg). Then create a Messenger object through the IncomingHandler object, which is a special object interacting with the client, and then return the underlying Binder of the Messenger object in the onBind of the Service. Let's take a look at the implementation of the client process:
package com.zejian.ipctest.messenger; import android.app.Activity; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; import android.os.Bundle; import android.os.IBinder; import android.os.Message; import android.os.Messenger; import android.os.RemoteException; import android.util.Log; import android.view.View; import android.widget.Button; import com.zejian.ipctest.R; /** * Created by zejian * Time 2016/10/3. * Description: Clients interacting with the server */ public class ActivityMessenger extends Activity { /** * Messenger interacting with server */ Messenger mService = null; /** Flag indicating whether we have called bind on the service. */ boolean mBound; /** * Implement the object linked with the server */ private ServiceConnection mConnection = new ServiceConnection() { public void onServiceConnected (ComponentName className, IBinder service) { /** * Create the corresponding Messenger through the IBinder object passed by the server * Interact with the server through the Messenger object */ mService = new Messenger(service); mBound = true; } public void onServiceDisconnected (ComponentName className) { // This is called when the connection with the service has been // unexpectedly disconnected -- that is, its process crashed. mService = null; mBound = false; } }; public void sayHello (View v) { if (!mBound) return; // Create a Message entity that interacts with the service Message Message msg = Message.obtain( null, MessengerService.MSG_SAY_HELLO, 0, 0); try { //send message mService.send(msg); } catch (RemoteException e) { e.printStackTrace(); } } @Override protected void onCreate (Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_messenager); Button bindService= (Button) findViewById(R.id.bindService); Button unbindService= (Button) findViewById(R.id.unbindService); Button sendMsg= (Button) findViewById(R.id.sendMsgToService); bindService.setOnClickListener( new View.OnClickListener() { @Override public void onClick (View v) { Log.d( "zj", "onClick-->bindService"); //The current Activity is bound to the server bindService( new Intent(ActivityMessenger. this, MessengerService.class), mConnection, Context.BIND_AUTO_CREATE); } }); //Send message to server sendMsg.setOnClickListener( new View.OnClickListener() { @Override public void onClick (View v) { sayHello(v); } }); unbindService.setOnClickListener( new View.OnClickListener() { @Override public void onClick (View v) { // Unbind from the service if (mBound) { Log.d( "zj", "onClick-->unbindService"); unbindService(mConnection); mBound = false; } } }); } }
in the client process, we need to create a ServiceConnection object, which represents the link with the server. When calling the bindService method to bind the current Activity to the MessengerService, the onServiceConnected method is called to construct the Messenger object interacting with the server by using the underlying Binder object passed by the server, and then create the Message entity Message interacting with the Service, Encapsulate the information to occur in the Message and send it to the server through the Messenger instance object. ServiceConnection, bindService method and unbindService method have been analyzed before and will not be repeated here. Finally, we need to declare Service and Activity in the manifest file. To test the interaction of different processes, we need to put the Service in a separate process. Therefore, the Service declaration is as follows:
<service android:name=".messenger.MessengerService" android:process= ":remote" />
- 1
- 2
- 3
android:process=":remote" means that the Service is created in a separate process. Finally, we run the program, and the results are as follows:
then click bind service several times, then send information to the server, and finally unbind. The Log is printed as follows:
from the above example, it can be seen that the Service server does receive the information sent by the client, and the data must be encapsulated in Message for data transmission in Messenger, because both Message and messenger implement the Parcelable interface, which can easily transfer data across processes (for the Parcelable interface, see another blog article: Analysis of parallelable and Serializable of serialization and deserialization )The information carriers that Message can deliver are what,arg1,arg2,Bundle and replyTo. As for the object field, it is very practical for data transmission in the same process, but it is quite embarrassing for communication between processes. In android 2 2 ago, object did not support cross process transmission, but even android 2 2 after that, we can only pass the objects that implement the Parcelable interface provided by the android system, that is, the objects that implement the Parcelable interface through customization cannot be passed through the object field, so the practicability of the object field becomes quite low in cross process. Fortunately, however, we also have a Bundle object, which can support a large number of data types. Next, from the Log, we can see that the calling sequence of their life cycle methods is basically the same, that is, onCreate(), onBind, onUnBind and onDestroy, whether using the implementation of extended Binder class or Messenger, and onBind() is called only for the first time in multiple bindings. OK ~, the above example demonstrates how to interpret the messages sent by the client at the server, but sometimes we may need the server to respond to the client. At this time, we need to provide two-way messaging. Here is a simple example of two-way messaging between the server and the client.
let's take a look at the modification of the server. On the server, we just need to modify the IncomingHandler and reply a message to the client after receiving the message.
/** * Used to receive data passed from the client */ class IncomingHandler extends Handler { @Override public void handleMessage( Message msg) { switch (msg.what) { case MSG_SAY_HELLO: Log.i( TAG, "thanks,Service had receiver message from client!"); //Reply to the client information, and the object is passed by the client Messenger client=msg.replyTo; //Get message entity of reply information Message replyMsg= Message.obtain( null, MessengerService. MSG_SAY_HELLO); Bundle bundle= new Bundle(); bundle.putString( "reply", "ok~,I had receiver message from you! "); replyMsg.setData(bundle); //Send message to client try { client.send(replyMsg); } catch ( RemoteException e) { e.printStackTrace(); } break; default: super.handleMessage(msg); } } }
then modify the client. In order to receive the reply from the server, the client also needs a Messenger and Handler to receive messages. Its implementation is as follows:
/** * Used to receive the information returned by the server */ private Messenger mRecevierReplyMsg= new Messenger( new ReceiverReplyMsgHandler()); private static class ReceiverReplyMsgHandler extends Handler{ private static final String TAG = "zj"; @Override public void handleMessage (Message msg) { switch (msg.what) { //Receive server reply case MessengerService.MSG_SAY_HELLO: Log.i(TAG, "receiver message from service:"+msg.getData().getString( "reply")); break; default: super.handleMessage(msg); } } }
in addition to adding the above code, it is also necessary to pass the Messenger receiving the reply from the server to the server through the replyTo parameter of the Message when sending the Message, so as to serve as a bridge for students. The code is as follows:
public void sayHello(View v) { if (!mBound) return; // Create a Message entity that interacts with the service Message Message msg = Message.obtain( null, MessengerService.MSG_SAY_HELLO, 0, 0); //Pass the Messenger receiving the reply from the server to the server through the replyTo parameter of Message msg.replyTo=mRecevierReplyMsg; try { //send message mService.send(msg); } catch (RemoteException e) { e.printStackTrace(); } }
ok ~, the simple example of two-way message transmission between the server and the client has been modified. Let's run the code and see the Log printing, as follows:
it can be seen from the Log that the server and client have indeed received information respectively. Now we have analyzed the way of cross process communication through messenger. Finally, in order to help you understand, here is a schematic diagram of inter process communication through messenger:
4.3 notes on binding services
1. Multiple clients can connect to a service at the same time. However, only when the first client binds will the system call the onBind() method of the service to retrieve the IBinder. Bind bind() to the same client again without calling the same client. When the last client unbinds the service, the system destroys the service (unless startService() also starts the service).
2. In general, we should set binding and unbinding operations at the time of bringing up and teardown of the client life cycle (such as the life cycle of Activity) in order to control the Service in the binding state. Generally, there are the following two cases:
If you only need to interact with the service when the Activity is visible, you should bind it during onStart() and unbind it during onStop().
If you want the Activity to still receive responses when it stops running in the background, you can bind it during onCreate() and unbind it during onDestroy(). It should be noted that this means that the Activity needs to use the service throughout its running process (even during background running). Therefore, if the service is located in other processes, the system is likely to terminate the process when the weight of the process is increased.
3. In general (note), do not bind or unbind during onResume() and onPause() of an Activity, because these callbacks will occur every life cycle transition, so it is unreasonable to bind and unbind repeatedly. In addition, if multiple activities in the application are bound to the same service and conversion occurs between two activities, if the current Activity is unbound (suspended) before the next binding (recovery period), the system may destroy the service and rebuild the service. Therefore, the binding of the service should not occur in onResume() and onPause() of the Activity.
4. We should always catch the DeadObjectException. The DeadObjectException exception is raised when the connection is interrupted, indicating that the calling object has died, that is, the Service object has been destroyed. This is the only exception raised by the remote method. The DeadObjectException inherits from RemoteException, so we can also catch the RemoteException exception.
5. The application component (client) can be bound to the service by calling bindService(). The Android system then calls the onBind() method of the service, which returns the IBinder used for interacting with the service, which is executed asynchronously. Base note:
5. About the conversion between startup service and binding service
through the previous analysis of the two Service states, I believe you have a relatively clear understanding of the two Service states. Now let's analyze what happens when the startup state and binding state exist at the same time?
although there are two states of a Service: startup and binding, in fact, a Service can be in both States, that is, it can be either a startup Service (running indefinitely) or a binding Service. It should be noted that the Android system will only create an instance object for one Service, so whether it is to start the Service or bind the Service, the operation is the same Service instance, and the following two situations will occur due to the execution sequence of bind Service or start Service:
Bind the service before starting the service
if the current Service instance runs in the bound state first and then in the started state, the bound Service will turn to the started Service. At this time, if the previously bound host (Activity) is destroyed, it will not affect the operation of the Service. The Service will continue to run continuously. Specify that the Service will be destroyed only when the call is received to stop the Service or there is insufficient memory.
Start the service before binding the service
if the current Service instance runs in the startup state first and then in the binding state, the current startup Service will not be converted to the binding Service, but will still be bound with the host. Only after the host is unbound, the Service will still run in the background according to the life cycle of the startup Service. The Service will not be destroyed until the Context calls stopService() or the Service itself calls stopSelf() method or there is insufficient memory.
the above two cases show that the priority of starting the Service is indeed higher than that of binding the Service. However, no matter whether the Service is in the startup or binding state, or in the startup and binding state, we can use the Service by calling Intent like using Activity (even if the Service comes from another application). Of course, we can also declare the Service as a private Service through the manifest file to prevent other applications from accessing it. Finally, there is something special to note here. Since the Service runs in the main thread of its managed process (UI thread), it neither creates its own thread nor runs in a separate process (unless otherwise specified). This means that if the Service will perform any time-consuming events or blocking operations (such as MP3 playback or networking), a new thread should be created within the Service to complete this work. In short, the time-consuming operations should be executed by another thread. Only by using a separate thread can the risk of "application non response" (ANR) errors be reduced, so that the main thread of the application can focus on the interaction between the user and the Activity, so as to achieve a better user experience.
6. Front desk service and notification sending
the foreground service is considered to be a service that users are actively aware of, so the system will not consider terminating it when there is insufficient memory. The foreground service must provide notifications to the status bar, which is located under the "in progress" heading, which means that notifications cannot be cleared unless the service is stopped or deleted from the foreground. For example, a music player that plays music from a service is set to run in the foreground because the user is clearly aware of its operation. The notification in the status bar may indicate the song being played and allow the user to start the Activity to interact with the music player. If we need to set the service to run in the foreground, how can we achieve it? Android official provides us with two methods, startforegroup() and stopforegroup(), which are parsed as follows:
startForeground(int id, Notification notification)
The function of this method is to set the current service as the foreground service, where the ID parameter represents the integer number that uniquely identifies the notification. It should be noted that the integer id provided to startforegroup() must not be 0, and notification is a notification in the status bar.stopForeground(boolean removeNotification)
This method is used to delete a service from the foreground. This method passes in a Boolean value to indicate whether the status bar notification is also deleted. true means delete. Note that this method does not stop the service. However, if the service is stopped while it is running in the foreground, the notification is also deleted.
Let's use the above two methods in combination with a simple case. The foreroundservice code is as follows:
package com.zejian.ipctest.foregroundService; import android.app.Notification; import android.app.Service; import android.content.Intent; import android.graphics.BitmapFactory; import android.os.IBinder; import android.support.annotation.Nullable; import android.support.v4.app.NotificationCompat; import com.zejian.ipctest.R; /** * Created by zejian * Time 2016/10/4. * Description:Start foreground service Demo */ public class ForegroundService extends Service { /** * id Cannot be set to 0, otherwise it cannot be set to foreground service */ private static final int NOTIFICATION_DOWNLOAD_PROGRESS_ID = 0x0001; private boolean isRemove= false; //Need to remove /** * Notification */ public void createNotification (){ //Use compatible version NotificationCompat.Builder builder= new NotificationCompat.Builder( this); //Set notification icon for status bar builder.setSmallIcon(R.mipmap.ic_launcher); //Set the icon of the notification bar bar bar builder.setLargeIcon(BitmapFactory.decodeResource(getResources(),R.drawable.screenflash_logo)); //Users are not allowed to click the delete button to delete builder.setAutoCancel( false); //Prohibit sliding deletion builder.setOngoing( true); //Time display in the upper right corner builder.setShowWhen( true); //Set the title and content of the notification bar builder.setContentTitle( "I am Foreground Service!!!"); //Create notification Notification notification = builder.build(); //Set as foreground service startForeground(NOTIFICATION_DOWNLOAD_PROGRESS_ID,notification); } @Override public int onStartCommand (Intent intent, int flags, int startId) { int i=intent.getExtras().getInt( "cmd"); if(i== 0){ if(!isRemove) { createNotification(); } isRemove= true; } else { //Remove foreground service if (isRemove) { stopForeground( true); } isRemove= false; } return super.onStartCommand(intent, flags, startId); } @Override public void onDestroy () { //Remove foreground service if (isRemove) { stopForeground( true); } isRemove= false; super.onDestroy(); } @Nullable @Override public IBinder onBind (Intent intent) { return null; } }
in the ForegroundService class, a notification notification is created, and the parameters passed when starting the Service determine whether to start or close the foreground Service. Finally, when the onDestroy method is called, the foreground Service should also be removed. The following is the implementation of foreroundactivity:
package com.zejian.ipctest.foregroundService; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.view.View; import android.widget.Button; import com.zejian.ipctest.R; /** * Created by zejian * Time 2016/10/4. * Description: */ public class ForegroundActivity extends Activity { @Override protected void onCreate (Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_foreground); Button btnStart= (Button) findViewById(R.id.startForeground); Button btnStop= (Button) findViewById(R.id.stopForeground); final Intent intent = new Intent( this,ForegroundService.class); btnStart.setOnClickListener( new View.OnClickListener() { @Override public void onClick (View v) { intent.putExtra( "cmd", 0); //0, turn on the front desk service, 1, turn off the front desk service startService(intent); } }); btnStop.setOnClickListener( new View.OnClickListener() { @Override public void onClick (View v) { intent.putExtra( "cmd", 1); //0, turn on the front desk service, 1, turn off the front desk service startService(intent); } }); } }
the code is relatively simple. Let's run the program directly to see the results:
ok ~, the above is about the Service foreground Service. Next, let's talk about the difference between Service and thread
7. Difference between Service and Thread
The two concepts are quite different
Thread is the smallest unit of program execution. It is the basic unit of CPU allocation. UI thread in android system is also a kind of thread. Of course, thread can also be used to perform some time-consuming asynchronous operations.
Service is a mechanism of Android. The service runs on the main thread and is hosted by the system process. The communication between it and other components is similar to client and server. It is a kind of lightweight IPC communication. The carrier of this communication is binder. It is an IPC for exchanging information in the linux layer, and the so-called service background task only refers to components without UI.
The implementation tasks of the two are very different
In android system, thread generally refers to the working thread (i.e. background thread), and the main thread is a special working thread, which is responsible for assigning events to corresponding user interface gadgets, such as drawing events and event response. Therefore, in order to ensure that the response of the application UI can force the main thread to perform time-consuming operations. If the actions you perform cannot be completed quickly, make sure they are executed on a separate worker thread.
Service is a component in the android system. Generally, it runs in the main thread, so it can't perform time-consuming operations in service, otherwise the system will report ANR exception. Most of the reason why service is called background service is that it has no UI and users can't perceive it (of course, some means can also be used to let users know), but if you need to let service perform time-consuming tasks, You can start a separate thread in the service to execute.
Both usage scenarios
When you want to execute time-consuming network or database queries and other tasks that block UI threads or use CPU intensively, you should use worker threads to ensure that UI threads are not occupied and affect the user experience.
In an application, if you need to run in the background for a long time and do not need interaction, use services. For example, playing music is performed in the background through Service+Notification and displayed in the notification bar.
The best way to use both
In most cases, Thread and Service will be used together. For example, downloading files will generally be executed in the background through Service + Notification, and + Thread will be displayed in the Notification bar for asynchronous download. For another example, the application will maintain a Service to obtain push services from the network. In the official view of Android, the same is true. Therefore, the official website provides a combination of Thread and Service to facilitate us to perform time-consuming tasks in the background. It is IntentService. (if you want to know more about IntentService, you can see another article of the blogger: Full explanation of IntentService for Android multithreading )Of course, IntentService is not applicable to all scenarios, but its advantages are easy to use and concise code. We do not need to create Service instances and threads at the same time. It is still very good in some scenarios! Because IntentService is a single worker thread, tasks need to be queued, so it is not suitable for most multitasking situations.
The real relationship between the two
- The two have nothing to do with half a cent.
8. Manage the service life cycle
as for the execution sequence of the Service life cycle method, we have analyzed it almost. Here is a new execution flow chart (from the Android official website)
the left figure shows the life cycle of the Service created using startService(), and the right figure shows the life cycle of the Service created using bindService(). Through the life cycle method in the figure, we can monitor the overall execution process of the Service, including creation, operation and destruction. The method callback in different states of the Service has been clearly described in the previous analysis, which will not be repeated here. The original description of the life cycle on the official website is given below:
the whole life cycle of the service starts from the call of onCreate() and ends when onDestroy() returns. Similar to Activity, the service completes the initial setting in onCreate() and releases all remaining resources in onDestroy(). For example, a music playback service can create a thread for playing music in onCreate() and then stop the thread in onDestroy().
onCreate() and onDestroy() methods will be called for all services regardless of whether the service is created through startService() or bindService().
the effective life cycle of the service starts with calling onStartCommand() or onBind() methods. Each method has an Intent object, which is passed to startService() or bindService() respectively.
for starting a service, the effective life cycle ends at the same time as the whole life cycle (even after onStartCommand() returns, the service is still active). For binding services, the valid life cycle ends when onUnbind() returns.
from the execution flow chart, the service life cycle is much simpler than the Activity life cycle. However, we must pay close attention to how to create and destroy services, because services can run in the background without users' awareness. There are two situations in the life cycle of management services (from creation to destruction):
Start service
The service is created when other components call startService(), then runs indefinitely, and must be stopped from the line by calling stopSelf(). In addition, other components can also stop the service by calling stopService(). After the service is stopped, the system will destroy it.Binding service
This service is created when another component (client) calls bindService(). Then, the client communicates with the service through the IBinder interface. The client can close the connection by calling unbindService(). Multiple clients can bind to the same service, and the system will destroy the service after all bindings are cancelled. (the service does not have to stop running by itself)
although we can manage the service life cycle through the above two cases, we must also consider another case, that is, the combination of starting service and binding service, that is, we can bind to the service that has been started using startService(). For example, you can start the background music service by calling startservice () using Intent (identify the music to play). Then, when the user needs to control the player slightly or obtain information about the currently playing song, the Activity can bind to the service by calling bindService(). In this case, stopService() or stopSelf() will not actually stop the service unless all clients are unbound. Therefore, in this case, we need special attention.
9. Implicit startup problems above Android 5.0
Since there is implicit startup, there will be display startup. Let's first understand what implicit startup and display startup are.
- Display start
Directly on the code at a glance, do not explain.
//Display start Intent intent = new Intent( this,ForegroundService. class); startService(intent);
- Implicit start
An Action needs to be set. We can set the name of the Action to the full path name of the Service. In this case, android:exported defaults to true.
final Intent serviceIntent= new Intent(); serviceIntent.setAction( "com.android.ForegroundService"); startService(serviceIntent);
Meaning of existence
If in the same application, both can be used. In different applications, you can only start implicitly.Implicit startup problems for Android 5.0 and above
after Android 5.0, google banned the implicit declaration of Intent to start the Service for security reasons. If the Service is started implicitly, there will be an error that does not indicate Intent, as follows:
the main reason can be found in the source code. Here we look at the validateServiceIntent(Intent service) in the ContextImpl source code of Android 4.4. It can be seen that if the component and package of the intent to start the service are empty and the version is greater than KITKAT, only an alarm will be sent out to tell the developer to implicitly declare that it is unsafe for intent to start the service
and in android 5 After 0? We're looking at android 6 The source code of 0 is as follows (sublime text check the source code of android versions is cool!!):
from the source code, we can see that if the component and package of the intent ion of starting the service are empty and the version is greater than LOLLIPOP(5.0), an exception will be thrown directly. This exception is consistent with the exception reported in the previous implicit startup. So how to solve it?Solution
- Set Action and packageName
-
final Intent serviceIntent= new Intent(); serviceIntent.setAction( "com.android.ForegroundService");
-
serviceIntent.setPackage(getPackageName()); //Set the package name of the application
-
startService(serviceIntent);
- Convert implicit startup to display startup
-
public static Intent getExplicitIntent(Context context, Intent implicitIntent) {
-
// Retrieve all services that can match the given intent
-
PackageManager pm = context.getPackageManager();
-
List<ResolveInfo> resolveInfo = pm.queryIntentServices(implicitIntent, 0);
-
// Make sure only one match was found
-
if (resolveInfo == null || resolveInfo.size() != 1) {
-
return null;
-
}
-
// Get component info and create ComponentName
-
ResolveInfo serviceInfo = resolveInfo. get( 0);
-
String packageName = serviceInfo.serviceInfo.packageName;
-
String className = serviceInfo.serviceInfo.name;
-
ComponentName component = new ComponentName(packageName, className);
-
// Create a new intent. Use the old one for extras and such reuse
-
Intent explicitIntent = new Intent(implicitIntent);
-
// Set the component to be explicit
-
explicitIntent.setComponent(component);
-
return explicitIntent;
-
}
The calling method is as follows:
-
Intent mIntent= new Intent(); //Auxiliary Intent
-
mIntent.setAction( "com.android.ForegroundService");
-
final Intent serviceIntent= new Intent(getExplicitIntent( this,mIntent));
-
startService(serviceIntent);
This problem is perfectly solved.
10. How to ensure that the service is not killed
in fact, this method is not recommended, but since we talked about it, let's give some implementation ideas here. It is mainly divided into the following three situations
- Killing Service due to insufficient memory resources
This situation is easy to handle. You can set the return value of onStartCommand() method to start_ Stick or START_REDELIVER_INTENT, which means that the Service is killed when the memory resources are tight, and then restored when the memory resources are sufficient. You can also set the Service as the foreground Service, which has a higher priority and will not be killed when memory resources are tight. We have analyzed and implemented the implementation of these two points before, so we won't repeat it here. The simple code is as follows:
/** * Return to start_ Stick or START_REDELIVER_INTENT * @param intent * @param flags * @param startId * @return */ @Override public int onStartCommand (Intent intent, int flags, int startId) { // return super.onStartCommand(intent, flags, startId); return START_STICKY; }
- The user kills the Service by setting - > Apps - > running - > stop
This situation is manually intervened by the user, but fortunately, this process will execute the service life cycle, that is, the onDestory method will be called. At this time, you can send A broadcast restart in onDestory(). This will start immediately after killing the service. This scheme is feasible, but in order to improve the program, we can start two services to monitor and start each other. Service A listens to B's broadcast to start B, and service B listens to A's broadcast to start A. The code implementation of the first method is given here as follows:
package com.zejian.ipctest.neverKilledService; import android.app.Service; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.os.IBinder; import android.support.annotation.Nullable; /** * Created by zejian * Time 2016/10/4. * Description:The user kills the Service by setting - > Apps - > running - > stop */ public class ServiceKilledByAppStop extends Service{ private BroadcastReceiver mReceiver; private IntentFilter mIF; @Nullable @Override public IBinder onBind (Intent intent) { return null; } @Override public void onCreate () { super.onCreate(); mReceiver = new BroadcastReceiver() { @Override public void onReceive (Context context, Intent intent) { Intent a = new Intent(ServiceKilledByAppStop. this, ServiceKilledByAppStop.class); startService(a); } }; mIF = new IntentFilter(); //Custom action mIF.addAction( "com.restart.service"); //Register broadcast receiver registerReceiver(mReceiver, mIF); } @Override public void onDestroy () { super.onDestroy(); Intent intent = new Intent(); intent.setAction( "com.restart.service"); //Send broadcast sendBroadcast(intent); unregisterReceiver(mReceiver); } }
- The user forcibly kills the Service through settings - > Apps - > downloaded - > force stop
This method is tragic because it directly kill s the program and does not follow the life cycle process. In the first two cases, as long as Force Stop is executed, it will be abandoned. In other words, in this case, the service cannot be restarted, or the Force Stop can only be set, but it is unnecessary. It is too rogue....
ok ~, the above is the solution to ensure that the Service will not be killed in a certain scenario. For the third case, if there is a solution, please leave a message. ok, that's the end of all the introduction about Service.
Main references:
https://developer.android.com/guide/components/services.html#Notifications
https://developer.android.com/guide/components/processes-and-threads.html
https://developer.android.com/guide/components/bound-services.html#Lifecycle
http://blog.csdn.net/vrix/article/details/45289207
Exploration of android development Art