深入Android架构(从线程到AIDL)_20 IPC的Proxy-Stub设计模式02

2、 IBinder接口的一般用途

前言
一般用途
  • Android的IPC框架仰赖单一的IBinder接口。此时Client端调用IBinder接口的transact()函数,透过IPC机制而调用到远方(Remote)的onTransact()函数。
  • 在Java层框架里, IBinder接口实现于Binder基类,如下图:
  • myActivity调用IBinder接口,执行myBinder的onTransact()函数,可送信息给myService去播放mp3音乐,如下图:
  • myService也能送Broadcast信息给myActivity,将字符串显示于画面上:
java 复制代码
// myActivity.java
// .........
public class myActivity extends Activity implements OnClickListener {
    private final int WC = LinearLayout.LayoutParams.WRAP_CONTENT;
    private final int FP = LinearLayout.LayoutParams.FILL_PARENT;
    private Button btn, btn2, btn3;
    public TextView tv;
    private IBinder ib = null;
    private final String MY_S_EVENT = new String("com.misoo.pk01.myService.MY_S_EVENT");
    protected final IntentFilter filter=new IntentFilter(MY_S_EVENT);
    private BroadcastReceiver receiver=new myIntentReceiver();

    public void onCreate(Bundle icicle) {
        super.onCreate(icicle);
        LinearLayout layout = new LinearLayout(this);
        layout.setOrientation(LinearLayout.VERTICAL);
        btn = new Button(this); btn.setId(101); btn.setText("play");
        btn.setBackgroundResource(R.drawable.heart);
        btn.setOnClickListener(this);
        LinearLayout.LayoutParams param = new LinearLayout.LayoutParams(80, 50);
        param.topMargin = 10; layout.addView(btn, param);
        btn2 = new Button(this);
        btn2.setId(102);btn2.setText("stop");
        btn2.setBackgroundResource(R.drawable.heart);
        btn2.setOnClickListener(this);
        layout.addView(btn2, param);

        btn3 = new Button(this);
        btn3.setId(103); btn3.setText("exit");
        btn3.setBackgroundResource(R.drawable.cloud);
        btn3.setOnClickListener(this);
        layout.addView(btn3, param);
        tv = new TextView(this); tv.setText("Ready");
        LinearLayout.LayoutParams param2 = new
        LinearLayout.LayoutParams(FP, WC);
        param2.topMargin = 10;
        layout.addView(tv, param2);
        setContentView(layout);
        //---------------------------------
        registerReceiver(receiver, filter);
        //------------------------------------------------------
        bindService( new Intent("com.misoo.pk01.REMOTE_SERVICE"),mConnection, Context.BIND_AUTO_CREATE);
    }

    btn3 = new Button(this);
    btn3.setId(103); btn3.setText("exit");
    btn3.setBackgroundResource(R.drawable.cloud);
    btn3.setOnClickListener(this);
    layout.addView(btn3, param);
    tv = new TextView(this); tv.setText("Ready");
    LinearLayout.LayoutParams param2 = new
    LinearLayout.LayoutParams(FP, WC);
    param2.topMargin = 10;
    layout.addView(tv, param2);
    setContentView(layout);
    //---------------------------------
    registerReceiver(receiver, filter);
    //------------------------------------------------------
    bindService( new Intent("com.misoo.pk01.REMOTE_SERVICE"),mConnection, Context.BIND_AUTO_CREATE) );
}

private ServiceConnection mConnection =new ServiceConnection() {
    @Override 
    public void onServiceConnected(ComponentName className, IBinder ibinder) {
        ib = ibinder;
    }
    
    @Override 
    public void onServiceDisconnected(ComponentName name) { }
};

public void onClick(View v) {
    switch (v.getId()) {
        case 101: // Play Button
            Parcel data = Parcel.obtain();
            Parcel reply = Parcel.obtain();
            try { ib.transact(1, data, reply, 0);
            } catch (Exception e) { e.printStackTrace(); }
            break;
        case 102: // Stop Button
            data = Parcel.obtain(); reply = Parcel.obtain();
            try { ib.transact(2, data, reply, 0);
            } catch (Exception e) { e.printStackTrace(); }
            break;
        case 103: finish(); break;
    }
}
  • 其中的代码:
    case 101: // Play Button
    //.....
    ib.transact(1, data, reply, 0);
    case 102: // Stop Button
    // .....
    ib.transact(2, data, reply, 0);
  • 就是对<Play>和<Stop>两个功能进行"编码" 的动作。
  • 编好码之后,就将这编码值当做第1个参数传给IBinder接口的transact()函数。
  • 于是编码值就跨进程地传递到myBinder类里的onTransact()函数了。
