什么是AIDL
AIDL:Android Interface Definition Language,即Android接口定义语言。
服务端:
1、创建一个AIDL文件,实际上是一个interface,声明一个方法
2、创建一个服务,利用AIDL文件的Stub方法在服务中实例化AIDL文件,实现AIDL文件中接口中定义的方法,返回一个IBinder对象
3、当绑定服务时将这个IBinder对象返回
客户端:
1、创建一个和服务端一模一样的AIDL文件,声明同样的方法
2、绑定服务,得到服务端返回的IBinder对象
3、将IBinder对象转换为本地定义AIDL文件,实际上是一个已经实例化的AIDL对象
4、用这个AIDL对象就可以调用服务端的方法
服务端的代码:
首先在Android Studio中创建一个aidl文件,Android Studio会自动创建一个aidl的文件夹:
创建一个aidl文件 IMyAdd,其中定义个简单的加法运算:
1 // IMyAdd.aidl 2 package com.jiao.myaidl; 3 4 // Declare any non-default types here with import statements 5 6 interface IMyAdd { 7 /** 8 * Demonstrates some basic types that you can use as parameters 9 * and return values in AIDL. 10 */ 11 int add(int first,int second); 12 }
然后创建一个service
1 package com.jiao.myaidl; 2 3 import android.app.Service; 4 import android.content.Intent; 5 import android.os.Binder; 6 import android.os.IBinder; 7 import android.os.RemoteException; 8 import android.support.annotation.Nullable; 9 10 /** 11 * Created by jiaocg on 2016/3/9. 12 */ 13 public class MyAddService extends Service { 14 15 16 public MyAddService() { 17 } 18 19 20 private Binder mBinder = new IMyAdd.Stub() { 21 @Override 22 public int add(int first, int second) throws RemoteException { 23 return first + second; 24 } 25 }; 26 27 @Nullable 28 @Override 29 public IBinder onBind(Intent intent) { 30 return mBinder; 31 } 32 }
在清单文件中注册service
1 <service android:name="com.jiao.myaidl.MyAddService"> 2 <intent-filter> 3 <action android:name="com.jiao.myaidl.action.MYADD_SERVICE" /> 4 5 <category android:name="android.intent.category.DEFAULT" /> 6 </intent-filter> 7 </service>
客户端代码
和服务端一样首先创建同样的aidl文件,并且声明同样的方法(注意,一定要在同一个包名下)
创建aidl文件:
1 // IMyAdd.aidl 2 package com.jiao.myaidl; 3 4 // Declare any non-default types here with import statements 5 6 interface IMyAdd { 7 /** 8 * Demonstrates some basic types that you can use as parameters 9 * and return values in AIDL. 10 */ 11 int add(int first,int second); 12 }
客户端调用代码:
1 package com.jiao.myaidl; 2 3 import android.content.ComponentName; 4 import android.content.Context; 5 import android.content.Intent; 6 import android.content.ServiceConnection; 7 import android.os.Bundle; 8 import android.os.IBinder; 9 import android.os.RemoteException; 10 import android.support.v7.app.AppCompatActivity; 11 import android.view.View; 12 import android.widget.Button; 13 import android.widget.Toast; 14 15 import com.jiao.myaidl.client.R; 16 17 public class MainActivity extends AppCompatActivity implements View.OnClickListener { 18 19 private boolean mIsBindService; 20 private IMyAdd mIMyAdd; 21 private ServiceConnection mConnection = new ServiceConnection() { 22 @Override 23 public void onServiceConnected(ComponentName name, IBinder service) { 24 25 Toast.makeText(MainActivity.this, "绑定服务成功", Toast.LENGTH_SHORT).show(); 26 mIMyAdd = IMyAdd.Stub.asInterface(service); 27 } 28 29 @Override 30 public void onServiceDisconnected(ComponentName name) { 31 32 bindService(); 33 } 34 }; 35 private Button bt_aidl_add; 36 private Button bt_aidl_bind; 37 private Button bt_aidl_unbind; 38 39 @Override 40 protected void onCreate(Bundle savedInstanceState) { 41 super.onCreate(savedInstanceState); 42 setContentView(R.layout.activity_main); 43 44 initView(); 45 46 } 47 48 private void initView() { 49 50 bt_aidl_bind = (Button) findViewById(R.id.bt_aidl_bind); 51 bt_aidl_unbind = (Button) findViewById(R.id.bt_aidl_unbind); 52 bt_aidl_add = (Button) findViewById(R.id.bt_aidl_add); 53 bt_aidl_add.setOnClickListener(this); 54 bt_aidl_bind.setOnClickListener(this); 55 bt_aidl_unbind.setOnClickListener(this); 56 } 57 58 59 //绑定服务 60 private void bindService() { 61 Intent intent = new Intent(); 62 intent.setAction("com.jiao.myaidl.action.MYADD_SERVICE"); 63 bindService(intent, mConnection, Context.BIND_AUTO_CREATE); 64 mIsBindService = true; 65 } 66 67 68 //解绑服务 69 private void unbindService() { 70 71 if (mIsBindService) { 72 mIsBindService = false; 73 unbindService(mConnection); 74 } 75 } 76 77 78 @Override 79 public void onClick(View v) { 80 switch (v.getId()) { 81 case R.id.bt_aidl_bind: 82 83 bindService(); 84 85 break; 86 case R.id.bt_aidl_unbind: 87 Toast.makeText(this, "解绑成功", Toast.LENGTH_SHORT).show(); 88 unbindService(); 89 break; 90 case R.id.bt_aidl_add: 91 92 if (mIsBindService && mIMyAdd != null) { 93 try { 94 int result = mIMyAdd.add(5, 5); 95 96 Toast.makeText(this, result + "", Toast.LENGTH_SHORT).show(); 97 } catch (RemoteException e) { 98 e.printStackTrace(); 99 } 100 101 } else { 102 Toast.makeText(this,"没有绑定服务", Toast.LENGTH_SHORT).show(); 103 } 104 105 break; 106 } 107 } 108 109 }
布局代码:
1 <?xml version="1.0" encoding="utf-8"?> 2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 3 android:layout_width="match_parent" 4 android:layout_height="match_parent" 5 android:orientation="vertical"> 6 7 8 <Button 9 android:layout_marginTop="50dp" 10 android:id="@+id/bt_aidl_bind" 11 android:layout_width="match_parent" 12 android:layout_height="wrap_content" 13 android:text="绑定服务" /> 14 15 <Button 16 android:id="@+id/bt_aidl_unbind" 17 android:layout_width="match_parent" 18 android:layout_height="wrap_content" 19 android:text="解绑服务" /> 20 21 <Button 22 android:id="@+id/bt_aidl_add" 23 android:layout_width="match_parent" 24 android:layout_height="wrap_content" 25 android:text="AIDL测试" /> 26 </LinearLayout>
上述步骤完成之后,将两个工程同时运行,即可测试客户端能否调用服务端的方法
二 AIDL的高级应用
上个例子是用来说明客户端通过绑定服务的方式来调用服务端的方法,下面再介绍一种客户端用来获取
服务端的对象和数据,实现服务端和客户端的数据共享;
步骤和第一个例子的步骤是一样的,首先要创建一个对象类,我们设为 Computer
创建一个computer AIDL文件来声明这个对象:
服务端代码:
1 // Computer.aidl 2 package com.jiao.myaidl.entity; 3 4 // Declare any non-default types here with import statements 5 6 parcelable Computer;
然后创建Computer对象类
1 package com.jiao.myaidl.entity; 2 3 import android.os.Parcel; 4 import android.os.Parcelable; 5 6 /** 7 * Created by jiaocg on 2016/3/9. 8 */ 9 public class Computer implements Parcelable { 10 11 12 public int computerId; 13 public String name; 14 public String model; 15 16 public Computer(int computerId, String name, String model) { 17 18 this.computerId = computerId; 19 this.name = name; 20 this.model = model; 21 } 22 23 24 protected Computer(Parcel in) { 25 computerId = in.readInt(); 26 name = in.readString(); 27 model = in.readString(); 28 } 29 30 public static final Creator<Computer> CREATOR = new Creator<Computer>() { 31 @Override 32 public Computer createFromParcel(Parcel in) { 33 return new Computer(in); 34 } 35 36 @Override 37 public Computer[] newArray(int size) { 38 return new Computer[size]; 39 } 40 }; 41 42 @Override 43 public int describeContents() { 44 return 0; 45 } 46 47 @Override 48 public void writeToParcel(Parcel dest, int flags) { 49 dest.writeInt(computerId); 50 dest.writeString(name); 51 dest.writeString(model); 52 } 53 }
这里要特别注意创建的ComputerAIDL文件和Computer对象类 要在同一个包里:
如下图所示:
然后创建一个IComputerManager aidl文件,其中声明两个方法:
添加对象和获取所有对象
1 // IComputerManager.aidl 2 package com.jiao.myaidl; 3 4 // Declare any non-default types here with import statements 5 import com.jiao.myaidl.entity.Computer; 6 interface IComputerManager { 7 void addComputer(in Computer computer); 8 List<Computer> getComputerList(); 9 }
创建一个ComputerService
1 package com.jiao.myaidl; 2 3 import android.app.Service; 4 import android.content.Intent; 5 import android.os.IBinder; 6 import android.os.RemoteException; 7 8 import com.jiao.myaidl.entity.Computer; 9 10 import java.util.List; 11 import java.util.concurrent.CopyOnWriteArrayList; 12 13 public class ComputerService extends Service { 14 public ComputerService() { 15 } 16 17 18 private CopyOnWriteArrayList<Computer> mComputerList = new CopyOnWriteArrayList<>(); 19 20 private final IComputerManager.Stub mBinder = new IComputerManager.Stub() { 21 22 23 @Override 24 public void addComputer(Computer computer) throws RemoteException { 25 26 27 mComputerList.add(computer); 28 } 29 30 @Override 31 public List<Computer> getComputerList() throws RemoteException { 32 return mComputerList; 33 } 34 }; 35 36 37 @Override 38 public void onCreate() { 39 super.onCreate(); 40 mComputerList.add(new Computer(0, "苹果", "model1")); 41 mComputerList.add(new Computer(1, "联想", "model2")); 42 mComputerList.add(new Computer(2, "华为", "model3")); 43 } 44 45 @Override 46 public IBinder onBind(Intent intent) { 47 // TODO: Return the communication channel to the service. 48 // throw new UnsupportedOperationException("Not yet implemented"); 49 return mBinder; 50 } 51 }
清单文件声明服务:
1 <service android:name="com.jiao.myaidl.ComputerService"> 2 <intent-filter> 3 <action android:name="com.jiao.myaidl.action.COMPUTER_SERVICE" /> 4 5 <category android:name="android.intent.category.DEFAULT" /> 6 </intent-filter> 7 8 </service>
客户端代码:
首先和服务端一样要创建同样的Computer AIDL文件和Computer对象 并且包名要一致
(即客户端 Computer aidl文件的包名和Computer对象的包名要一致 同时 也要和服务器存放computer的包名一致)
创建Computer AIDL文件
1 // Computer.aidl 2 package com.jiao.myaidl.entity; 3 4 // Declare any non-default types here with import statements 5 6 7 /** 8 * Demonstrates some basic types that you can use as parameters 9 * and return values in AIDL. 10 */ 11 parcelable Computer;
创建Computer对象
1 package com.jiao.myaidl.entity; 2 3 import android.os.Parcel; 4 import android.os.Parcelable; 5 6 /** 7 * Created by jiaocg on 2016/3/10. 8 */ 9 10 public class Computer implements Parcelable { 11 12 13 public int computerId; 14 public String name; 15 public String model; 16 17 public Computer(int computerId, String name, String model) { 18 19 this.computerId = computerId; 20 this.name = name; 21 this.model = model; 22 } 23 24 25 protected Computer(Parcel in) { 26 computerId = in.readInt(); 27 name = in.readString(); 28 model = in.readString(); 29 } 30 31 public static final Creator<Computer> CREATOR = new Creator<Computer>() { 32 @Override 33 public Computer createFromParcel(Parcel in) { 34 return new Computer(in); 35 } 36 37 @Override 38 public Computer[] newArray(int size) { 39 return new Computer[size]; 40 } 41 }; 42 43 @Override 44 public int describeContents() { 45 return 0; 46 } 47 48 @Override 49 public void writeToParcel(Parcel dest, int flags) { 50 dest.writeInt(computerId); 51 dest.writeString(name); 52 dest.writeString(model); 53 } 54 }
客户调用代码
1 package com.jiao.myaidl; 2 3 import android.content.ComponentName; 4 import android.content.Context; 5 import android.content.Intent; 6 import android.content.ServiceConnection; 7 import android.os.Bundle; 8 import android.os.IBinder; 9 import android.os.RemoteException; 10 import android.support.v7.app.AppCompatActivity; 11 import android.view.View; 12 import android.widget.Button; 13 import android.widget.Toast; 14 15 import com.google.android.gms.appindexing.AppIndex; 16 import com.google.android.gms.common.api.GoogleApiClient; 17 import com.jiao.myaidl.client.R; 18 import com.jiao.myaidl.entity.Computer; 19 20 import java.util.List; 21 22 public class Main2Activity extends AppCompatActivity implements View.OnClickListener { 23 24 private boolean mIsBindService;//是否绑定了服务 25 private IComputerManager mRemoteComputerManager; 26 private Button bt_aidl_add; 27 private Button bt_aidl_bind; 28 private Button bt_aidl_unbind; 29 30 31 //在IBinder代表的进程退出时被调用 IBinder死亡时调用 32 //自定义的死亡通知接受者必须要重写父类DeathRecipient的成员函数binderDied。 33 // 当Binder驱动程序通知一个Binder代理对象它所引用的Binder本地对象已经死亡时, 34 // 就会调用它所指定的死亡通知接受者的成员函数binderDied。 35 private IBinder.DeathRecipient mDeathRecipient = new IBinder.DeathRecipient() { 36 37 @Override 38 public void binderDied() { 39 40 if (mRemoteComputerManager != null) { 41 mRemoteComputerManager.asBinder().unlinkToDeath(mDeathRecipient, 0); 42 mRemoteComputerManager = null; 43 bindService(); 44 45 } 46 } 47 }; 48 49 50 private ServiceConnection mConnection = new ServiceConnection() { 51 @Override 52 public void onServiceConnected(ComponentName name, IBinder service) { 53 54 mIsBindService = true; 55 Toast.makeText(Main2Activity.this, "绑定服务成功", Toast.LENGTH_SHORT).show(); 56 mRemoteComputerManager = IComputerManager.Stub.asInterface(service); 57 58 try { 59 //注册 IBinder 死亡通知 60 mRemoteComputerManager.asBinder().linkToDeath(mDeathRecipient, 0); 61 } catch (RemoteException e) { 62 e.printStackTrace(); 63 } 64 } 65 66 @Override 67 public void onServiceDisconnected(ComponentName name) { 68 69 mRemoteComputerManager = null; 70 } 71 }; 72 /** 73 * ATTENTION: This was auto-generated to implement the App Indexing API. 74 * See https://g.co/AppIndexing/AndroidStudio for more information. 75 */ 76 private GoogleApiClient client; 77 78 79 @Override 80 protected void onCreate(Bundle savedInstanceState) { 81 super.onCreate(savedInstanceState); 82 setContentView(R.layout.activity_main2); 83 84 initView(); 85 // ATTENTION: This was auto-generated to implement the App Indexing API. 86 // See https://g.co/AppIndexing/AndroidStudio for more information. 87 client = new GoogleApiClient.Builder(this).addApi(AppIndex.API).build(); 88 } 89 90 91 private void initView() { 92 93 bt_aidl_bind = (Button) findViewById(R.id.bt_aidl_bind); 94 bt_aidl_unbind = (Button) findViewById(R.id.bt_aidl_unbind); 95 bt_aidl_add = (Button) findViewById(R.id.bt_aidl_add); 96 bt_aidl_add.setOnClickListener(this); 97 bt_aidl_bind.setOnClickListener(this); 98 bt_aidl_unbind.setOnClickListener(this); 99 } 100 101 102 @Override 103 public void onClick(View v) { 104 switch (v.getId()) { 105 case R.id.bt_aidl_bind: 106 107 bindService(); 108 109 break; 110 case R.id.bt_aidl_unbind: 111 Toast.makeText(this, "解绑成功", Toast.LENGTH_SHORT).show(); 112 unbindService(); 113 break; 114 case R.id.bt_aidl_add: 115 116 if (!mIsBindService || mRemoteComputerManager == null){ 117 Toast.makeText(this,"not bind service",Toast.LENGTH_SHORT).show(); 118 return; 119 } 120 try { 121 List<Computer> computerList = mRemoteComputerManager.getComputerList(); 122 for (int i =0;i<computerList.size();i++){ 123 String str = "computerId:" + String.valueOf(computerList.get(i).computerId) + 124 " brand:" + computerList.get(i).name + 125 " model:" + computerList.get(i).model ; 126 127 System.out.println(str); 128 } 129 } catch (RemoteException e) { 130 e.printStackTrace(); 131 } 132 133 break; 134 } 135 } 136 137 138 private void bindService() { 139 140 Intent it = new Intent(); 141 it.setAction("com.jiao.myaidl.action.COMPUTER_SERVICE"); 142 it.setPackage("com.jiao.myaidl.server"); 143 mIsBindService = bindService(it, mConnection, Context.BIND_AUTO_CREATE); 144 145 } 146 147 private void unbindService() { 148 149 if (!mIsBindService) { 150 return; 151 } 152 mIsBindService = false; 153 unbindService(mConnection); 154 } 155 156 157 }
以上就实现了客户端从服务器获取对象,并使用对象,实现了服务端和客户端的数据共享。