Android basic knowledge 05: four major components-service 03: Implementation Mechanism

Source: Internet
Author: User

This topic describes services. There are two articles:

Basic knowledge of Android 05: Service 01 of four components

Android basic knowledge 05: four major components-service 02: Remote Call

Android basic knowledge 05: four major components-service 03: Implementation Mechanism

This article introduces the implementation mechanism of the service. The content comes from the best web.

In a remote service call, how does the activity communicate with the service? For remote service calls, there are usually two different processes in different projects. What is the process communication mechanism? I drew a picture to illustrate it.

When the android process is generated: 1. A main thread is generated. 2. Generate a logoff object 3. Generate a message queue. 4. Generate a virtual machine object to implement communication between Java and C ++. Communication is implemented through the C/C ++-layer IPC.
Inter-process communication: Android uses the ibinder interface to implement inter-process communication. myactivity calls the ibinder's transact () function and calls the remote ontransact () function through IPC.

By default, if servie and activity and broadcastreceiver are in the same project, these components will be executed in the same process and the main thread will be responsible for the execution, of course, you can also execute it in different components through configuration.

We have discussed the remote communication between services, that is, how the activities and services communicate with each other when they are not in the same process, but only at the principle level, today, I wrote a test program to further illustrate the remote communication mechanism.
The IPC communication in the android framework actually relies on a single ibinder interface. When the activity calls the transact () function of the ibinder interface, it calls the remote ontransact () function through the IPC Mechanism. After the transact function is called, the android framework waits for the remote ontransact () function to be executed and returns the result based on the thread synchronization mechanism. Dumb draws a secondary diagram to further illustrate this process.
1. javabbinder is a class provided at the underlying layer of the Android system. In fact, it is a proxy (proxy mode) and implements the ibinder interface at the same time, so that its ontransact () function can call the ontransact () function of mybinder.
2. when remoteservicetransactactivity requires a process to execute the javabbinder object, the android framework starts a thread X from the process in which remoteservicetransact is located to cooperate with thread a for execution, in this way, it becomes the communication in the process.
3. With this remote proxy method, the user will feel like executing a program in a local thread.

The running result is as follows:

From the results, we can see that the thread name of the activity is main, and the thread name of the service is also main, but it is not the same as that of the previous activity, to prove this, I renamed it main-changed. The thread running the binder is called binder thread #2, which is used in combination with the Remote Call of the active thread of the activity.
The test code is as follows:

Remotemusicservice. Java

