In the previous section, we explained the local service. This section mainly describes remote service, which involves aidl. Okay, old rules. Let's start with the basic knowledge:
I. Basic Knowledge
Role of aidl
On the Android platform, each application Program All apps are running in their own process space. Generally, one process cannot access the memory space of another process (one application cannot access another application). To communicate, you need to break down the object into basic units that the operating system can understand, android provides aidl for processing.
Aidl (Android Interface Definition Language) Is an IDL Language used to generate Interprocess Communication (IPC) between two processes on the Android device. Code . If you want to call operations on objects in another process (such as service) in a process (such as activity), you can use aidl to generate serializable parameters. In other words, this is the activity of my app. You need to call the service of other apps.
Of course, the activity and service of the same app can also be in different processes, which can be set in service configuration, Android: Process = ": Remote"
Use of aidl The official documentation reminds us when to use aidl is necessary: Only you allow the client to access your service from different applications for inter-process communication, and want to process multithreading in your service. (Too stiff. Call components of different processes .)
So how to make aidl? The following steps
1:Create a. aidl file. Create a new file and. AidlSave the file as a suffix and write interfaces and methods in this file. The general Java interface declaration is the same. The difference is that the complicated import type should be displayed, even if the complex type object is in the same package. Java basic data types (INT, long, Char, Boolean, etc.), string and charsequence, set Interface Types list and map, no need to import.
For example:
Package com. Dongzi;
Interface istockquoteservice {
Double getprice (string ticker );
}
2: after creating the aidl file, refresh the project and you will find a Java file identical to the aidl file under the gen package. For example:
View code
/*
* This file is auto-generated. Do not modify.
* Original file: D :\\ mywordspace \ Myphone \ SRC \ com \ Dongzi \ istockquoteservice. aidl
*/
Package Com. Dongzi;
Public Interface Istockquoteservice Extends Android. OS. iinterface {
/** Local-side IPC implementation stub class. */
Public Static Abstract Class Stub Extends Android. OS. Binder Implements Com. Dongzi. istockquoteservice {
Private Static Final Java. Lang. String descriptor = "com. Dongzi. istockquoteservice ";
/** Construct the stub at attach it to the interface. */
Public Stub (){
This . Attachinterface ( This , Descriptor );
}
/**
* Cast an ibinder object into an com. Dongzi. istockquoteservice
* Interface, generating a proxy if needed.
*/
Public Static Com. Dongzi. istockquoteservice asinterface (Android. OS. ibinder OBJ ){
If (OBJ = Null )){
Return Null ;
}
Android. OS. iinterface Iin = (Android. OS. iinterface) obj. querylocalinterface (descriptor );
If (IIN! = Null ) & (IIN Instanceof Com. Dongzi. istockquoteservice ))){
Return (COM. Dongzi. istockquoteservice) iIn );
}
Return New Com. Dongzi. istockquoteservice. stub. Proxy (OBJ );
}
Public Android. OS. ibinder asbinder (){
Return This ;
}
@ Override
Public Boolean Ontransact ( Int Code, Android. OS. Parcel data, Android. OS. Parcel reply, Int Flags)
Throws Android. OS. RemoteException {
Switch (CODE ){
Case Interface_transaction :{
Reply. writestring (descriptor );
Return True ;
}
Case Transaction_getprice :{
Data. enforceinterface (descriptor );
Java. Lang. String _ arg0;
_ Arg0 = data. readstring ();
Double _ Result = This . Getprice (_ arg0 );
Reply. writenoexception ();
Reply. writedouble (_ result );
Return True ;
}
}
Return Super . Ontransact (Code, Data, reply, flags );
}
Private Static Class Proxy Implements Com. Dongzi. istockquoteservice {
Private Android. OS. ibinder mremote;
Proxy (Android. OS. ibinder remote ){
Mremote = remote;
}
Public Android. OS. ibinder asbinder (){
Return Mremote;
}
Public Java. Lang. String getinterfacedescriptor (){
Return Descriptor;
}
Public Double Getprice (Java. Lang. String ticker) Throws Android. OS. RemoteException {
Android. OS. Parcel _ DATA = Android. OS. Parcel. Obtain ();
Android. OS. Parcel _ reply = Android. OS. Parcel. Obtain ();
Double _ Result;
Try {
_ Data. writeinterfacetoken (descriptor );
_ Data. writestring (ticker );
Mremote. transact (stub. transaction_getprice, _ data, _ reply, 0 );
_ Reply. readexception ();
_ Result = _ reply. readdouble ();
}
Finally {
_ Reply. Recycle ();
_ Data. Recycle ();
}
Return _ Result;
}
}
Static Final Int Transaction_getprice = (Android. OS. ibinder. first_call_transaction + 0 );
}
Public Double Getprice (Java. Lang. String ticker) Throws Android. OS. RemoteException;
}
The aidl tool automatically generates so much code, but we only need to know three.
Public static abstract class stub extends Android. OS. Binder implements com. Dongzi. istockquoteservice static abstract internal class stub
Private Static class proxy implements com. Dongzi. istockquoteservice aidl Service proxy class
Public double getprice (Java. Lang. String ticker) throws Android. OS. RemoteException;The interface published by aidl is the interface method we have defined.
3: store the aidl file in other client applications. We use this as the server.. Of course, we can also conveniently use this application as the client and server. ActuallyThe fundamental difference is that the caller and the called are in different processes.AddAndroid: Process = ": Remote"You can. Save the trouble of creating an application client call.
4: aidl only defines a contract. Here we need a service to provide the service. Therefore, myservice is created.
Ii. Practice
Now that we have some basic knowledge, let's get started with code. Suppose we need to call the services of other applications in a process. This service provides a stock price query or GPS positioning service.
Define a class, inherit the stub internal class generated by aidl, and implement the methods defined by aidl.
The Code is as follows:
View code
Package Com. Dongzi;
Import Android. App. Service;
Import Android. content. intent;
Import Android. OS. ibinder;
Import Android. OS. RemoteException;
Import Android. util. log;
Public Class Myservice Extends Service {
Static Final String tag = "myservice ";
// Define the internal class myserviceimpl to inherit the internal class automatically generated by our aidl file,
// And implement the interface method defined in the aidl file.
Private Class Myserviceimpl Extends Istockquoteservice. Stub {
@ Override
Public Double Getprice (string ticker) Throws RemoteException {
Log. E (TAG, "getprice ");
Return 10.5;
}
}
@ Override
Public Ibinder onbind (intent arg0 ){
// Return aidl implementation
Return New Myserviceimpl ();
}
@ Override
Public Void Ondestroy (){
Log. E (TAG, "Release myservice ");
Super . Ondestroy ();
}
}
We need to return our aidl interface implementation object in the onbind Method for other processes to call.
Of course, now that both aidl and service are defined, you need to set them in mainfest. xml.
<Service android: Name = ". myservice"
Android: Process = ": Remote"
>
<Intent-filter>
<Action Android: Name = "com. Dongzi. istockquoteservice"/>
</Intent-filter>
</Service>
In the same app on the client server, Android: Process = ": Remote" indicates that a new process is automatically created when the service is required in the application. If Android: Process = "remote" does not have a semicolon (:), a global process is created and different applications share the process.
Now the client is calling our service. The Code is as follows:
View code
Package Com. Dongzi;
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. View. View. onclicklistener;
Import Android. widget. Button;
Public Class Myyactivity Extends Activity {
Static Final String tag = "myyactivity ";
@ Override
Public Void Oncreate (bundle savedinstancestate ){
Super . Oncreate (savedinstancestate );
Setcontentview (R. layout. Main );
Button btncall = (button) findviewbyid (R. Id. btncall );
If (Btncall! = Null )
Btncall. setonclicklistener ( New Onclicklistener (){
@ Override
Public Void Onclick (view v ){
// Bind a service
Bindmyservice ();
}
});
}
Istockquoteservice iservice = Null ;
Private Serviceconnection conn = New Serviceconnection (){
@ Override
Public Void Onserviceconnected (componentname name, ibinder Service ){
// Return the aidl interface object, and then call the aidl method.
Iservice = istockquoteservice. stub. asinterface (service );
Double Values = 0.0;
Try {
Value = iservice. getprice ("");
}
Catch (RemoteException e ){
Log. E (TAG, "Call error! ");
E. printstacktrace ();
}
Log. E (TAG, "Return Value:" + value );
}
@ Override
Public Void Onservicedisconnected (componentname name ){
Log. I (TAG, "release service ");
}
};
Private Void Bindmyservice (){
// Intent intent = new intent ("com. Dongzi. istockquoteservice ");
Intent intent = New Intent ( This , Myservice.Class );
Startservice (intent );
Bindservice (intent, Conn, context. bind_auto_create );
}
}
Start the service when you click the button and then bind the service. After connecting to the service, we will find that the method defined in aidl is called and printed as follows:
The project structure is as follows: