One of the four major components of Android-Service (2)

Source: Internet
Author: User

This section describes the service lifecycle and local sevice. The following describes the remote service and aidl (Android Interface Definition Language;

The official document reminds us that it is necessary to use aidl:

Only you allow the client to access your service from different applications for inter-process communication, and want to process multithreading in your service.

Why does aidl need to be used? Why is it impossible to use service directly?

In Android, each application can have its own process. Services are often used when writing UI applications.When data and objects are transmitted between different applications and each application has its own process, how does one transmit objects in different processes? Obviously, cross-Process Memory sharing is not allowed in Java. Therefore, objects can only be transferred into simple forms that the operating system can understand to achieve cross-border object access.In J2EE, RMI can be used to pass objects through serialization. In Android, aidl is used. In theory, aidl can pass bundle, but it is troublesome to do so.

First, we will introduce the relevant knowledge of aidl:
Aidl (Android Interface Description Language) is an excuse description language. The compiler can generate a piece of code through the aidl file,Use predefined interfaces to implement internal communication between two processes. If you want to access an object in another service in one activity, you must first convert the object to a parameter that can be recognized by aidl (possibly multiple parameters ), then, aidl is used to pass these parameters. At the message receiver, these parameters are used to assemble them into desired objects.

Define the aidl Interface
The aidl interface file is nothing special to the common interface content, but its extension is. aidl. Save it in the src directory.If other applications require IPC, the SRC of those applications will also contain this file..Android SDK tools automatically generates an ibinder interface file in the gen directory..Service must implement this ibinder interface as appropriate. Then the client program can bind the service and call the method from ibinder during IPC.
Each aidl file can only define one interface, and can only be an interface declaration and method declaration.

Create a. aidl File
Aidl uses a simple syntax to declare an interface and describe the parameters and return values of its methods and methods. These parameters and return values can be of any type, or even interfaces generated by other aidl.
The basic data types (INT, long, Char, Boolean, etc.), string and charsequence of the Java programming language, list and map of the Set interface types, and the import statement is not required..
If you want to use other aidl Interface Types in aidl, You need to import them, even in the same package structure. Aidl allows passing classes that implement the parcelable interface. Import is required.
Note that for non-basic data types, which are not string and charsequence types, a direction is required,Including in, out, And inout, In indicates that it is set by the client, out indicates that it is set by the server, and inout indicates that both can be set.

Aidl only supports interface methods,Static variables cannot be exposed..AidlIPC (interprocess communication)The Mechanism is similar to that of COM or CORBA,Is based on the interface, but it is lightweight. It uses the proxy class to pass values between the client and the implementation layer.

To use aidl, you need to do two things:

1. Introduce related classes of aidl. 2. Call the class generated by aidl.


Create an aidl Service
It is more complex than building a common service,The procedure is as follows::
(1) createFiles with the extension of aidl. The syntax of this file is similar to Java code, but it will be slightly different. For details, see the instance content.
(2) If the aidl file content is correct,The ADT automatically generates a Java interface file (*. Java).
(3) create a service class ).
(4) Implement the Java interface generated by the aidl file.
(5) In androidmanifest. configure the aidl service in the XML file. Note that the value of the Android: Name attribute in the <action> tag is the ID of the service to be referenced by the client, that is, the parameter value of the intent class.

This example adds and displays user information;

This section describes the knowledge about aidl and pracable;

Code:

Remoteservicedemoactivity. Java

