Android learning notes-use of remote services and android learning notes --
1. AIDL and Binder
The Activity, Content Provider, Broadcast, and Service components of the Android system can transmit data across processes.
Activity can call the activities of other processes implicitly; Content Provier can access data in other applications across processes; Broadcast communicates with other applications through Broadcast; Service implements RPC through Binder
The implementation mechanism of the Binder is very complicated. We will not describe it here. We only need to know that it is the Remote Procedure Call Protocol in the C/S mode. For example, application A provides operation interfaces that implement addition, subtraction, multiplication, division, and provide external operations. Other applications can remotely call the interfaces provided by application A to perform operations, you do not need to implement it yourself;
So what is AIDL? AIDL is the abbreviation of AndroidInterface definition language, which is the android Interface definition language. Compare a Binder to a pipe. AIDL defines the format of data transmitted in the pipe.
The following example shows how to use AIDL to call remote services.
2. server implementation
1. Create an Android project in Eclipse and name it "Service. Right-click the src directory of the Service Project and name it com. example. aild; add a common file to the new package and name it IRemoteService. aidl indicates that the Service provides the getPid () and basicTypes () interfaces externally;
package com.example.aidl;interface IRemoteService { /** Request the process ID of this service, to do evil things with it. */ int getPid(); /** Demonstrates some basic types that you can use as parameters * and return values in AIDL. */ int basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString);}
After the aidl file is complete, the com. example. aild package and IRemoteService. java file will be automatically generated under the gen directory. We do not need to make any modifications. After that, the Service directory structure is as follows:
Package com. example. service; import android. app. service; import android. content. intent; import android. OS. IBinder; import android. OS. process; import android. util. log; import com. example. aidl. IRemoteService; public class AIDLService extends Service {private String TAG = "REMOTESERVICE"; @ Override public IBinder onBind (Intent intent) {// TODO Auto-generated method stub Log. d (TAG, "DDService onBind"); return mBinder ;}@ Override public void onCreate () {// TODO Auto-generated method stub super. onCreate (); Log. d (TAG, "DDService onCreate ........ "+" Thread: "+ Thread. currentThread (). getName ();}/* is different from the local service. Here, the Stub-Type Binder */private final IRemoteService is created. stub mBinder = new IRemoteService. stub () {public int getPid () {Log. d (TAG, "Thread:" + Thread. currentThread (). getName ();/* The number of the current Thread returned to the caller */return (int) Thread. currentThread (). getId ();} public int basicTypes (int anInt, long aLong, boolean sort lean, float aFloat, double aDouble, String aString) {Log. d (TAG, "Thread:" + Thread. currentThread (). getName (); Log. d (TAG, "basicTypes aDouble:" + aDouble + "anInt:" + anInt + "lean" + lean + "aString" + aString ); /* The number of the current Thread returned to the caller */return (int) Thread. currentThread (). getId ();}};}
We can see that, unlike the local service, IRemoteService is returned in onBind. stub type variables. The Stub class actually inherits from the Binder and defines the interfaces we define in AIDL. We need to implement these interfaces, namely getPid () and basicTypes ();
3. Declare the service in AndroidMainfest. xml
<service android:name=".AIDLService" android:process=":xlzh" > <intent-filter> <action android:name="com.example.aidl" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter></service>
Android: process is added to the Serivce attribute. You can enter the android: process as needed after the colon. Google.
OK, so far, all the work on the server has been completed. Next, let's talk about how the client uses the interfaces provided by the server.
3. Client implementation
1. Create a project in Eclipse named Client. Then copy the com. example. aidl package in the Server project to the src directory of the Client project. The project structure is as follows:
<LinearLayout xmlns: android = "http://schemas.android.com/apk/res/android" android: layout_width = "match_parent" android: layout_height = "match_parent" android: orientation = "vertical"> <Button android: id = "@ + id/binderButton" android: layout_width = "match_parent" android: layout_height = "wrap_content" android: text = "bind"/> <Button android: id = "@ + id/unbinderButton" android: layout_width = "match_parent" android: layout_height = "wrap_content" android: text = "unbind"/> </LinearLayout>
3. Use the remote service in Acitivity. The content of MainActivity. java is as follows:
Package com. example. client; 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. remoteException; import android. util. log; import android. view. view; import android. widget. button; import com. example. aidl. IRemoteService; publ Ic class MainActivity extends Activity {private String TAG = "com. example. aidl "; private IRemoteService remoteService; private Button mBindButton; private Button mUnbindButton; @ Override public void onCreate (Bundle savedInstanceState) {super. onCreate (savedInstanceState); setContentView (R. layout. activity_main); mBindButton = (Button) findViewById (R. id. binderButton); mBindButton. setOnClickListener (New View. onClickListener () {@ Override public void onClick (View v) {// TODO Auto-generated method stub Log. d (TAG, "Bind Service"); // Intent intent = new Intent (IRemoteService. class. getName ();/* Create an Intent and specify AndroidMainfest of the Service. the Action name declared in xml */Intent intent = new Intent ("com. example. aidl ");/* after Android5.0, services cannot be implicitly called, so the package name of the service is specified again */intent. setPackage ("com. example. service ");/* bind service */bindService (Intent, conn, Context. BIND_AUTO_CREATE) ;}}); mUnbindButton = (Button) findViewById (R. id. unbinderButton); mUnbindButton. setOnClickListener (new View. onClickListener () {@ Override public void onClick (View v) {// TODO Auto-generated method stub Log. d (TAG, "UnBind Service");/* UnBind Service */unbindService (conn) ;}} ServiceConnection conn = new ServiceConnection () {@ Override public void onServiceDisconn Ected (ComponentName name) {Log. d (TAG, "UnBind Service success! ") ;}@ Override public void onServiceConnected (ComponentName, IBinder service) {Log. d (TAG," Bind Service success! ");/* Get the server handle */remoteService = IRemoteService. stub. asInterface (service); try {int pid1 = remoteService. getPid (); int pid2 = remoteService. basicTypes (12,122 3, true, 12.2f, 12.3, "My love, I understand");/* print the thread Number of the server side when the getPid interface and basicTypes interface are included */Log. d (TAG, "remoteService. getPid (): "+ pid1 +" remoteService. basicTypes (): "+ pid2);} catch (RemoteException e) {e. printStackTrace () ;}};@ Override protected void onDestroy () {super. onDestroy ();/* The regular method is to set the flag to indicate whether the service has been unbind to determine whether to call unbindService *. This is simple. By default, the service has been unbind.
*/ //unbindService(conn); }}
4. Notes
1. You are not allowed to call services implicitly after Android5.0. Therefore, you must specify the package name of the service to be called (called only one afternoon)
2. When the getpid and basicTypes interfaces are called, the server side processes the client-called threads differently. For specific reasons, you need to learn more about the Binder Mechanism.
3. Unlike local services, the server returns the Stub-Type Binder inherited from the Binder. The client uses the asInterface interface of Stub when obtaining the handle of the server. In addition, the android: process attribute must be specified when the server declares a service in AndroidMainfest. xml.
4. AIDL supports the following data types
Java Native type
String and CharSequence
The elements of List, Map, List, and Map objects must be data types supported by AIDL. The preceding three types do not need to be imported)
The API automatically generated by AIDL needs to be imported)
Classes that implement the android. OS. Parcelable interface. import is required ).
5. Summary
The process for using remote services is summarized as follows;
1. Define the AIDL file and declare the interface that the service needs to provide externally
2. Implement the interface defined in AIDL on the server
3. Declare the remote service in AndroidMainfest. xml
4. Copy the AIDL file of the server in the client
5. Bind the service name and package of the server specified in the client
6. The client uses the Stub. asInterface interface to obtain the hander of the server and call the interface provided by the Service.