AIDL binder实例

1.前言

本章主要参考了Binder系列9—如何使用AIDL,介绍aidl实现binder通信的主要工作

2. aidl接口文件

#IRemoteService.aidl 
interface IRemoteService {
    
    
    int getPid();
    MyData getMyData();
}

3. IRemoteService.java文件

sdk根据aidl接口文件会自动生成IRemoteService.java文件,包含了实体binder(stub类)和代理binder(proxy binder类)

package com.gityuan.appbinderdemo;
public interface IRemoteService extends android.os.IInterface {
    
    
    public static abstract class Stub extends android.os.Binder implements com.gityuan.appbinderdemo.IRemoteService {
    
    
        private static final java.lang.String DESCRIPTOR = "com.gityuan.appbinderdemo.IRemoteService";

        /**
         * Stub构造函数
         */
        public Stub() {
    
    
            this.attachInterface(this, DESCRIPTOR);
        }

        /**
         * 将IBinder 转换为IRemoteService interface
         */
        public static com.gityuan.appbinderdemo.IRemoteService asInterface(android.os.IBinder obj) {
    
    
            if ((obj == null)) {
    
    
                return null;
            }
            android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
            if (((iin != null) && (iin instanceof com.gityuan.appbinderdemo.IRemoteService))) {
    
    
                return ((com.gityuan.appbinderdemo.IRemoteService) iin);
            }
            return new com.gityuan.appbinderdemo.IRemoteService.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_getPid: {
    
    
                    data.enforceInterface(DESCRIPTOR);
                    int _result = this.getPid();
                    reply.writeNoException();
                    reply.writeInt(_result);
                    return true;
                }
                case TRANSACTION_getMyData: {
    
    
                    data.enforceInterface(DESCRIPTOR);
                    com.gityuan.appbinderdemo.MyData _result = this.getMyData();
                    reply.writeNoException();
                    if ((_result != null)) {
    
    
                        reply.writeInt(1);
                        _result.writeToParcel(reply, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
                    } else {
    
    
                        reply.writeInt(0);
                    }
                    return true;
                }
            }
            return super.onTransact(code, data, reply, flags);
        }

        private static class Proxy implements com.gityuan.appbinderdemo.IRemoteService {
    
    
            private android.os.IBinder mRemote;

            /**
             * Proxy构造函数
             */
            Proxy(android.os.IBinder remote) {
    
    
                mRemote = remote;
            }

            @Override
            public android.os.IBinder asBinder() {
    
    
                return mRemote;
            }

            public java.lang.String getInterfaceDescriptor() {
    
    
                return DESCRIPTOR;
            }

            @Override
            public int getPid() throws android.os.RemoteException {
    
    
                android.os.Parcel _data = android.os.Parcel.obtain();
                android.os.Parcel _reply = android.os.Parcel.obtain();
                int _result;
                try {
    
    
                    _data.writeInterfaceToken(DESCRIPTOR);
                    mRemote.transact(Stub.TRANSACTION_getPid, _data, _reply, 0);
                    _reply.readException();
                    _result = _reply.readInt();
                } finally {
    
    
                    _reply.recycle();
                    _data.recycle();
                }
                return _result;
            }

            @Override
            public com.gityuan.appbinderdemo.MyData getMyData() throws android.os.RemoteException {
    
    
                android.os.Parcel _data = android.os.Parcel.obtain();
                android.os.Parcel _reply = android.os.Parcel.obtain();
                com.gityuan.appbinderdemo.MyData _result;
                try {
    
    
                    _data.writeInterfaceToken(DESCRIPTOR);
                    mRemote.transact(Stub.TRANSACTION_getMyData, _data, _reply, 0);
                    _reply.readException();
                    if ((0 != _reply.readInt())) {
    
    
                        _result = com.gityuan.appbinderdemo.MyData.CREATOR.createFromParcel(_reply);
                    } else {
    
    
                        _result = null;
                    }
                } finally {
    
    
                    _reply.recycle();
                    _data.recycle();
                }
                return _result;
            }
        }

        static final int TRANSACTION_getPid = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
        static final int TRANSACTION_getMyData = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
    }

    public int getPid() throws android.os.RemoteException;

    public com.gityuan.appbinderdemo.MyData getMyData() throws android.os.RemoteException;
}
        

4. server端

本例是为了演示进程间的通信机制,故需要将Service与Activity处于不同的进程,需要在AndroidManifest.xml中,把service配置成android:process=":remote",进程也可以命名成其他的。

## RemoteService.java
public class RemoteService extends Service {
    
    
    private static final String TAG = "BinderSimple";

    MyData mMyData;

    @Override
    public void onCreate() {
    
    
        super.onCreate();
        Log.i(TAG, "[RemoteService] onCreate");
        initMyData();
    }

