AIDL:Android接口定义语言Android Interface Definition Language (AIDL) 官方文档链接:http://developer.android.com/guide/components/aidl.html 一. 使用AIDL的步骤: 1. 新建一个interface,声明Activity需要调用Service的方法 2. 修改接口文件的扩展名为“.aidl”,点击项目,按F5刷新 3. 拷贝aidl文件到客户端项目中, 注意:aidl所在报名必须完全一致 4. Service中的Binder继承aidl文件名.Stub 5. 在Activity中的onServiceConnected()方法中, mMService = IMyService.Stub.asInterface(service); 实现了Activity所在进程对Service所在进程的方法调用 二. Activity进程调用Service进程,获取任意类型返回值 1. 自定义类型,实现Parcelable接口 提示:参照Parcelable的doc 2. 创建一个与自定义类型同名的aidl文件, 内容:parcelable 自定义类型类名 在aidl接口中就可以使用这个类型了 注意:即使在同一个包中,也要导入 import com.yuchen.aidl.Student;
下面提供一个复合型的AIDL实例
首先考虑Service模块
有两个.aidl文件
package com.aidl.service; parcelable Person;
package com.aidl.service; import com.aidl.service.Person; interface IStockQuoteService { String getQuote(in String ticker, in Person requester); }
然后是.aidl文件的实现类
public class Person implements Parcelable { private int age; private String name; public static final Parcelable.Creator<Person> CREATOR = new Creator<Person>() { @Override public Person[] newArray(int size) { // TODO Auto-generated method stub return new Person[size]; } @Override public Person createFromParcel(Parcel source) { // TODO Auto-generated method stub return new Person(source); } }; public Person(){ } public Person(Parcel in){ readFromParcel(in); } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public int describeContents() { // TODO Auto-generated method stub return 0; } @Override public void writeToParcel(Parcel out, int flags) { // TODO Auto-generated method stub out.writeInt(age); out.writeString(name); } public void readFromParcel(Parcel in) { // TODO Auto-generated method stub age = in.readInt(); name = in.readString(); } }
public class StockQuoteService extends Service { private NotificationManager notificationManager; public class StockQuoteServiceImpl extends IStockQuoteService.Stub{ @Override public String getQuote(String ticker, Person requester) throws RemoteException { // TODO Auto-generated method stub return "Hello" + requester.getName() + "! Quote for " + ticker + "is 20.0"; } } @Override public void onCreate(){ super.onCreate(); notificationManager = (NotificationManager)this.getSystemService(NOTIFICATION_SERVICE); displayNotificationMessage("onCreate() called in StockQuoteService"); } @SuppressWarnings("deprecation") private void displayNotificationMessage(String message) { // TODO Auto-generated method stub Notification notification = new Notification(R.drawable.emo_im_winking,message,System.currentTimeMillis()); PendingIntent contentIntent = PendingIntent.getActivity(this,0,new Intent(this,MainActivity.class),0); notification.setLatestEventInfo(this, "StockQuoteService", message, contentIntent); notification.flags = Notification.FLAG_NO_CLEAR; notificationManager.notify(R.id.app_notification_id, notification); } @Override public void onDestroy(){ super.onDestroy(); displayNotificationMessage("onDestroy() called in StockQuoteService"); notificationManager.cancelAll(); } @Override public IBinder onBind(Intent intent) { // TODO: Return the communication channel to the service. displayNotificationMessage("onBind() called in StockQuoteService"); return new StockQuoteServiceImpl(); } }
配置文件
<service android:name="com.aidl.service.StockQuoteService" > <intent-filter> <action android:name="com.aidl.service.IStockQuoteService" /> </intent-filter> </service>
然后就是Client模块
注意:在Client模块中,必须把在Service模块中的.aidl文件以及JavaBean类连包结构一起移到Client代码中
然后就是视图的实现了
public class MainActivity extends Activity { private static final String TAG = "StockQuoteClient"; private IStockQuoteService stockService = null; private ToggleButton bindBtn; private Button callBtn; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); bindBtn = (ToggleButton) findViewById(R.id.bindBtn); bindBtn.setOnCheckedChangeListener(new OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { // TODO Auto-generated method stub if (isChecked) { bindService(new Intent(IStockQuoteService.class.getName()), serConn, Context.BIND_AUTO_CREATE); } else { unbindService(serConn); } callBtn.setEnabled(isChecked); bindBtn.setChecked(isChecked); } }); callBtn = (Button) findViewById(R.id.callBtn); callBtn.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub callService(); } }); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); return true; } private void callService() { try { Person person = new Person(); person.setAge(22); person.setName("VIJAY"); String response = stockService.getQuote("ANDROID",person); Toast.makeText(this, "Value from service is "+response, Toast.LENGTH_SHORT).show(); } catch (RemoteException e) { // TODO Auto-generated catch block e.printStackTrace(); } } private ServiceConnection serConn = new ServiceConnection() { @Override public void onServiceDisconnected(ComponentName name) { // TODO Auto-generated method stub Log.e(TAG, "onServiceDisconnected() called"); bindBtn.setChecked(false); callBtn.setEnabled(false); stockService = null; } @Override public void onServiceConnected(ComponentName name, IBinder service) { // TODO Auto-generated method stub Log.e(TAG, "onServiceConnected() called"); stockService = IStockQuoteService.Stub.asInterface(service); bindBtn.setChecked(true); callBtn.setEnabled(true); } }; @Override protected void onDestroy() { Log.e(TAG, "onDestroy() called"); if(callBtn.isEnabled()) unbindService(serConn); super.onDestroy(); } }
这里介绍一下AIDL对非原句类型的支持
1、AIDL支持String和CharSequence
2、AIDL支持传递其他AIDL接口,但你引用的每个AIDL接口都需要一个Import语句
3、AIDL支持传递实现android.os.Parcelable接口的复杂类型。需要在AIDL文件中包含针对这些类型的import语句
4、AIDL支持java.util.List和java.util.Map,但具有一些限制。集合中的允许数据类型有Java原句、String、CharSequence以及android.os.Parcelable。无需为List或Map提供import语句,但需要为Parcelable提供import语句
5、除字符串外,非原句类型需要一个方向指示符。方向指示符包括in、out和inout