/** * RemoteMusicService.java * com.androidtest.service.mediaplayer * * Function: TODO * *   ver     date      author * ────────────────────────────────── *    2011-5-19 Leon * * Copyright (c) 2011, TNT All Rights Reserved.*/ package com.androidtest.service; import com.androidtest.R;import com.androidtest.parcelable.ParcelableObject; import android.app.Service;import android.content.Intent;import android.media.MediaPlayer;import android.os.Binder;import android.os.IBinder;import android.os.Parcel;import android.os.Parcelable;import android.os.RemoteException;import android.util.Log; /** * ClassName:RemoteMusicService * Function: TODO ADD FUNCTION * Reason: TODO ADD REASON * * @author   Leon * @version * @since    Ver 1.1 * @Date 2011-5-19 */public class RemoteServiceTransact extends Service { private IBinder mBinder = null ;private String  replyString; @Overridepublic void onCreate() { // TODO Auto-generated method stubsuper.onCreate();mBinder = new myBinder();Thread.currentThread().setName("Service Thread Name : " +Thread.currentThread().getName()+"-chenaged"); } @Overridepublic IBinder onBind(Intent intent) { // TODO Auto-generated method stubreplyString = Thread.currentThread().getName();return mBinder; } public  class myBinder extends Binder{ @Overrideprotected boolean onTransact(int code, Parcel data, Parcel reply,int flags) throws RemoteException { // TODO Auto-generated method stubreply.writeString(replyString +  " Binder Thread is :" + Thread.currentThread().getName());return true; } } }

Remoteservicetransactactivity. Java

/*** Remoteservicetransactactivity. java * COM. androidtest. service ** function: Todo ** ver Date Author * ── ─ * 2011-6-21 Leon ** copyright (c) 2011, TNT All Rights Reserved. */package COM. androidtest. service; import COM. androidtest. service. mediaplayer. imusicservice; 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. parcel; import android. util. log; import android. view. view; import android. widget. button; import android. widget. linearlayout; import android. widget. textview;/*** classname: remoteservicetransactactivity * function: Todo add function * reason: todo add reason ** @ author Leon * @ version * @ since ver 1.1 * @ date 2011-6-21 */public class remoteservicetransactactivity extends activity {Private Static final string tag = remoteservicetransactactivity. class. getsimplename (); private final int WC = linearlayout. layoutparams. wrap_content; private final int Wp = linearlayout. layoutparams. fill_parent; private button buttonrunservice; private textview; private ibinder; @ overrideprotected void oncreate (bundle savedinstancestate) {// todo auto-generated method stubsuper. oncreate (savedinstancestate); linearlayout layout = new linearlayout (this); layout. setorientation (linearlayout. vertical); this. settitle ("test run service .. "); // defines buttonbuttonrunservice = new button (this); buttonrunservice. setid (1); buttonrunservice. settext ("Run service"); buttonrunservice. setonclicklistener (new view. onclicklistener () {@ overridepublic void onclick (view v) {// todo auto-generated method stub parcel sendparcel = parcel. obtain (); parcel replyparcel = parcel. obtain (); try {ibinder. transAct (2, sendparcel, replyparcel, 0); // print the name of the main thread of the activity, rename the name of the main thread of the service, and return, it indicates that the service runs in different // processes textview. settext ("activity thread name is:" + thread. currentthread (). getname () + "and" + replyparcel. readstring ();} catch (exception e) {e. printstacktrace () ;}}); // defines textviewtextview = new textview (this); textview. settext ("ready .... "); // Add it to layout. addview (buttonrunservice); layout. addview (textview); this. setcontentview (layout); this. bindservice (new intent ("com. androidtest. service. remoteservicetransact "), myserviceconnection, context. bind_auto_create);} private serviceconnection myserviceconnection = new serviceconnection () {@ overridepublic void onserviceconnected (componentname, ibinder binder) {ibinder = binder; log. D (TAG, "onserviceconnected") ;}@ overridepublic void onservicedisconnected (componentname name) {log. D (TAG, "onservicedisconnected ");}};}

At the same time, this service needs to be defined in Android manifest so that it can run in different processes.

<service android:enabled="true" android:process=":remote"                                         android:name=".service.RemoteServiceTransact">      <intent-filter>         <action android:name="com.androidtest.service.RemoteServiceTransact" />      </intent-filter>  </service>

The automatically generated code can be found that this Code actually helps us implement a proxy class, which can communicate between different processes. Our activity calls this proxy class, and this calls the methods in the remote service. Thus, remote communication is realized.
Today, I wrote a proxy class for underlying remote communication (the specific communication method has been described in Article 6th), which also achieves remote service call. The basic structure is similar to the code automatically generated by the ADT, but it is much clearer. The usage method is the same as that in the fourth article, which is very common.


Imymusicservice. Java

/*** Imusicservice. java * COM. androidtest. service. mediaplayer ** function: Todo ** ver Date Author * ── ─ * 2011-6-22 Leon ** copyright (c) 2011, TNT All Rights Reserved. */package COM. androidtest. service. remoteplayer; import android. OS. binder; import android. OS. ibinder; import android. OS. parcel; import android. OS. remoteException; import android. util. log;/*** classname: imusicservice function: Todo add function reason: todo add reason ** @ author Leon * @ version * @ since ver 1.1 * @ date 2011-6-22 */public interface imymusicservice {static final string tag = imymusicservice. class. getsimplename (); static final int transaction_play = android. OS. ibinder. first_call_transaction + 0; static final int transaction_pause = android. OS. ibinder. first_call_transaction + 1; static final int transaction_stop = android. OS. ibinder. first_call_transaction + 2; Public void play () throws RemoteException; Public void pause () throws RemoteException; Public void stop () throws RemoteException; public static abstract class stub extends binder implements imymusicservice {// receives @ overrideprotected Boolean ontransact for the Service (INT code, parcel data, parcel reply, int flags) throws RemoteException {// todo auto-generated method stubswitch (CODE) {Case transaction_play: This. play ();/*** note that readstring is interpreted as this * read a string value from the parcel at the current dataposition (). * For the second read, the data position will be moved forward. Here it is null */string temp = data. readstring (); log. V (TAG, "the message from clinet:" + temp); reply. writestring (temp); Return true; Case transaction_pause: This. pause (); log. V (TAG, "the message from clinet:" + data. readstring (); reply. writestring (data. readstring (); Return true; Case transaction_stop: This. stop (); log. V (TAG, "the message from clinet:" + data. readstring (); reply. writestring (data. readstring (); Return true;} return Super. ontransact (Code, Data, reply, flags);} // template mode public abstract void play () throws RemoteException; public abstract void pause () throws RemoteException; public abstract void stop () throws RemoteException; // actually gets the proxy class for the activity to call public static imymusicservice asinterface (ibinder) {return new proxy (ibinder );} // The activity actually communicates with the remote stub through this proxy. Private Static class proxy implements imymusicservice {private ibinder; Public proxy (ibinder) {This. ibinder = ibinder ;}@ overridepublic void pause () {parcel senddata = parcel. obtain (); parcel replydata = parcel. obtain (); senddata. writestring ("pause"); try {ibinder. transAct (transaction_pause, senddata, replydata, 0); log. V (TAG, "the message from service" + replydata. readstring ();} catch (RemoteException e) {// todo auto-generated catch blocke. printstacktrace ();} // todo auto-generated method stub} @ overridepublic void play () {// todo auto-generated method stubparcel senddata = parcel. obtain (); parcel replydata = parcel. obtain (); senddata. writestring ("play"); try {ibinder. transAct (transaction_play, senddata, replydata, 0); log. V (TAG, "the message from service" + replydata. readstring ();} catch (RemoteException e) {// todo auto-generated catch blocke. printstacktrace () ;}@ overridepublic void stop () {// todo auto-generated method stubparcel senddata = parcel. obtain (); parcel replydata = parcel. obtain (); senddata. writestring ("stop"); try {ibinder. transAct (transaction_stop, senddata, replydata, 0); log. V (TAG, "the message from service" + replydata. readstring ();} catch (RemoteException e) {// todo auto-generated catch blocke. printstacktrace ();}}}}}

Mycustomremotebinder. Java

/** * MyRemoteBinder.java * com.androidtest.service.remoteplayer * * Function: TODO * *   ver     date      author * ────────────────────────────────── *    2011-6-22 Leon * * Copyright (c) 2011, TNT All Rights Reserved.*/ package com.androidtest.service.remoteplayer; import android.media.MediaPlayer;import android.os.RemoteException; import com.androidtest.service.mediaplayer.MyMediaController; /** * ClassName:MyRemoteBinder * Function: TODO ADD FUNCTION * Reason: TODO ADD REASON * * @author   Leon * @version * @since    Ver 1.1 * @Date 2011-6-22 */public class MyCustomRemoteBinder extends IMyMusicService.Stub{ public  MyCustomRemoteBinder(MediaPlayer mediaPlayer){MyMediaController.mediaPlayer=mediaPlayer ;};@Overridepublic void play() throws RemoteException { // TODO Auto-generated method stubMyMediaController.play.execute(); } @Overridepublic void pause() throws RemoteException { // TODO Auto-generated method stubMyMediaController.pause.execute(); } @Overridepublic void stop() throws RemoteException { // TODO Auto-generated method stubMyMediaController.stop.execute(); };  }

The aidl language is used to enable ADT to automatically generate a stub class (Binder subclass) to call services in different processes. By studying ADT, this article is the end of Android Service (7). It is not difficult to use the service, but it is difficult to understand the mechanism, in particular, remote calls must have a deep understanding of remote proxy. The source code of this series is a lot of design. If someone needs it, please add the best group of niu.com to ask for dumb.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.