Package COM. potato; import Java. util. list; 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. view. view; import android. widget. button; import android. widget. edittext; import android. widget. t Oast; public class remoteservicedemoactivity extends activity {/** called when the activity is first created. */Boolean misremotebound = false; // Note 2 edittext meditinputperson; @ overridepublic void oncreate (bundle savedinstancestate) {super. oncreate (savedinstancestate); setcontentview (R. layout. main); If (misremotebound) {unbindservice (mremoteconnection);} else {bindservice (new intent ("com. potato. itests Ervice "), // Note 1 mremoteconnection, context. bind_auto_create);} misremotebound =! Misremotebound; button btnaddperson = (button) findviewbyid (R. id. btn_add_person_info); btnaddperson. setonclicklistener (new view. onclicklistener () {private int Index = 0; @ overridepublic void onclick (view) {person = new person (); Index = index + 1; person. setname ("person" + index); person. setage (20); person. settelnumber ("123456"); try {// Save the information to mremoteservice. savepersoninfo (person);} catch (REM Oteexception e) {e. printstacktrace () ;}}); meditinputperson = (edittext) findviewbyid (R. id. edit_input_person_info); // display all saved information on edittext. Button btnlistperson = (button) findviewbyid (R. id. btn_list_person_info); btnlistperson. setonclicklistener (new view. onclicklistener () {@ overridepublic void onclick (view) {list <person> List = NULL; try {list = mremoteservice. getallperson ();} catch (remoteeffectio N e) {e. printstacktrace ();} If (list! = NULL) {stringbuilder text = new stringbuilder (); For (person: List) {text. append ("\ nperson name:"); text. append (person. getname (); text. append ("\ n age:"); text. append (person. getage (); text. append ("\ n Tel number:"); text. append (person. gettelnumber ();} meditinputperson. settext (text);} else {toast. maketext (remoteservicedemoactivity. this, "Get data error", toast. length_short ). show () ;}}) ;}protected void ondestroy () {super. ondestroy (); // Note 3 Remove bindif (misremotebound) {unbindservice (mremoteconnection) ;}} private itestservice mremoteservice; private serviceconnection mremoteconnection = new serviceconnection () {public void onserviceconnected (componentname classname, ibinder Service) {mremoteservice = itestservice. stub. asinterface (service); // Note 4} public void onservicedisconnected (componentname classname) {mremoteservice = NULL; // Note 4 }};}

Note 1.

Intent-related knowledge is used here. I will not explain it first. I will explain it later. Please stay tuned;

Note 2, 3

Misremotebound identifies the binding of a service, which is the same as the activity and lives together;

Note 4

Mremoteservice = itestservice. stub. asinterface (service );

This is a unique call method of aidl;

The ibinder in the onserviceconnection method parameter is not of the imyservice. Stub type and cannot be directly transformed up. You can only use the imyservice. stub. asinterface (service) method to obtain a type object that implements the imyservice interface.Its type is imyservice. stub. Proxy.

Remoteservice. Java

Package COM. potato; import Java. util. using list; import Java. util. list; import android. app. service; import android. content. intent; import android. OS. ibinder; import android. OS. remoteException; public class remoteservice extends Service {private region list <person> personlist = new region list <person> (); @ overridepublic ibinder onbind (intent) {return mbinder ;} // implement the private final itestservice interface to be called. stub Mbinder = new itestservice. Stub () {// Note 5 @ overridepublic void savepersoninfo (person) throws RemoteException {If (person! = NULL) {personlist. Add (person) ;}@ overridepublic list <person> getallperson () throws RemoteException {return personlist ;}};}

Note 5.

Implement and add the interfaces and methods required by you;

Person. Java

Package COM. potato; import android. OS. parcel; import android. OS. parcelable; public class person implements parcelable {// Note 6 private string name; private string telnumber; private int age; Public Person () {} public person (parcel PL) {name = pl. readstring (); telnumber = pl. readstring (); age = pl. readint ();} Public String getname () {return name;} public void setname (string name) {This. name = Name;} Public String gettelnumber () {return telnumber;} public void settelnumber (string telnumber) {This. telnumber = telnumber;} public int getage () {return age;} public void setage (INT age) {This. age = age ;}@ overridepublic int describecontents () {return 0 ;}@ overridepublic void writetoparcel (parcel DEST, int flags) {// note 6dest. writestring (name); DeST. writestring (telnumber); DeST. writeint (AGE);} public static final parcelable. creator <person> creator = new parcelable. creator <person> () {// Note 6 @ overridepublic person createfromparcel (parcel source) {return new person (source) ;}@ overridepublic person [] newarray (INT size) {return new person [size] ;}};}

Note 6

Serialization;

The person class is a serialized class,The parcelable interface is used for serialization.,Is a serialization class provided by Android, which is more efficient than serializable..
Parcelable needs to implement three functions:
1) void writetoparcel (parcel DEST, int flags) writes the data to be serialized to the external provided parcel object DeST. After reading the code on the internet, I guess that the order of reading parcel data must be the same as the write order here. Otherwise, the data may be read incorrectly. I have not tried it!
2) describecontents () is useless;
3) Static final parcelable. creator Object Creator the Creator name is fixed, and its corresponding interface has two methods:
Createfromparcel (parcel source) is used to create a person instance from the source

