简单实现 AIDL(进程间通信)
aidl应用场景,因为安卓不同的应用运行在不同的进程,不能共享内存。当一个项目实现某一部分功能时依赖于另一个项目时候我们就可以用aidl来实现。
下面实现一个模拟远程的登陆操作,登陆成功返回用户信息,登陆失败返回错误信息。
正确的用户名:user,密码:123456
实现方式:
先建立客户端或者服务端都可以,但是两个AIDL文件的包名等必须完全一致。
1、客户端:
建立.aidl文件,文件目录如下:
文件内容如下:
// ILoginInterface.aidl package com.demo.jinjin.aidlclient; // Declare any non-default types here with import statements interface ILoginInterface { /** * Demonstrates some basic types that you can use as parameters * and return values in AIDL. */ void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString); String login(String user,String pwd); }此时编译项目,即可在generated目录下生成相应的java文件,目录如下:
打开文件,可看到文件内容如下:
/* * This file is auto-generated. DO NOT MODIFY. * Original file: E:\\MyBase\\AIDLClient\\app\\src\\main\\aidl\\com\\demo\\jinjin\\aidlclient\\ILoginInterface.aidl */ package com.demo.jinjin.aidlclient; // Declare any non-default types here with import statements public interface ILoginInterface extends android.os.IInterface { /** Local-side IPC implementation stub class. */ public static abstract class Stub extends android.os.Binder implements com.demo.jinjin.aidlclient.ILoginInterface { private static final java.lang.String DESCRIPTOR = "com.demo.jinjin.aidlclient.ILoginInterface"; /** Construct the stub at attach it to the interface. */ public Stub() { this.attachInterface(this, DESCRIPTOR); } /** * Cast an IBinder object into an com.demo.jinjin.aidlclient.ILoginInterface interface, * generating a proxy if needed. */ public static com.demo.jinjin.aidlclient.ILoginInterface asInterface(android.os.IBinder obj) { if ((obj==null)) { return null; } android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR); if (((iin!=null)&&(iin instanceof com.demo.jinjin.aidlclient.ILoginInterface))) { return ((com.demo.jinjin.aidlclient.ILoginInterface)iin); } return new com.demo.jinjin.aidlclient.ILoginInterface.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_basicTypes: { data.enforceInterface(DESCRIPTOR); int _arg0; _arg0 = data.readInt(); long _arg1; _arg1 = data.readLong(); boolean _arg2; _arg2 = (0!=data.readInt()); float _arg3; _arg3 = data.readFloat(); double _arg4; _arg4 = data.readDouble(); java.lang.String _arg5; _arg5 = data.readString(); this.basicTypes(_arg0, _arg1, _arg2, _arg3, _arg4, _arg5); reply.writeNoException(); return true; } case TRANSACTION_login: { data.enforceInterface(DESCRIPTOR); java.lang.String _arg0; _arg0 = data.readString(); java.lang.String _arg1; _arg1 = data.readString(); java.lang.String _result = this.login(_arg0, _arg1); reply.writeNoException(); reply.writeString(_result); return true; } } return super.onTransact(code, data, reply, flags); } private static class Proxy implements com.demo.jinjin.aidlclient.ILoginInterface { 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; } /** * Demonstrates some basic types that you can use as parameters * and return values in AIDL. */ @Override public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, java.lang.String aString) throws android.os.RemoteException { android.os.Parcel _data = android.os.Parcel.obtain(); android.os.Parcel _reply = android.os.Parcel.obtain(); try { _data.writeInterfaceToken(DESCRIPTOR); _data.writeInt(anInt); _data.writeLong(aLong); _data.writeInt(((aBoolean)?(1):(0))); _data.writeFloat(aFloat); _data.writeDouble(aDouble); _data.writeString(aString); mRemote.transact(Stub.TRANSACTION_basicTypes, _data, _reply, 0); _reply.readException(); } finally { _reply.recycle(); _data.recycle(); } } @Override public java.lang.String login(java.lang.String user, java.lang.String pwd) throws android.os.RemoteException { android.os.Parcel _data = android.os.Parcel.obtain(); android.os.Parcel _reply = android.os.Parcel.obtain(); java.lang.String _result; try { _data.writeInterfaceToken(DESCRIPTOR); _data.writeString(user); _data.writeString(pwd); mRemote.transact(Stub.TRANSACTION_login, _data, _reply, 0); _reply.readException(); _result = _reply.readString(); } finally { _reply.recycle(); _data.recycle(); } return _result; } } static final int TRANSACTION_basicTypes = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0); static final int TRANSACTION_login = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1); } /** * Demonstrates some basic types that you can use as parameters * and return values in AIDL. */ public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, java.lang.String aString) throws android.os.RemoteException; public java.lang.String login(java.lang.String user, java.lang.String pwd) throws android.os.RemoteException; }这个文件内容我们不许要做过多的关注。
下面进行远程服务的绑定:
private ILoginInterface iLoginInterface; private ServiceConnection connection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { iLoginInterface = ILoginInterface.Stub.asInterface(service); LoginPresenter presenter = new LoginPresenter(MainActivity.this); presenter.login(iLoginInterface); unbindService(connection); } @Override public void onServiceDisconnected(ComponentName name) { connection = null; } };
bindService( new Intent("com.demo.jinjin.aidlserver"),connection, Context.BIND_AUTO_CREATE);绑定成功之后进行登陆操作,登陆操作完成之后记得解绑,注意此处的intent的action与服务端service注册的action要保持一致。
这块采用的是MVP的模式,所以登陆的具体方法在model中,通过presenter实现调度。
presenter如下:
public void login(ILoginInterface iLoginInterface){ LoginModel loginModel = new LoginModel(); try { loginModel.lolgin(iLoginView.getUser(), iLoginView.getPwd(),iLoginInterface, new OnLoginFinish() { @Override public void loginSuccess(User user) { iLoginView.showSnackBar(user.getUser()); } @Override public void loginFailed(String error) { iLoginView.showSnackBar(error); } }); } catch (RemoteException e) { e.printStackTrace(); } catch (JSONException e) { e.printStackTrace(); } }model如下:
@Override public void lolgin(String user, String pwd, ILoginInterface iLoginInterface, OnLoginFinish onLoginFinish) throws RemoteException, JSONException { String result = iLoginInterface.login(user,pwd); Log.e("test","---------->" + result); JSONObject object = new JSONObject(result); if (100 ==object.getInt("result_code")){ JSONObject object1 = object.getJSONObject("result_info"); User user1 = new User(); user1.setUser(object1.getString("user")); user1.setPwd(object1.getString("pwd")); onLoginFinish.loginSuccess(user1); }else { onLoginFinish.loginFailed("用户名,密码错误"); } }即可实现远程的登陆操作。
2、服务端实现:
将客户端的aidl目录整体拷贝到服务端,如下:
之后对代码进行编译,生成相应的java目录:
下面进行远程service的定义,如下:
package com.demo.jinjin.aidlserver; import android.app.Service; import android.content.Intent; import android.os.IBinder; import android.os.RemoteException; import android.support.annotation.Nullable; import android.util.Log; import com.demo.jinjin.aidlclient.ILoginInterface; import org.json.JSONException; import org.json.JSONObject; /** * Created by linkmax on 2016/8/2. */ public class LoginService extends Service { private static final String TAG = "AIDLService"; private void Log(String str){ Log.e(TAG,"----------" + str + "----------"); } public void onCreate(){ Log.e(TAG,"service created"); } public void onStart(Intent intent, int startId){ Log.e(TAG,"service started id = " + startId); } @Nullable @Override public IBinder onBind(Intent t){ Log.e(TAG,"service on bind"); return mBinder; } public void onDestroy(){ Log.e(TAG,"service on destroy"); super.onDestroy(); } public boolean onUnbind(Intent intent){ Log.e(TAG,"service on unbind"); return super.onUnbind(intent); } public void onRebind(Intent intent){ Log.e(TAG,"service on rebind"); super.onRebind(intent); } private final ILoginInterface.Stub mBinder = new ILoginInterface.Stub() { @Override public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) throws RemoteException { } @Override public String login(String user, String pwd) throws RemoteException { if ("user".equals(user) && "123456".equals(pwd)){ JSONObject object = new JSONObject(); try { JSONObject object1 = new JSONObject(); object1.put("user","server_user"); object1.put("pwd","server_123456"); object.put("result_code",100); object.put("result_info",object1); } catch (JSONException e) { e.printStackTrace(); } return object.toString(); }else { JSONObject object = new JSONObject(); try { JSONObject object1 = new JSONObject(); object1.put("user","server_error"); object1.put("pwd","server_error"); object.put("result_code",200); object.put("result_info",object1); } catch (JSONException e) { e.printStackTrace(); } return object.toString(); } } }; }最后进行远程service的注册, 如下:
<service android:name=".LoginService"> <intent-filter> <action android:name="com.demo.jinjin.aidlserver"/> </intent-filter> </service>注意,两边的action需要保持一致。
此时启动客户端与服务端即可实现远程的登陆操作。
源码下载:源码