AIDL (android interface defintion language) 定义跨进程调用数据,也就是说不同进程之间的数据共享。
- AIDL 定义接口的源代码必须以.aidl结尾。
- AIDL 接口中用到的数据类型,除了基本类型、String List Map CharSequence 之外,其他类型都需要导包。
先看一下项目结构图:

接下来我们需要定义一个Book实体,属于自定义类型。
Book.java
package com.hkrt.action;
import android.os.Parcel;
import android.os.Parcelable;
public class Book implements Parcelable {
private String author;
private String bookName;
private int bookPrice;
public Book() {
}
public Book(Parcel parcel) {
author = parcel.readString();
bookName = parcel.readString();
bookPrice = parcel.readInt();
}
public String getBookName() {
return bookName;
}
public void setBookName(String bookName) {
this.bookName = bookName;
}
public int getBookPrice() {
return bookPrice;
}
public void setBookPrice(int bookPrice) {
this.bookPrice = bookPrice;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel parcel, int flags) {
parcel.writeString(author);
parcel.writeString(bookName);
parcel.writeInt(bookPrice);
}
public static final Parcelable.Creator<Book> CREATOR = new Creator<Book>() {
public Book createFromParcel(Parcel source) {
return new Book(source);
}
public Book[] newArray(int size) {
return new Book[size];
}
};
}
注:对象在跨进程访问,类必须实现 Parcelable。原文是这样说的。
Interface for classes whose instances can be written to and restored from a
Parcel
. Classes implementing the Parcelable interface must also have a static field called CREATOR
, which is an object implementing the Parcelable.Creator
interface.
然后定义一个Book.aidl 文件
parcelable Book;
接下来定义把对外提供的服务定义aidl(IaidlServerService.aidl)。
package com.hkrt.action;
import com.hkrt.action.Book;
import java.util.List;
interface IAIDLServerService {
String sayHello();
Book getBook();
List<Book> getBooks();
}
当保存这个文件时,就会在gen/<package>/生成对应的java文件。如图上所示。
然后。编写本地实现,实现这三个接口,并初始化数据。
package com.hkrt.action;
import java.util.ArrayList;
import java.util.List;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
import com.hkrt.action.IAIDLServerService.Stub;
public class AidlServerService extends Service{
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
/*** 在AIDL文件中定义的接口实现 */
private IAIDLServerService.Stub mBinder = new Stub() {
@Override
public String sayHello() throws RemoteException {
return "Hello";
}
@Override
public Book getBook() throws RemoteException {
Book mBook = new Book();
mBook.setAuthor("机器人");
mBook.setBookName("Android应用开发");
mBook.setBookPrice(50);
return mBook;
}
@Override
public List<Book> getBooks() throws RemoteException {
List<Book> books = new ArrayList<Book>();
Book book1 = new Book();
book1.setAuthor("机器人Tom");
book1.setBookName("Android adil person one");
book1.setBookPrice(501);
books.add(book1);
Book book2 = new Book();
book2.setAuthor("机器人Jom");
book2.setBookName("Android adil person two");
book2.setBookPrice(502);
books.add(book2);
Book book3 = new Book();
book3.setAuthor("机器人Jom3");
book3.setBookName("Android adil person three");
book3.setBookPrice(502);
books.add(book3);
return books;
}
};
}
需要把这个service 注册到AndroidManifest.xml下。
<service android:name="AidlServerService" android:process=":remote">
<intent-filter>
<action android:name="com.hkrt.action.IAIDLServerService"></action>
</intent-filter>
</service>
这样第一个应用就写完了,只是提供一些数据,可又被另一个进程访问。
接下来我们需要新建另外一个程序,访问第一个程序对外提供的数据。
先看一下结构图:

具中图:

