Android service is divided into two types:
- Local Service: Called Within the same apk
- Remote service: Called by another apk
Remote services need to be done with Aidl.
What is Aidl?
Aidl (Android Interface Definition Language) is an IDL language used to generate interprocess communication between two processes on Android devices (interprocess communication, IPC) The code. You can use Aidl to generate serializable parameters if you want to invoke the operation of another process (such as a service) object in one process (for example, activity).
The AIDL IPC mechanism is interface-oriented, like COM or CORBA, but more lightweight. It is the use of proxy classes to pass data on both the client and the implementation side.
The role of Aidl
Because each application runs in its own process space and can run another service process from the application UI, objects are often passed between different processes. On the Android platform, a process usually cannot access the memory space of another process, so in order to talk, the object needs to be decomposed into basic units that the operating system can understand, and through process boundaries in an orderly manner.
The process of implementing this data transfer through code is tedious, and Android provides aidl tools to handle the job.
Choose the use of Aidl
Official documentation specifically reminds us of when it is necessary to use AIDL: Only you allow clients to access your service from different applications for interprocess communication, as well as to handle multithreading in your service.
If you do not need to perform concurrent communication between different applications (IPC), you should create your interface by implementing a Binder, or if you want to do IPC but do not need to process multithreading, then implement your interface using a Messenger. In any case, before using Aidl, you must understand how to bind Service--bindservice.
The following is a demonstration of the use of aidl using an instance of client activity operation Service-side services to play music.
Development tools: Eclipse 3.7 (Indigo) + Android SDK 4.1+ ADT 20.0.2
Service-side code structure
Client code structure
What is marked is the need for hands-on.
Service side
Create a new Android application project, named Playerserver. A music file is placed inside the raw folder under Res, and I'm putting the Delta Goodrem "Lost Without You" clip. If there is no raw this folder, create a new one yourself, named Raw. This file is sandwiched between the raw folder and the Layout folder. The files in raw conform to the naming rules for identifiers, do not appear in Chinese and spaces, and multiple words can be connected with underscores.
Create a new Iremoteserviice.aidl file and add the following code:
Package pandafang.demo.playerserver; Interface Iremoteservice { void play (); void Stop (); }
The code of the visible aidl file is the same as Java's interface, but the aidl cannot be added with modifiers such as public. When Ctrl + S is saved, ADT automatically generates Iremoteservice.java files based on this iremoteservice.aidl file. As with the R.java file under "gen/package name", the code is generated automatically and not manually modified.
The next step is knowledge of the bound service (reference: official documentation). Iremoteservice.java has a stub static abstract class extends Binder implements Iremoteservice. Write yourself a playerservice used to play music, play music needs to use the Android.media.MediaPlayer class. The code is as follows:
Package pandafang.demo.playerserver; Import Java.io.FileDescriptor; Import java.io.IOException; Import Android.app.Service; Import android.content.Intent; Import Android.media.MediaPlayer; Import Android.os.IBinder; Import android.os.RemoteException; Import Android.util.Log; /** * Music Playing service * @author Panda Fang * @date 2012-10-22 10:15:33 * * Public class Playerservice extends service { public static final String TAG = "Playerservice"; Private MediaPlayer MPlayer; Implement the interface defined in the Aidl file private IBinder Mbinder = new Iremoteservice.stub () {@Override public void Stop () throws RemoteException {try {if (mplayer.isplaying ()) {m Player.stop (); }} catch (Exception e) {//Todo:handle Exception e.printstacktrace (); }} @Override public void Play ()Throws RemoteException {try {if (mplayer.isplaying ()) {return; }//Before start requires prepare. If you use method one before instantiating MPlayer, start directly on the first play without prepare. But after stop one time, play again needs to be prepare before start. Before using the method two here is simple, do not judge various conditions mplayer.prepare (); Mplayer.start (); } catch (Exception e) {//Todo:handle Exception e.printstacktrace (); } } }; @Override public IBinder onbind (Intent Intent) {log.i (TAG, "service Onbind"); if (mplayer==null) {///Method A description//This method instantiates the player while specifying the music data source, if this method is used before, Mplayer.start () no longer need to call Mplayer.prepar E ()//Official documentation: On success, prepare () would already has been called and must not being called again. Once the create succeeds, prepare has been called and is not called again. View source code The Prepare method has been called inside the Create method. Method one start//MPlayer = Mediaplayer.create (this, r.raw.lost); Method one end//Method two description//If this method is required, call Mplayer.prepare () before Mplayer.start () Method two begins mplayer = new MediaPlayer (); try {filedescriptor fd = getresources (). OPENRAWRESOURCEFD (R.raw.lost). Getfiledescriptor ();//Get Music data source Mplayer.setdatasource (FD); Set data source mplayer.setlooping (TRUE); Set to loop play} catch (IOException e) {//TODO auto-generated catch block e.pr Intstacktrace (); }//Method two end log.i (TAG, "player created"); } return Mbinder; } @Override public boolean onunbind (Intent Intent) {if (MPlayer! = null) {MPlayer. Release (); } log.i (TAG, "service Onunbind"); return Super.onunbind (Intent); } }
After the service has been written, it is customary to add a declaration in the Androidmanifest.xml code as follows:
Need to join is just ... In that paragraph, pay attention to the android:process= ": Remote" and intent-filter.
Run the service-side to the device, ready to be called to the client.
Client
Create a new Android application project, named Playerclient. Copy the package that has the Aidl file on the server to the client src directory, keep the Aidl file in the package, and delete the other files.
Edit the activity_main.xml layout file under Layout, add two buttons, the code is as follows:
Write the Mainactivity.java code as follows:
Package pandafang.demo.playerclient; Import Pandafang.demo.playerserver.IRemoteService; 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.Menu; Import Android.view.View; Import Android.view.View.OnClickListener; Import Android.widget.Button; /** * Client Control interface * @author Panda Fang * @date 2012-10-22 10:36:44 * * public class Mainactivity extends Activity { public static final String TAG = "mainactivity"; The string public of the Intent-filter ACTION declaration in the server-side Androidmanifest.xml public static final string action = "Com.example.playerserver. Playerservice "; Private Button playbtn, stopbtn; Private Iremoteservice Mservice; Private Boolean isbinded = false; Private SerViceconnection conn = new Serviceconnection () {@Override public void onservicedisconnected (Co Mponentname name) {isbinded = false; Mservice = null; } @Override public void onserviceconnected (componentname name, IBinder service) { Mservice = IRemoteService.Stub.asInterface (service); Isbinded = true; } }; @Override public void OnCreate (Bundle savedinstancestate) {super.oncreate (savedinstancestate); Setcontentview (R.layout.activity_main); Dobind (); Initviews (); } private void Initviews () {playbtn = (Button) Findviewbyid (R.id.button1); STOPBTN = (Button) Findviewbyid (R.id.button2); Playbtn.setonclicklistener (Clicklistener); Stopbtn.setonclicklistener (Clicklistener); } @Override Public boolean Oncreateoptionsmenu (Menu menu) {gEtmenuinflater (). Inflate (R.menu.activity_main, menu); return true; } @Override protected void OnDestroy () {dounbind (); Super.ondestroy (); } public void Dobind () {Intent Intent = new Intent (ACTION); Bindservice (Intent, Conn, context.bind_auto_create); } public void Dounbind () {if (isbinded) {unbindservice (conn); Mservice = null; isbinded = false; }} private Onclicklistener Clicklistener = new Onclicklistener () {@Override public void OnClick (View v) {if (V.getid () = = Playbtn.getid ()) {//Play LOG.I (TAG, "play button clicked"); try {mservice.play (); } catch (RemoteException e) {//TODO auto-generated catch block E.printstacktra CE (); }} else {//Stop log.i (TAG, "stop button clicked"); try {mservice.stop (); } catch (RemoteException e) {//TODO auto-generated catch block E.printstacktra CE (); } } } }; }
Mainactivity is automatically generated from the wizard and does not require a declaration to be registered with Androidmanifest.xml.
Run client to device, press button to play/stop effect