1.在build.gradle 中
main { manifest.srcFile 'src/main/AndroidManifest.xml' java.srcDirs = ['src/main/java', 'src/main/aidl'] resources.srcDirs = ['src/main/java', 'src/main/aidl'] aidl.srcDirs = ['src/main/aidl'] res.srcDirs = ['src/main/res'] assets.srcDirs = ['src/main/assets'] }
以免创建aidl 之后程序编译的时候报找不到类 错误。
2.创建一个User.aidl
// Book.aidl package cn.mugua.com.newaidldemo; // Declare any non-default types here with import statements import cn.mugua.com.newaidldemo.User; parcelable User;系统会自动生成一个aidl文件夹
在当前文件夹下面分别创建 User.Java Book.Java IuserManager.aidl;
public class User implements Parcelable{// public int mUserId; public String mUserName; public boolean mIsmale; public Book mBook; private User(Parcel in) { mUserId = in.readInt(); mUserName = in.readString(); mIsmale = in.readInt()==1; mBook = in.readParcelable(Thread.currentThread().getContextClassLoader());//这里需要传当前线程的上下文加载器 否则会报找不到类错误 } public static final Creator<User> CREATOR = new Creator<User>() {//反序列化 @Override public User createFromParcel(Parcel in) { return new User(in); } @Override public User[] newArray(int size) { return new User[size]; } }; @Override public int describeContents() { return 0; } @Override public void writeToParcel(Parcel dest, int flags) {//序列化 dest.writeInt(mUserId); dest.writeString(mUserName); dest.writeInt(mIsmale?1:0); dest.writeParcelable(mBook,0);//这里的flag0 或者1 几乎所有时候都为0 表示是否将当前对象作为返回值 如果为1的话资源不会释放 }
扫描二维码关注公众号,回复:
1497437 查看本文章
// IUserManager.aidl package cn.mugua.com.newaidldemo; // Declare any non-default types here with import statements import cn.mugua.com.newaidldemo.User; interface IUserManager { void addUser(in User user); List<User> getUserList(); }
3.运行 或者makeProject 会在Build/generated/source/aidl/debug 下面自动生成一个
IUserManager.java
package cn.mugua.com.newaidldemo; public interface IUserManager extends android.os.IInterface { /** * Local-side IPC implementation stub class. */ public static abstract class Stub extends android.os.Binder implements cn.mugua.com.newaidldemo.IUserManager { private static final java.lang.String DESCRIPTOR = "cn.mugua.com.newaidldemo.IUserManager"; /** * Construct the stub at attach it to the interface. */ public Stub() { this.attachInterface(this, DESCRIPTOR); } /** * Cast an IBinder object into an cn.mugua.com.newaidldemo.IUserManager interface, * generating a proxy if needed. */ public static cn.mugua.com.newaidldemo.IUserManager asInterface(android.os.IBinder obj) { if ((obj == null)) { return null; } android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR); if (((iin != null) && (iin instanceof cn.mugua.com.newaidldemo.IUserManager))) { return ((cn.mugua.com.newaidldemo.IUserManager) iin); } return new cn.mugua.com.newaidldemo.IUserManager.Stub.Proxy(obj); } @Override public android.os.IBinder asBinder() { return this; } @Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException { switch (code) { case INTERFACE_TRANSACTION: { reply.writeString(DESCRIPTOR); return true; } case TRANSACTION_addUser: { data.enforceInterface(DESCRIPTOR); cn.mugua.com.newaidldemo.User _arg0; if ((0 != data.readInt())) { _arg0 = cn.mugua.com.newaidldemo.User.CREATOR.createFromParcel(data); } else { _arg0 = null; } this.addUser(_arg0); reply.writeNoException(); return true; } case TRANSACTION_getUserList: { data.enforceInterface(DESCRIPTOR); java.util.List<cn.mugua.com.newaidldemo.User> _result = this.getUserList(); reply.writeNoException(); reply.writeTypedList(_result); return true; } } return super.onTransact(code, data, reply, flags); } private static class Proxy implements cn.mugua.com.newaidldemo.IUserManager { private android.os.IBinder mRemote; Proxy(android.os.IBinder remote) { mRemote = remote; } @Override public android.os.IBinder asBinder() { return mRemote; } public java.lang.String getInterfaceDescriptor() { return DESCRIPTOR; } @Override public void addUser(cn.mugua.com.newaidldemo.User user) throws android.os.RemoteException { android.os.Parcel _data = android.os.Parcel.obtain(); android.os.Parcel _reply = android.os.Parcel.obtain(); try { _data.writeInterfaceToken(DESCRIPTOR); if ((user != null)) { _data.writeInt(1); user.writeToParcel(_data, 0); } else { _data.writeInt(0); } mRemote.transact(Stub.TRANSACTION_addUser, _data, _reply, 0); _reply.readException(); } finally { _reply.recycle(); _data.recycle(); } } @Override public java.util.List<cn.mugua.com.newaidldemo.User> getUserList() throws android.os.RemoteException { android.os.Parcel _data = android.os.Parcel.obtain(); android.os.Parcel _reply = android.os.Parcel.obtain(); java.util.List<cn.mugua.com.newaidldemo.User> _result; try { _data.writeInterfaceToken(DESCRIPTOR); mRemote.transact(Stub.TRANSACTION_getUserList, _data, _reply, 0); _reply.readException(); _result = _reply.createTypedArrayList(cn.mugua.com.newaidldemo.User.CREATOR); } finally { _reply.recycle(); _data.recycle(); } return _result; } } static final int TRANSACTION_addUser = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0); static final int TRANSACTION_getUserList = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1); } public void addUser(cn.mugua.com.newaidldemo.User user) throws android.os.RemoteException; public java.util.List<cn.mugua.com.newaidldemo.User> getUserList() throws android.os.RemoteException; }
通过这个类可以详细的了解Binder 的机制:所有在Binder中传输的接口都需要继承 IInterface 这个类声明了两个方法 就是我们在aidl 中声明的方法
同时它还给这个方法声明了两个id 用来标识 在transact 方法中到底调用的是哪个 方法 。。。后续详解
4.创建一个UserService
package cn.mugua.com.newaidldemo; import android.app.Service; import android.content.Intent; import android.os.IBinder; import android.os.RemoteException; import android.support.annotation.Nullable; import java.util.ArrayList; import java.util.List; /** * Created by diyang on 2017/12/12. */ public class UserService extends Service{ private static List<User> mUserList = new ArrayList<>(); @Nullable @Override public IBinder onBind(Intent intent) { return new UserBinder(); } public static class UserBinder extends IUserManager.Stub{ public UserBinder() { } @Override public synchronized void addUser(User user) throws RemoteException { if(!mUserList.contains(user)){ try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } mUserList.add(user); } } @Override public synchronized List<User> getUserList() throws RemoteException { try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } return mUserList; } } }
package cn.mugua.com.newaidldemo; import android.content.ComponentName; import android.content.Intent; import android.content.ServiceConnection; import android.os.Bundle; import android.os.IBinder; import android.support.v7.app.AppCompatActivity; import android.util.Log; import android.view.View; import java.util.ArrayList; import java.util.List; public class MainActivity extends AppCompatActivity implements View.OnClickListener { private ServiceConnection mConn; private IUserManager mBinder; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mConn = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { mBinder = IUserManager.Stub.asInterface(service); } @Override public void onServiceDisconnected(ComponentName name) { mBinder = null; } }; bindService(new Intent(this,UserService.class),mConn,BIND_AUTO_CREATE); findViewById(R.id.btn_addUser).setOnClickListener(this); findViewById(R.id.btn_getUsers).setOnClickListener(this); } private int id = 1; @Override public void onClick(View v) { if(mBinder == null){ return; } List<User> users = new ArrayList<>(); long time = System.currentTimeMillis(); switch (v.getId()){ case R.id.btn_addUser: try{ mBinder.addUser(new User(id,id+"",true,new Book(id,"book"+id))); id++; }catch (Exception e){ e.printStackTrace(); } break; case R.id.btn_getUsers: try{ users = mBinder.getUserList(); }catch (Exception e){ e.printStackTrace(); } break; } long current = System.currentTimeMillis(); Log.i("during_time",current-time+""); Log.i("during_time",users.toString()+""); } @Override protected void onPause() { super.onPause(); if(mConn != null) unbindService(mConn); } }
需要注意以下几点
1.这里的mBinder 不能写成是UserBinder 否则会报 不能将Proxy强转为 UserBinder 因为服务端和客户端 不同的进程的时候 Binder 是将数据封装到了Proxy中
mBinder = IUserManager.Stub.asInterface(service);
2.运行代码报错 找不到Book 类
这时候需要将
private User(Parcel in) { mUserId = in.readInt(); mUserName = in.readString(); mIsmale = in.readInt()==1; mBook = in.readParcelable(Book.class.getClassLoader()); }最后一行代码改成 Book. class .getClassLoader()
具体原因下次再研究