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>
运行结果:
公开接口