Android Service from shortest to shortest (1)
1. Description:
Service is one of the four main components of Android and plays a very important role in Android development. Let's take a look at the official definition of Service:
A Service is an application component that can perform long-running operations in the background and does not provide a user interface. another application component can start a service and it will continue to run in the background even if the user switches to another application. additionally, a component can bind to a service to interact with it and even perform interprocess communication (IPC ). for example, a service might handle network transactions, play music, perform file I/O, or interact with a content provider, all from the background.
Service is an application component that runs time-consuming operations in the background without a user interface. Other application components can start the Service. When the user switches to another application scenario, the Service will continue to run in the background. In addition, a component can be bound to a service for interaction (IPC Mechanism). For example, a service may process network operations and play music, operation file I/O or interaction with content provider, all these activities are performed in the background.
2. Lifecycle
The Service has two statuses: "started" and "Bound"
Started
A service is "started" when an application component (such as an activity) starts it by calling startService (). once started, a service can run in the background indefinitely, even if the component that started it is destroyed. usually, a started service performs a single operation and does not return a result to the caller. for example, it might download or upload a file over the network. when the operation is done, the service shocould stop itself.
Bound
A service is "bound" when an application component binds to it by calling bindService (). A bound service offers a client-server interface that allows components to interact with the service, send requests, get results, and even do so parse SS processes with interprocess communication (IPC ). A bound service runs only as long as another application component is bound to it. multiple components can bind to the service at once, but when all of them unbind, the service is destroyed.
The service started through startService () is in the "started" status. once started, the service runs in the background, even if the application component started has been destroyed. Generally, a service in the started status executes a single task and does not return any results to the initiator. For example, when downloading or uploading a file is completed, the service should stop it.
There is also a "bind" status service, which is started by calling bindService (). A Bound service provides an interface that allows components to interact with the service, which can send requests and obtain returned results, you can also use Process Communication to interact (IPC ). The bound service can only run after the application component is bound. Multiple components can bind a service. When the unbind () method is called, the service will be destroyed.
In addition, there is a warning in the official instructions:
Caution: A service runs in the main thread of its hosting process-the service does not create its own thread and does not run in a separate process (unless you specify otherwise ). this means that, if your service is going to do any CPU intensive work or blocking operations (such as MP3 playback or networking ), you shoshould create a new thread within the service to do that work. by using a separate thread, you will reduce the risk of Application Not Responding (ANR) errors and the application's main thread can remain dedicated to user interaction with your activities.
The service and activity both exist in the main thread of the current process. Therefore, some operations that block the UI, such as time-consuming operations, cannot be performed in the service, for example, start another thread to process time-consuming operations such as network requests. If you perform CPU and time-consuming operations in the service, an ANR warning may be triggered. In this case, the application will pop up the "force close" or "wait" dialog box. Therefore, the understanding of the service is just at the same level as the activity, but it is invisible. It is a component running in the background. This is why the activity is called the basic component of Android.
Methods In the Service life cycle:
In this figure, we can see two types of startup? Http://www.bkjia.com/kf/ware/vc/ "target =" _ blank "class =" keylink "> keys + 8 PHtcTJ + keys/fW3Mbaz + keys + CjwvcD4KPHA + CnNlcnZpY2XJ + keys/Co7o8L3A + keys "brush: java; "> public class MyService extends Service {private int localCount = 0; class MyIBinder extends Binder implements LocalService {@ Overridepublic int getCount () {return localCount ;}} @ Overridepublic void onCreate () {new Thread (new Runnable () {@ Overridepublic void run () {try {while (true) {Log. I ("MyService", "onCreate:" + localCount); Thread. sleep (1000); localCount ++ ;}} catch (InterruptedException e) {e. printStackTrace ();}}}). start (); super. onCreate () ;}@ Overridepublic void onStart (Intent intent, int startId) {Log. I ("MyService", "onStart"); super. onStart (intent, startId) ;}@ Overridepublic int onStartCommand (Intent intent, int flags, int startId) {Log. I ("MyService", "onStartCommand"); return super. onStartCommand (intent, flags, startId) ;}@ Overridepublic void onDestroy () {Log. I ("MyService", "onDestroy"); super. onDestroy () ;}@ Overridepublic boolean onUnbind (Intent intent) {Log. I ("MyService", "onUnbind"); return super. onUnbind (intent) ;}@ Overridepublic IBinder onBind (Intent arg0) {Log. I ("MyService", "onBind"); return new MyIBinder ();}}There is also an easy-to-understand diagram of the Service life cycle (from the network)
3. Service and Thread
1. Service is a mechanism of android. If it is a Local Service during running, the corresponding Service runs on the main thread of the main process. If it is a Remote Service, the corresponding Service runs on the main thread of the independent process, and the communication between the service and the caller is synchronized (whether it is a Remote service or a local service ), it has nothing to do with the thread!
2. the running of Thread is independent from the Activity. That is to say, after an Activity is finished, if you do not stop the Thread actively or the run method in the Thread is not completed, the Thread will continue to be executed. Therefore, there will be a problem: after the Activity is finished, you no longer hold the Thread reference, that is, you cannot control the previously created Thread at the next startup, and service. On the other hand, you cannot control the same Thread in different activities.
3. You can also register BroadcastReceiver in the Service and control it by sending broadcast elsewhere. These cannot be done by the Thread.
In addition, here we want to describe a subclass of Service, IntentService. First, let's take a look at the instructions in the official documentation:
IntentService
This is a subclass of Service that uses a worker thread to handle all start requests, one at a time. this is the best option if you don "t require that your service handle multiple requests simultaneously. all you need to do is implement onHandleIntent (), which has es the intent for each start request so you can do the background work.
IntentService uses the queue method to add the requested Intent to the queue, and then starts a worker thread (thread) to process the Intent in the queue. For Asynchronous startService requests, intentService will process the second one after processing the second one. Each request will be processed in a separate worker thread and will not block the main thread of the application. This provides us with an idea, if there are time-consuming operations, it is better to use IntentService to process time-consuming operations than to enable new threads in the Service. In the general inheritance Service, if time-consuming operations are required, the thread must be opened separately, but the IntentService can be used to perform time-consuming operations directly, because a worker thread is implemented by default. For Asynchronous startService requests, IntentService processes the second request after completing one request.
Let's take a look at the specific implementation of IntentService:
public class HelloIntentService extends IntentService { /** * A constructor is required, and must call the super IntentService(String) * constructor with a name for the worker thread. */ public HelloIntentService() { super("HelloIntentService"); } /** * The IntentService calls this method from the default worker thread with * the intent that started the service. When this method returns, IntentService * stops the service, as appropriate. */ @Override protected void onHandleIntent(Intent intent) { // Normally we would do some work here, like download a file. // For our sample, we just sleep for 5 seconds. long endTime = System.currentTimeMillis() + 5*1000; while (System.currentTimeMillis() < endTime) { synchronized (this) { try { wait(endTime - System.currentTimeMillis()); } catch (Exception e) { } } } }}
For stopping a Service, if the service is not bound, you must stop the service to save system resources when the task is finished. You can stop the Service by stopSelf, you can also stop the service by stopService () in other components. The Bound service can be stopped by onUnBind.
When a new thread is started in the service, you must pay attention to the need to end the thread when the service ends. Otherwise, the resource will be wasted, and may cause business logic errors (if the business logic is processed in the new thread ).
public void onCreate() {new Thread(new Runnable() {@Overridepublic void run() {try {while (true) {Log.i("MyService", "onCreate:" + localCount);Thread.sleep(1000);localCount++;}} catch (InterruptedException e) {e.printStackTrace();}}}).start();super.onCreate();}
At the end of the service, the new Thread will continue to run.
4. Communication
There are many communication methods between services and activities, IBinder and BroaderCast. This article introduces another method: Messenger.
The official document explains: It references a Handler object so that others (Messenger) can send messages to it (using mMessenger.
Send (Message msg) method ). This class allows Message-based communication between different processes (that is, two processes can communicate through Message). Create a Messenger using Handler on the server end, and the client can communicate with the server by holding the Messenger.
Previously, we used Handler + Message for communication. In the same process, we held a Handler object of the main thread from the thread and sent messages to the main thread. Since Android can use the bindler mechanism for cross-communication, we can certainly combine Handler and bindler to send messages across processes.
Check the API and you will find that Messenger is implemented in this way.
The general usage is as follows:
1. remotely create a Messenger object through mMessenger = new Messenger (mHandler)
2. The client uses bindlerService to request remote connection
3. The remote onBind method returns a bindler return mmesder. getBinder ();
4. The client uses the remote return bindler to get a messenger (that is, get a remote Messenger)
public void onServiceConnected(ComponentName name, IBinder service) { rMessenger = new Messenger(service); ...... }
Although a new Messenger is provided here, we can check its implementation.
Public Messenger (IBinder target) {mTarget = imesget. Stub. asInterface (target );}
MTarget is obtained through Aidl, which is actually created remotely.
5. The client can use this remote messenger object to send messages remotely: rMessenger. send (msg );
In this way, the Handler object on the remote server can receive the Message and process it in the handlerMessage (Message msg) method. (This Handler object is the mHandler parameter used when the server creates the Messenger ).
MHandler. obtainMessage ()
After these five steps, it seems that only the client sends messages to the server, and such message transmission is unidirectional. How can we implement bidirectional transmission?
First, you must make a slight modification in step 1, and use the msm before sending (msg. replyTo = mMessenger set your messenger to the message, so that when the server receives the message, it also obtains the client's messenger object, and then the server can obtain the client's messenger object through, and send cMessenger = msg to it. replyTo; cMessenger. send (message );
This completes the function of sending messages from the server to the client, so that the client can receive the messages sent by the server in the handlerMessage method of its own Handler object for processing.
The two-way communication announcement is complete.
Public class Binding extends Activity implements View. onClickListener {private Messenger mMessenger; private Messenger rMessenger; private TextView mCallbackText; private boolean isBound; @ Overrideprotected void onCreate (Bundle savedInstanceState) {super. onCreate (savedInstanceState); setContentView (R. layout. activity_main); initView ();} private Handler mHandler = new Handler () {@ Overridepublic void handleM Essage (Message msg) {switch (msg. what) {case MessengerService. MSG_SET_VALUE: mCallbackText. setText ("Received from service:" + msg. arg1); break; default: break; }}; private ServiceConnection connection = new ServiceConnection () {public void onServiceConnected (ComponentName, IBinder service) {rMessenger = new Messenger (service); mMessenger = new Messenger (mHandler); sendInitMessage ();} public void onS ErviceDisconnected (ComponentName name) {rMessenger = null ;}};/*** send a message to it using the messenger of the server. */Private void sendInitMessage () {Message message = Message. obtain (null, MessengerService. MSG_SET_VALUE); message. replyTo = mMessenger; try {rMessenger. send (message);} catch (RemoteException e) {e. printStackTrace () ;}} public void onClick (View v) {Intent intent = new Intent ("com. app. messenger_service "); switch (v. getId () {case R. id. bind: if (! IsBound) {isBound = bindService (intent, connection, BIND_AUTO_CREATE);} break; case R. id. unbind: if (isBound) {unbindService (connection); isBound = false;} break; default: break;} private void initView () {findViewById (R. id. bind ). setOnClickListener (this); findViewById (R. id. unbind ). setOnClickListener (this); mCallbackText = (TextView) findViewById (R. id. callback); mCallbackText. setText ("Not attached. ");}}
public class MessengerService extends Service {private Messenger cMessenger;private boolean connecting = false;static final int MSG_REGISTER_CLIENT = 1;static final int MSG_UNREGISTER_CLIENT = 2;static final int MSG_SET_VALUE = 3;private Handler mHandler = new Handler() {@Overridepublic void handleMessage(Message msg) {switch (msg.what) {case MSG_SET_VALUE:try {Message message = Message.obtain(null,MessengerService.MSG_SET_VALUE);message.arg1 = 0;cMessenger = msg.replyTo;cMessenger.send(message);} catch (RemoteException e) {e.printStackTrace();}break;default:super.handleMessage(msg);}}};private Messenger mMessenger = new Messenger(mHandler);@Overridepublic void onDestroy() {super.onDestroy();}@Overridepublic boolean onUnbind(Intent intent) {connecting = false;return super.onUnbind(intent);}@Overridepublic IBinder onBind(Intent intent) {connecting = true;new Thread(new Runnable() {@Overridepublic void run() {int i = 0;try {while (connecting) {Message message = Message.obtain(null, MSG_SET_VALUE);Thread.sleep(1000);message.arg1 = i++;cMessenger.send(message);}} catch (InterruptedException e) {e.printStackTrace();} catch (RemoteException e) {e.printStackTrace();}}}).start();return mMessenger.getBinder();}@Overridepublic void onRebind(Intent intent) {Toast.makeText(this, "onRebind", Toast.LENGTH_SHORT).show();}}