Newarray (INT size) deserialization;

The following is the aidl file generation (as long as the file named. aidl is generated)

Itestservice. aidl

Package com. Potato; import com. Potato. person;/** when writing aidl files, note the following: 1. The interface name and aidl file name are the same. 2. You do not need to add access permission modifiers such as public, private, and protected before interfaces and methods, or use final or static. 3. The types of packages supported by aidl by default are Java basic types (INT, long, Boolean, etc.) and (string, list, map, and charsequence). Import Declaration is not required when these types are used. Element Types in list and map must be supported by aidl. If you use a custom type as a parameter or return value, the custom type must implement the parcelable interface. 4. The custom type and other Interface Types generated by aidl should be explicitly imported in the aidl description file, even if the class and the defined package are in the same package. 5. All non-Java basic type parameters in the aidl file must be marked with In, out, And inout to indicate whether the parameters are input parameters, output parameters, or input and output parameters. 6. The default mark of the original Java type is in, and cannot be any other mark. */Interface itestservice {void savepersoninfo (in person); List <person> getallperson ();}

Person. aidl

Package com. Potato;/** Note 7 the first letter of parcelable must be in lowercase. **/parcelable person;

Note 7

Because person is not a basic Java class or string, list, map, and charsequence, the import declaration is required;

The first letter of parcelable must be in lowercase.

Main. xml

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="fill_parent"    android:layout_height="fill_parent"    android:orientation="vertical" >    <TextView        android:layout_width="fill_parent"        android:layout_height="wrap_content"        android:text="@string/hello" />         <Button        android:id="@+id/btn_add_person_info"        android:layout_width="fill_parent"        android:layout_height="wrap_content"        android:text="addPerson" />           <Button        android:id="@+id/btn_list_person_info"        android:layout_width="fill_parent"        android:layout_height="wrap_content"        android:text="listPerson" />            <EditText        android:id="@+id/edit_input_person_info"        android:layout_width="fill_parent"        android:layout_height="wrap_content"/></LinearLayout>

Androidmainfest. xml

<?xml version="1.0" encoding="utf-8"?><manifest xmlns:android="http://schemas.android.com/apk/res/android"    package="com.potato"    android:versionCode="1"    android:versionName="1.0" >    <uses-sdk android:minSdkVersion="8" />    <application        android:icon="@drawable/ic_launcher"        android:label="@string/app_name" >        <activity            android:label="@string/app_name"            android:name=".RemoteServiceDemoActivity" >            <intent-filter >                <action android:name="android.intent.action.MAIN" />                <category android:name="android.intent.category.LAUNCHER" />            </intent-filter>        </activity>                <service             android:name=".RemoteService"            android:process=":remote">             <intent-filter>                 <action android:name="com.potato.ITestService" />         </intent-filter>         </service>            </application></manifest>

Note:

<service             android:name=".RemoteService"            android:process=":remote">             <intent-filter>                 <action android:name="com.potato.ITestService" />              </intent-filter> </service>

Android: Process = ": Remote" indicates that a new process is automatically created in an application when the service is required.

If Android: Process = "remote" does not have a semicolon (:), a global process is created and different applications share the process.

If you have any questions, please send an email;

Contact: ligexiao@gmail.com

This also includes an instance of the player, which uses aidl

Source code download: source code

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.