android 之 AIDL

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文件。

我们先定义一下main.xml中的布局文件如下。
<?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 中写注释     /**注释*/

原文地址:https://www.cnblogs.com/java20130726/p/3218335.html