java 复制代码
class myIntentReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        int bn = intent.getIntExtra("key",-1);
        if(bn == 0)
            tv.setText("Playing");
        else
            tv.setText("Stop.");
    }
}

// myService.java
// ........
public class myService extends Service implements Runnable {
    private IBinder mBinder = null;
    private Thread th1;
    public static Handler h;
    private MediaPlayer mPlayer = null;
    public static Context ctx;
    private final String MY_S_EVENT = new String("com.misoo.pk01.myService.MY_S_EVENT");

    @Override public void onCreate() {
        super.onCreate(); ctx = this;
        mBinder = new myBinder();
        // 诞生一个子线程及其MQ; 等待Message
        th1 = new Thread(this);
        th1.start();
    }

    @Override
    public IBinder onBind(Intent intent) { return mBinder; }
    public void run() {
        Looper.prepare();
        h = new EventHandler(Looper.myLooper());
        Looper.loop();
    }

    //---------------------------------------
    class EventHandler extends Handler {
        public EventHandler(Looper looper) { super(looper); }
        public void handleMessage(Message msg) {
            String obj = (String)msg.obj;

            if(obj.contains("play")) {
                if(mPlayer != null) return;
                //----------------------------------
                Intent in = new Intent(MY_S_EVENT);
                in.putExtra("key", 0);
                ctx.sendBroadcast(in);

                //----------------------------------
                mPlayer = MediaPlayer.create(ctx, R.raw.dreamed);
                try { mPlayer.start();
                } catch (Exception e) {
                Log.e("Play", "error: " + e.getMessage(), e);
                }
            }
            else if(obj.contains("stop")) {
                if (mPlayer != null) {
                    Intent in = new Intent(MY_S_EVENT);
                    in.putExtra("key", 1);
                    ctx.sendBroadcast(in);
                    //----------------------------------
                    mPlayer.stop(); 
                    mPlayer.release();
                    mPlayer = null;
                }
            }
        }
    }
}

// myBinder.java
// .......
public class myBinder extends Binder{
    @Override 
    public boolean onTransact( int code, Parcel data, Parcel reply, int flags) throws android.os.RemoteException {
        switch( code ){
            case 1:
                // 将Message丢到子线程的MQ to play MP3
                String obj = "play";
                Message msg = myService.h.obtainMessage(1,1,1,obj);
                myService.h.sendMessage(msg);
                break;
            case 2:
                // 将Message丢到子线程的MQ to stop playing
                obj = "stop";
                msg = myService.h.obtainMessage(1,1,1,obj);
                myService.h.sendMessage(msg);
                break;
        }
        return true;
    }
}
  • 其代码就是对code进行"译码"动作。
  • 如果code值為1就執行<Play>動作;如果code值為2就執行<Stop>動作
相关推荐
微澜-2 个月前
海康IPC接入TRTC时,从海康中获取的数据显示时色差不正确
音视频·ipc·trtc
小乖兽技术2 个月前
C#与C++交互开发系列(二十):跨进程通信之共享内存(Shared Memory)
c++·c#·交互·ipc
小乖兽技术2 个月前
C#与C++交互开发系列(十九):跨进程通信之套接字(Sockets)
c++·c#·交互·ipc
Hdnw2 个月前
Android IPC机制(一)多进程模式
android·ipc
bbqz0075 个月前
逆向WeChat (五)
c++·微信·逆向·mojo·ipc·wechat·mmmojo
林多8 个月前
【通信中间件】Fdbus HelloWorld实例
c++·rpc·ipc·例子·fdbus·通信中间件
yangwei02510 个月前
【案例】IPC 中的WinCC RT Advanced PC项目,如何下载及开机自动启动?
ipc·wincc rt adv 应用
貌美不及玲珑心,贤妻扶我青云志1 年前
内网安全:IPC协议横向移动
安全·协议·横向移动·ipc
whowin1 年前
IPC之十二:使用libdbus在D-Bus上异步发送/接收信号的实例
进程间通信·ipc·dbus·libdbus