service 绑定有三种实现方式:
1. 直接继承Binder类实现。
条件: 同一应用,同一进程
2. 使用Messenger实现。
条件:要在不同的进程间通信,这种方式不用考虑线程安全性。(单线程操作时使用)
3. 使用AIDL实现。
条件:要在不同的进程间通信,并且需要多线程处理。要考虑线程之间的安全性。
使用AIDL实现:
三大基本步骤
- 创建.aidl文件
- 实现接口
- 公开接口
- 方法定义有0个或者多个参数,可以返回一个值或者是void.
- 方法中不是基本类型的参数,需要在方法参数前面加入in , out or inout
- 包含在.aidl中所有的注释在IBinder接口中都会生成(除了在import和package之前的注释)
- 仅仅支持方法,不支持静态的成员变量。
package com.hualu.servicemy; import com.hualu.servicemy.Book; interface IRemoteService{ int getPID() ; void basicInt(int i) ; void basicByte(byte b) ; void basicLong(long l) ; void basicDouble(double d) ; void basicFloat(float f) ; void basicString(String s) ; void basicBoolean(boolean b) ; void basicCharSequence(char c) ; void basicList(inout List<String> l) ; void basicMap(in Map m) ; Book getBook() ; }
实现接口
- 不能保证是从主线程里发起的调用,因此在使用的时候,需要考虑多线程启动和保证service运行时的线程安全性。
- 默认情况,远程调用是同步的。
- Service不会返回任何开发者自己抛出的异常到调用者。
package com.hualu.servicemy; import java.util.List; import java.util.Map; import android.app.Service; import android.content.Intent; import android.os.IBinder; import android.os.Process; import android.os.RemoteException; public class RemoteService extends Service { @Override public IBinder onBind(Intent intent) { return iBinder; } private final IRemoteService.Stub iBinder = new IRemoteService.Stub() { //实现接口 @Override public int getPID() throws RemoteException { return Process.myPid(); } @Override public Book getBook() throws RemoteException { Book book = new Book() ; book.setName("心善") ; return book; } @Override public void basicString(String s) throws RemoteException { System.out.println("string = "+s); } @Override public void basicMap(Map m) throws RemoteException { System.out.println("Map size = "+m.size()); } @Override public void basicLong(long l) throws RemoteException { System.out.println("long = "+l); } @Override public void basicList(List<String> l) throws RemoteException { System.out.println("List size = "+l.size()); } @Override public void basicInt(int i) throws RemoteException { System.out.println("int = "+i); } @Override public void basicFloat(float f) throws RemoteException { System.out.println("float = "+f); } @Override public void basicDouble(double d) throws RemoteException { System.out.println("double = "+d); } @Override public void basicCharSequence(char c) throws RemoteException { System.out.println("char = "+c); } @Override public void basicByte(byte b) throws RemoteException { } @Override public void basicBoolean(boolean b) throws RemoteException { } }; }
公开接口
package com.hualu.servicemy; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; 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.view.View.OnClickListener; import com.hualu.serviceexample.R; public class RemoteActivity extends Activity { private IRemoteService remoteService ; private boolean bindFlag = false ; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.remote_service) ; findViewById(R.id.remote).setOnClickListener(l) ; } private OnClickListener l = new OnClickListener(){ @Override public void onClick(View v) { if(remoteService != null){ try { remoteService.basicByte((byte)4) ; remoteService.basicBoolean(true) ; remoteService.basicInt(132) ; remoteService.basicLong(146) ; remoteService.basicFloat(83646.3f) ; remoteService.basicDouble(2.12) ; remoteService.basicString("remoteService") ; remoteService.basicCharSequence('r') ; List<String> l = new ArrayList<String>() ; l.add("Remote") ; l.add("Service") ; remoteService.basicList(l) ; Map<String,String> m = new HashMap<String,String>(); m.put("a", "a") ; remoteService.basicMap(m) ; Book b = remoteService.getBook() ; System.out.println(b.getName()); } catch (RemoteException e) { e.printStackTrace(); } } } } ; @Override protected void onStart() { super.onStart(); binderService() ; } @Override protected void onStop() { super.onStop(); unBindService() ; remoteService = null ; } private ServiceConnection conn = new ServiceConnection(){ //公开接口 @Override public void onServiceConnected(ComponentName name, IBinder service) { remoteService = IRemoteService.Stub.asInterface(service) ; bindFlag = true ; } @Override public void onServiceDisconnected(ComponentName name) { remoteService = null ; bindFlag = false ; } } ; private void binderService(){ bindService(new Intent(RemoteService.class.getName()), conn, Context.BIND_AUTO_CREATE) ; } private void unBindService(){ unbindService(conn) ; bindFlag = false ; conn = null ; } }
在aidl文件传递对象:
- 创建实现Parcelable接口的类。
- 实现
writeToParcel
, 将对象目前的状态写到Pacel中。 - 增加一个名字为CREATOR的静态的成员变量,这个CREATOR实现了Parcelable.Creator接口。
- 最终,创建一个.aidl文件,声明你的parcelable类。
package com.hualu.servicemy; parcelable Book ;
Book.java
package com.hualu.servicemy; import android.os.Parcel; import android.os.Parcelable; public class Book implements Parcelable { private String name ; @Override public int describeContents() { return 0; } public Book(){} private Book(Parcel in) { readFromParcel(in); } @Override public void writeToParcel(Parcel dest, int flags) { dest.writeString(name) ; } public void readFromParcel(Parcel in){ name = in.readString() ; } public final static Parcelable.Creator<Book> CREATOR = new Parcelable.Creator<Book>(){ @Override public Book createFromParcel(Parcel source) { return new Book(source); } @Override public Book[] newArray(int size) { return new Book[size]; } } ; public void setName(String name){ this.name = name ; } public String getName(){ return this.name ; } }
Layout文件:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center" android:orientation="vertical" > <Button android:id="@+id/remote" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/get_remote_data" /> <TextView android:id="@+id/textView1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/remote_service" /> </LinearLayout>
Manifest文件中定义的Activity和service:
<activity android:name="com.hualu.servicemy.RemoteActivity"> <intent-filter> <action android:name="android.intent.action.MAIN"></action> <category android:name="android.intent.category.LAUNCHER"></category> </intent-filter> </activity> <service android:name="com.hualu.servicemy.RemoteService"> <intent-filter > <action android:name="com.hualu.servicemy.RemoteService"/> </intent-filter> </service>
运行结果:
公开接口