Android进程间通讯AIDL详解
1. 什么是AIDL?
AIDL (Android Interface Definition Language) 是一种IDL 语言,用于生成可以在Android设备上两个进程之间进行进程间通信(interprocess communication, IPC)的代码。如果在一个进程中(例如Activity)要调用另一个进程中(例如Service)对象的操作,就可以使用AIDL生成可序列化的参数。
AIDL IPC机制是面向接口的,像COM或Corba一样,但是更加轻量级。它是使用代理类在客户端和实现端传递数据。
官方文档特别提醒我们何时使用AIDL是必要的:只有你允许客户端从不同的应用程序为了进程间的通信而去访问你的service,以及想在你的service处理多线程。如果不需要进行不同应用程序间的并发通信(IPC),you should create your interface by implementing a Binder;或者你想进行IPC,但不需要处理多线程的,则implementyour interface using a Messenger。无论如何,在使用AIDL前,必须要理解如何绑定service——bindService。。这里先假设你已经了解如何使用bindService。
2. 如何使用AIDL?
AIDL可用于进程间通讯,因此我创建了两个Model来进行测试,分别为服务端与客户端。
2.1 服务端
创建一个Model,MyAIDL:
进程间通讯传递数据设置为Book对象,需要使其序列化,在此实现了Parcelable接口。代码如下:
Book.java
public class Book implements Parcelable { public int bookId; public String bookName; public Book(int bookId, String bookName) { this.bookId = bookId; this.bookName = bookName; } @Override public int describeContents() { return 0; } @Override public void writeToParcel(Parcel dest, int flags) { dest.writeInt(bookId); dest.writeString(bookName); } protected Book(Parcel in) { bookId = in.readInt(); bookName = in.readString(); } public static final Creator CREATOR = new Creator() { @Override public Book createFromParcel(Parcel in) { return new Book(in); } @Override public Book[] newArray(int size) { return new Book[size]; } }; @Override public String toString() { StringBuffer sb = new StringBuffer(); sb.append("BookId="); sb.append(bookId); sb.append("; BookName="); sb.append(bookName); return sb.toString(); }}
在Book相同包名下创建AIDL文件,如图1-1:
图1-1
Book.aidl
// Book.aidlpackage com.example.myaidl.aidl;// Declare any non-default types here with import statementsparcelable Book;
IbookManager.aidl,在这里,虽然Book和IbookManager在同一个包里,但是也要加上
import com.example.myaidl.aidl.Book;
// IBookManager.aidlpackage com.example.myaidl.aidl;import com.example.myaidl.aidl.Book;// Declare any non-default types here with import statementsinterface IBookManager { /** * Demonstrates some basic types that you can use as parameters * and return values in AIDL. */ List getBookList(); void addBook(in Book book);}
AIDL是为进程间通讯实现接口,可以通过Service来实现接口并在其它进程中调用,代码如下:
MyService.java
public class MyService extends Service { private List mList = new ArrayList(); private BookBind bind = null; @Override public void onCreate() { super.onCreate(); bind = new BookBind(); mList.add(new Book(1, "onew")); mList.add(new Book(2, "two")); Log.i("ProgressName", getClass().getSimpleName()+"--------"+MainActivity.getCurProcessName(this)); log("创建服务成功!"); } @Nullable @Override public IBinder onBind(Intent intent) { log("绑定服务成功!"); return bind; } public class BookBind extends IBookManager.Stub { @Override public List getBookList() throws RemoteException { return mList; } @Override public void addBook(Book book) throws RemoteException { mList.add(book); log(mList.toString()); } } private void log(String str) { Log.i("AIDL:" + getClass().getSimpleName(), "---------" + str); }}
不要忘了在AndroidMainfest中进行配置
2.2客户端
与服务端相比,客户端更加简单,只需要将服务端的AIDL文件与Book.java文件复制过来,放在Model里面即可,不过这里的包名必须和服务端的包名完全相同,否则会报找不到的异常。下面用代码实现它:
MainActivity.java
package com.example.aidlclient.Activity;import android.app.Activity;import android.content.ComponentName;import android.content.Intent;import android.content.ServiceConnection;import android.os.IBinder;import android.os.Bundle;import android.view.View;import android.widget.ArrayAdapter;import android.widget.Button;import android.widget.EditText;import android.widget.ListView;import android.widget.Toast;import com.example.aidlclient.R;import com.example.myaidl.aidl.Book;import com.example.myaidl.aidl.IBookManager;import java.util.ArrayList;import java.util.List;public class MainActivity extends Activity implements View.OnClickListener { private EditText et_id; private EditText et_name; private Button bt_add; private Button bt_refresh; private ListView lv_contenxt; private List mData = new ArrayList(); private ArrayAdapter adapter; private IBookManager iBookManager; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); startService(); initView(); } @Override protected void onDestroy() { super.onDestroy(); } private void initView() { et_id = (EditText) findViewById(R.id.et_id); et_name = (EditText) findViewById(R.id.et_name); bt_add = (Button) findViewById(R.id.bt_add); bt_refresh = (Button) findViewById(R.id.bt_refresh); lv_contenxt = (ListView) findViewById(R.id.lv_conent); bt_add.setOnClickListener(this); bt_refresh.setOnClickListener(this); adapter = new ArrayAdapter(this, android.R.layout.simple_list_item_1, mData); lv_contenxt.setAdapter(adapter); } private ServiceConnection connBase = new ServiceConnection() { @Override public void onServiceDisconnected(ComponentName name) { iBookManager = null; } @Override public void onServiceConnected(ComponentName name, IBinder service) { // ,获取接口 iBookManager = IBookManager.Stub.asInterface(service); } }; /** * 开始服务 */ private void startService() { if (iBookManager != null) { return; } Intent intent = new Intent(); intent.setAction("com.ryg.sayhi.MyService"); bindService(intent, connBase, BIND_AUTO_CREATE); Toast.makeText(this, "开始绑定服务", Toast.LENGTH_SHORT).show(); } /** * 停止服务 */ private void endService() { if (connBase != null) { unbindService(connBase); Toast.makeText(this, "服务解除绑定", Toast.LENGTH_SHORT).show(); } } @Override public void onClick(View v) { switch (v.getId()) { case R.id.bt_add: addDate(); break; case R.id.bt_refresh: reFresh(); break; } } private void reFresh() { if (iBookManager == null) { startService(); } else { try { mData.clear(); mData.addAll(iBookManager.getBookList()); adapter.notifyDataSetChanged(); } catch (Exception e) { e.printStackTrace(); } } } private void addDate() { if (et_id.getText().toString().length() < 1 || et_name.getText().toString().length() < 1) { Toast.makeText(this, "请录入数据!", Toast.LENGTH_LONG).show(); return; } if (iBookManager == null) { startService(); } else { try { Book book = new Book(Integer.parseInt(et_id.getText().toString()), et_name.getText().toString()); iBookManager.addBook(book); Toast.makeText(this, "录入数据成功!", Toast.LENGTH_LONG).show(); et_name.setText(""); et_id.setText(""); } catch (Exception e) { Toast.makeText(this, "录入数据失败!", Toast.LENGTH_LONG).show(); e.printStackTrace(); } } }}
XML资源文件
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
运行结果如图1-2
图1-2
更多相关文章
- AIDL 进程间通信
- android6.0源码分析之AMS服务源码分析
- Android之开源中国客户端源码分析(一)
- Android(安卓)SurfaceFlinger服务启动过程源码分析
- 打造自己的Android聊天软件(socket篇)
- Binder通信机制
- SpringSource通过Spring for Android(安卓)1.0将Spring Framewor
- [转]微信ANDROID客户端-会话速度提升70%的背后
- Binder机制总结