    @Override
    public IBinder onBind(Intent intent) {
    
    
        Log.i(TAG,"[RemoteService] onBind");
        return mBinder;
    }

    @Override
    public boolean onUnbind(Intent intent) {
    
    
        Log.i(TAG, "[RemoteService] onUnbind");
        return super.onUnbind(intent);
    }

    @Override
    public void onDestroy() {
    
    
        Log.i(TAG, "[RemoteService] onDestroy");
        super.onDestroy();
    }

    /** * 实现IRemoteService.aidl中定义的方法 */
    private final IRemoteService.Stub mBinder = new IRemoteService.Stub() {
    
    

        @Override
        public int getPid() throws RemoteException {
    
    
            Log.i(TAG,"[RemoteService] getPid()="+android.os.Process.myPid());
            return android.os.Process.myPid();
        }

        @Override
        public MyData getMyData() throws RemoteException {
    
    
            Log.i(TAG,"[RemoteService] getMyData() "+ mMyData.toString());
            return mMyData;
        }

        /**此处可用于权限拦截**/
        @Override
        public boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
    
    
            return super.onTransact(code, data, reply, flags);
        }
    };

    /** * 初始化MyData数据 **/
    private void initMyData() {
    
    
        mMyData = new MyData();
        mMyData.setData1(10);
        mMyData.setData2(20);
    }
}

5. client端

##ClientActivity.java
public class ClientActivity extends AppCompatActivity {
    
    
    private static final String TAG = "BinderSimple";

    private IRemoteService mRemoteService;

    private boolean mIsBound;
    private TextView mCallBackTv;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
    
    
        super.onCreate(savedInstanceState);
        Log.i(TAG, "[ClientActivity] onCreate");

        setContentView(R.layout.activity_main);

        mCallBackTv = (TextView) findViewById(R.id.tv_callback);
        mCallBackTv.setText(R.string.remote_service_unattached);
    }

    /**
     * 用语监控远程服务连接的状态
     */
    private ServiceConnection mConnection = new ServiceConnection() {
    
    
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
    
    

            mRemoteService = IRemoteService.Stub.asInterface(service);
            String pidInfo = null;
            try {
    
    
                MyData myData = mRemoteService.getMyData();
                pidInfo = "pid="+ mRemoteService.getPid() +
                        ", data1 = "+ myData.getData1() +
                        ", data2="+ myData.getData2();
            } catch (RemoteException e) {
    
    
                e.printStackTrace();
            }
            Log.i(TAG, "[ClientActivity] onServiceConnected  "+pidInfo);
            mCallBackTv.setText(pidInfo);
            Toast.makeText(ClientActivity.this, R.string.remote_service_connected, Toast.LENGTH_SHORT).show();
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
    
    
            Log.i(TAG, "[ClientActivity] onServiceDisconnected");
            mCallBackTv.setText(R.string.remote_service_disconnected);
            mRemoteService = null;
            Toast.makeText(ClientActivity.this, R.string.remote_service_disconnected, Toast.LENGTH_SHORT).show();
        }
    };


    public void clickHandler(View view){
    
    
        switch (view.getId()){
    
    
            case R.id.btn_bind:
                bindRemoteService();
                break;

            case R.id.btn_unbind:
                unbindRemoteService();
                break;

            case R.id.btn_kill:
                killRemoteService();
                break;
        }
    }

    /**
     * 绑定远程服务
     */
    private void bindRemoteService(){
    
    
        Log.i(TAG, "[ClientActivity] bindRemoteService");
        Intent intent = new Intent(ClientActivity.this, RemoteService.class);
        intent.setAction(IRemoteService.class.getName());
        bindService(intent, mConnection, Context.BIND_AUTO_CREATE);

        mIsBound = true;
        mCallBackTv.setText(R.string.binding);
    }

    /**
     * 解除绑定远程服务
     */
    private void unbindRemoteService(){
    
    
        if(!mIsBound){
    
    
            return;
        }
        Log.i(TAG, "[ClientActivity] unbindRemoteService ==>");
        unbindService(mConnection);
        mIsBound = false;
        mCallBackTv.setText(R.string.unbinding);
    }

    /**
     * 杀死远程服务
     */
    private void killRemoteService(){
    
    
        Log.i(TAG, "[ClientActivity] killRemoteService");
        try {
    
    
            android.os.Process.killProcess(mRemoteService.getPid());
            mCallBackTv.setText(R.string.kill_success);
        } catch (RemoteException e) {
    
    
            e.printStackTrace();
            Toast.makeText(ClientActivity.this, R.string.kill_failure, Toast.LENGTH_SHORT).show();
        }
    }
}

参考文档

Binder系列9—如何使用AIDL

猜你喜欢

转载自blog.csdn.net/jasonactions/article/details/119800705