AIDL用于进程间通信,进程一般指一个执行单元,简单理解的话就是一个应用程序。这样进程间通信就可以分为两种,一种是两个APP之间进行通信,另一种是一个APP的不同进程之间进行通信。下面总结一下今天自己实现的前一种的实现步骤。
首先,第一步,新建一个服务端应用工程,在java包下面新建需要跨进程通信的传输数据的Java类,将该类进行序列化,序列化的方式采用Parcelable。如果跨进程通信的数据是AIDL所支持的数据类型,就不需要此步。
第二步,鼠标右键单击app -->new-->AIDL-->AIDL File,弹出新建对话框,输入要新建的aidl文件的名称。这时Android studio会在工程目录下自动生成和第一步Java类平级且包名一样的以aidl结尾的aidl文件。编写AIDL文件需要实现的功能。
第三步,写完AIDL文件和AIDL文件所需要的Java类后,对该应用程序进行编译。编译结束as会自动在build-->generated-->source-->aidl-->debug-->相同的包名下,生成我们在第二步定义的AIDL接口文件所对应的Java类。
第四步,代码实现服务端。
服务端的实现一般是新建一个类继承service类,为客户端提供调用的方法和数据。为客户端提供的调用方法就是前面在AIDL接口文件中定义的方法。
这时服务端就写好了
客户端实现:
第一步,新建客户端应用工程,工程建好之后,将服务端的AIDL文件夹拷贝到客户端的main目录下,因为上面服务端的AIDL文件所需要的Java类和AIDL文件不在一个文件夹,所以这块还需要把需要的Java类也从服务端拷贝到客户端的Java类的包下。
第二步,完成上述第一步的步骤之后这时应该编译一下客户端,让客户端也自己生成跨进程通信的AIDL文件所对应的Java类。
第三步,代码实现客户端。
客户端实现一般是activity,在activity里面请求服务端,并对服务端返回的数据进行相应的处理。
客户端实现主要是通过ServiceConnection对象中的onServiceConnected()方法中的IBinder service参数返回AIDL接口文件所对应的Java类中的实现android.os.IInterface接口的实现接口的接口实现对象来实现对服务端方法和数据的获取和调用等。
具体代码如,服务端:
AIDL文件夹下的Book.aidl 和BookManager.aidl文件
// Book.aidl.aidl package sun.example.aidls; // Declare any non-default types here with import statements parcelable Book;
// BookManager.aidl package sun.example.aidls; import sun.example.aidls.Book; // Declare any non-default types here with import statements interface BookManager { /** * Demonstrates some basic types that you can use as parameters * and return values in AIDL. */ //所有的返回值前都不需要加任何东西,不管是什么数据类型 List<Book> getBooks(); //传参时除了Java基本类型以及String,CharSequence之外的类型 //都需要在前面加上定向tag,具体加什么量需而定 void addBook(in Book book); }所需的Book.java文件
/** * Created by su on 2017/10/27. */ public class Book implements Parcelable { private String name; private int price; protected Book(Parcel in) { name = in.readString(); price = in.readInt(); } public static final Creator<Book> CREATOR = new Creator<Book>() { @Override public Book createFromParcel(Parcel in) { return new Book(in); } @Override public Book[] newArray(int size) { return new Book[size]; } }; @Override public int describeContents() { return 0; } @Override public void writeToParcel(Parcel dest, int flags) { dest.writeString(name); dest.writeInt(price); } /** * 参数是一个Parcel,用它来存储与传输数据 * @param dest */ public void readFromParcel(Parcel dest) { //注意,此处的读值顺序应当是和writeToParcel()方法中一致的 name = dest.readString(); price = dest.readInt(); } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getPrice() { return price; } public void setPrice(int price) { this.price = price; } public Book() { } @Override public String toString() { return "Book{" + "name='" + name + '\'' + ", price=" + price + '}'; } }服务端代码实现:
/** * Created by su on 2017/10/27. */ public class AIDLServer extends Service { //public final String TAG = this.getClass().getSimpleName(); private static final String TAG = "AIDLServer"; //包含Book对象的list private List<Book> mBooks = new ArrayList<>(); //由AIDL文件生成的BookManager private final BookManager.Stub mBookManager = new BookManager.Stub() { @Override public List<Book> getBooks() throws RemoteException { synchronized (this) { Log.e(TAG, "invoking getBooks() method , now the list is : " + mBooks.toString()); if (mBooks != null) { return mBooks; } return new ArrayList<>(); } } @Override public void addBook(Book book) throws RemoteException { synchronized (this) { if (mBooks == null) { mBooks = new ArrayList<>(); } if (book == null) { Log.e(TAG, "Book is null in In"); book = new Book(); } //尝试修改book的参数,主要是为了观察其到客户端的反馈 book.setPrice(2333); if (!mBooks.contains(book)) { mBooks.add(book); } //打印mBooks列表,观察客户端传过来的值 Log.e(TAG, "invoking addBooks() method , now the list is : " + mBooks.toString()); } } }; @Override public void onCreate() { super.onCreate(); Book book = new Book(); book.setName("Android开发艺术探索"); book.setPrice(28); mBooks.add(book); } @Nullable @Override public IBinder onBind(Intent intent) { Log.e(TAG, String.format("on bind,intent = %s", intent.toString())); return mBookManager; } }service在Android Manifest文件中的配置:
<service android:name=".AIDLServer" android:exported="true" android:enabled="true"> <intent-filter> <action android:name="sun.example.aidl"/> <category android:name="android.intent.category.DEFAULT"/> </intent-filter> </service>客户端代码实现:
public class AIDLActivity extends AppCompatActivity implements View.OnClickListener{ private static final String TAG = "AIDLActivity"; //由AIDL文件生成的Java类 private BookManager mBookManager = null; //标志当前与服务端连接状况的布尔值,false为未连接,true为连接中 private boolean mBound = false; //包含Book对象的list private List<Book> mBooks; private Button mButton; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_aidl); mButton = (Button) findViewById(R.id.btu_bindService); mButton.setOnClickListener(this); } /** * 按钮的点击事件,点击之后调用服务端的addBookIn方法 * * */ @Override public void onClick(View v) { //如果与服务端的连接处于未连接状态,则尝试连接 if (!mBound) { attemptToBindService(); Toast.makeText(this, "当前与服务端处于未连接状态,正在尝试重连,请稍后再试", Toast.LENGTH_SHORT).show(); return; } if (mBookManager == null) return; Book book = new Book(); book.setName("APP研发录In"); book.setPrice(30); try { mBookManager.addBook(book); Log.e(TAG, book.toString()); } catch (RemoteException e) { e.printStackTrace(); } } /** * 尝试与服务端建立连接 */ private void attemptToBindService() { Intent intent = new Intent(); intent.setAction("sun.example.aidl"); intent.setPackage("sun.example.aidls"); bindService(intent, mServiceConnection, Context.BIND_AUTO_CREATE); } @Override protected void onStart() { super.onStart(); if (!mBound) { attemptToBindService(); } } @Override protected void onStop() { super.onStop(); if (mBound) { unbindService(mServiceConnection); mBound = false; } } private ServiceConnection mServiceConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { Log.e(TAG, "service connected"); mBookManager = BookManager.Stub.asInterface(service); mBound = true; if (mBookManager != null) { try { mBooks = mBookManager.getBooks(); Log.e(TAG, "query book list, list type:" + mBooks.getClass().getCanonicalName()); Log.e(TAG, "query book list: "+mBooks.toString()); } catch (RemoteException e) { e.printStackTrace(); } } } @Override public void onServiceDisconnected(ComponentName name) { Log.e(TAG, "service disconnected"); mBound = false; } }; }