是从第一个图中拷出来的。自动就会在gen下对应的java文件。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<TextView
android:id="@+id/textview"
android:layout_width="200dp"
android:layout_height="20dp"
android:text="@string/hello"
/>
<Button
android:id="@+id/button"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="调用AIDL服务"
/>
<ExpandableListView
android:id="@+id/ExpandableListView01"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
</ExpandableListView>
</LinearLayout>
效果图:
接下来,我们需要把第一个程序对外程序提供的内容展出来。
我把第一个程序对处提供的集合用树结构展示出来。
TreeViewAdapter.java 是为树结构准备的。
package com.hkrt;
import java.util.ArrayList;
import java.util.List;
import android.content.Context;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.BaseExpandableListAdapter;
import android.widget.TextView;
public class TreeViewAdapter extends BaseExpandableListAdapter {
public static final int ItemHeight = 48;// 每项的高度
public static final int PaddingLeft = 36;// 每项的高度
private int myPaddingLeft = 0;// 如果是由SuperTreeView调用,则作为子项需要往右移
static public class TreeNode {
Object parent;
List<Object> childs = new ArrayList<Object>();
}
List<TreeNode> treeNodes = new ArrayList<TreeNode>();
Context parentContext;
public TreeViewAdapter(Context view, int myPaddingLeft) {
parentContext = view;
this.myPaddingLeft = myPaddingLeft;
}
public List<TreeNode> GetTreeNode() {
return treeNodes;
}
public void UpdateTreeNode(List<TreeNode> nodes) {
treeNodes = nodes;
}
public void RemoveAll() {
treeNodes.clear();
}
public Object getChild(int groupPosition, int childPosition) {
return treeNodes.get(groupPosition).childs.get(childPosition);
}
public int getChildrenCount(int groupPosition) {
return treeNodes.get(groupPosition).childs.size();
}
static public TextView getTextView(Context context) {
AbsListView.LayoutParams lp = new AbsListView.LayoutParams(
ViewGroup.LayoutParams.FILL_PARENT, ItemHeight);
TextView textView = new TextView(context);
textView.setLayoutParams(lp);
textView.setGravity(Gravity.CENTER_VERTICAL | Gravity.LEFT);
return textView;
}
public View getChildView(int groupPosition, int childPosition,
boolean isLastChild, View convertView, ViewGroup parent) {
TextView textView = getTextView(this.parentContext);
textView.setText(getChild(groupPosition, childPosition).toString());
textView.setPadding(myPaddingLeft + PaddingLeft, 0, 0, 0);
return textView;
}
public View getGroupView(int groupPosition, boolean isExpanded,
View convertView, ViewGroup parent) {
TextView textView = getTextView(this.parentContext);
textView.setText(getGroup(groupPosition).toString());
textView.setPadding(myPaddingLeft + (PaddingLeft >> 1), 0, 0, 0);
return textView;
}
public long getChildId(int groupPosition, int childPosition) {
return childPosition;
}
public Object getGroup(int groupPosition) {
return treeNodes.get(groupPosition).parent;
}
public int getGroupCount() {
return treeNodes.size();
}
public long getGroupId(int groupPosition) {
return groupPosition;
}
public boolean isChildSelectable(int groupPosition, int childPosition) {
return true;
}
public boolean hasStableIds() {
return true;
}
}
最后主要的展示 AidlClientDemoActivity.java 代码
package com.hkrt;
import java.util.List;
import android.app.Activity;
import android.content.ComponentName;
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 android.widget.Button;
import android.widget.ExpandableListView;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.ExpandableListView.OnChildClickListener;
import com.hkrt.action.Book;
import com.hkrt.action.IAIDLServerService;
public class AidlClientDemoActivity extends Activity {
private TextView mTextView;
private Button mButton;
ExpandableListView expandableList;
TreeViewAdapter adapter;
public String[] groups ;
public String[][] child;
private IAIDLServerService mIaidlServerService = null;
private ServiceConnection mConnection = new ServiceConnection() {
public void onServiceDisconnected(ComponentName name) {
mIaidlServerService = null;
}
public void onServiceConnected(ComponentName name, IBinder service) {
mIaidlServerService = IAIDLServerService.Stub.asInterface(service);
//aidl通信
try {
String mText = "Say hello: " + mIaidlServerService.sayHello() + "\n";
mText += "作者: " + mIaidlServerService.getBook().getAuthor()+"\n";
mText += "书名: " + mIaidlServerService.getBook().getBookName()+"\n";
mText += "价格: " + mIaidlServerService.getBook().getBookPrice();
List<Book> books = mIaidlServerService.getBooks();
groups = new String[books.size()];
for(int i=0;i<books.size();i++){
groups[i]=books.get(i).getBookName();
}
child =new String[groups.length][3];
for(int j=0;j<groups.length;j++){
Book book = books.get(j);
child[j][0] = "作者: " +book.getAuthor();
child[j][1] = "书名: "+book.getBookName();
child[j][2] = "价格: "+book.getBookPrice() + "";
}
mTextView.setText(mText);
List<TreeViewAdapter.TreeNode> treeNode = adapter.GetTreeNode();
for(int i=0;i<groups.length;i++)
{
TreeViewAdapter.TreeNode node=new TreeViewAdapter.TreeNode();
node.parent=groups[i];
for(int ii=0;ii<child[i].length;ii++)
{
node.childs.add(child[i][ii]);
}
treeNode.add(node);
}
adapter.UpdateTreeNode(treeNode);
expandableList.setAdapter(adapter);
expandableList.setOnChildClickListener(new OnChildClickListener(){
@Override
public boolean onChildClick(ExpandableListView arg0, View arg1,
int parent, int children, long arg4) {
String str="parent id:"+String.valueOf(parent)+",children id:"+String.valueOf(children);
Toast.makeText(AidlClientDemoActivity.this, str, 300).show();
return false;
}
});
} catch (RemoteException e) {
e.printStackTrace();
}
}
};
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
//初始化控件
mTextView = (TextView)findViewById(R.id.textview);
mButton = (Button)findViewById(R.id.button);
expandableList=(ExpandableListView) this.findViewById(R.id.ExpandableListView01);
//增加事件响应
mButton.setOnClickListener(new OnClickListener(){
public void onClick(View v) {
Intent service = new Intent("com.hkrt.action.IAIDLServerService");
bindService(service, mConnection,BIND_AUTO_CREATE);
adapter=new TreeViewAdapter(AidlClientDemoActivity.this,TreeViewAdapter.PaddingLeft>>1);
adapter.RemoveAll();
adapter.notifyDataSetChanged();
}
});
}
}
效果图:


如果。需要传递参数,服务器端的IaidlServerService.aidl
可以定义成 String sayMe(in String str);
in 表示传入参数。
在aidl 中写注释 /**注释*/