7. Binder, AIDL, Messenger

本文深入探讨了Android系统中的进程间通信(IPC)机制,重点介绍了Binder机制和AIDL的使用方式,包括同步RPC和异步RPC的具体实现。此外,还详细讲解了Messenger组件的原理及其在单向和双向通信中的应用。

Android RPC

Linux系统IPC包括:signals,pipes,message queues,semaphores,shared memory。Android中添加了Binder机制和AIDL来实现IPC。
RPC(Remote Procedure Call – 远程过程调度)基本步骤介绍:

  • Method and data decomposition(分解), also known as marshalling(信号编集,编组的,整理);
  • Transferring the marshalled information to the remote process;
  • Recomposing(重新安排) the information in the remote process, also known as unmarshalling;
  • Transferring return values back to the originating process.

Binder

Binder能使Application通过调用方法来让运行在不同进程中的Thread来传输functions和data。Server Process由android.os.Binder类定义了一个remote interface,Client Process中的Threads通过这个remote object来访问这个remote interface。
(The binders enables applications to transfer both functions and data – method calls – between threads running in different processes. The server process defines a remote interface supported by the android.os.Binder class, and threads in a client process can access the remote interface through this remote object.)

RPC传输function和data被称为transaction(交易/事务)。Client Process调用transact()方法,Server Process在onTransact()方法中接收。
这里写图片描述

onTransact()方法在Binder Thread Pool中的一个Thread中执行。Binder Thread Pool 仅仅处理来自其他Process的请求。它最多有16个Thread(Android系统开源,这个值可能被修改)。
IPC可以是双向的,two-way communication mechanism 可以在两个Processes之间被建立,这个机制对于使用Asynchronour RPC是很重要的。
我们可以设置IBinder.FLAG_ONEWAY,Binders也就支持Asynchronous transaction。当这个Flag设置后,client thread调用transact()方法并且会立即返回。而Server Process中Binder thread上的Binder会继续调用onTransact()方法,但是不能同步的返回任何数据到Client Thread。

https://developer.android.com/reference/android/os/IBinder.html
Binder System 支持 recursion[递归/循环] across processes.
这里写图片描述
这里写图片描述

如何检测 remote objects 无效:
这里写图片描述

注意:https://developer.android.com/reference/android/os/Binder.html
这里写图片描述

不错的Binder介绍地址:
http://weishu.me/2016/01/12/binder-index-for-newer/
http://blog.youkuaiyun.com/universus/article/details/6211589
http://blog.youkuaiyun.com/luoshengyang/article/details/6618363

AIDL

当一个进程打算暴露功能给其他进程访问,它需要定义一个Communication Contract(合同/契约). 基本上,server定义client调用的方法接口,我们使用AIDL(Android Interface Definition Language)来定义,定义在 .aidl 文件中。编译这个AIDL文件生成Java代码来支持IPC。
这里写图片描述
这个被生成的Java Interface存到所有的Client Application和Server Application中。这个Interface文件定义了两个内部类 – Proxy和Stub。这两个内部类处理数据的marshalling和unmarshalling,也传输这些数据。因此AIDL的创建自动生成Java代码,Java代码包裹着Binder Framework,并且建立Communication Contract。
这里写图片描述

Synchronous RPC

尽管在Server Process中的Remote method 是并行执行的,即由Binder Thread Pool并行处理,但是对于Client Process中的Calling Thread而言像是顺序执行的。当Server的Remote method被Binder Thread处理完了,可能会给Client返回一个值,那么Client的Calling Thread将会Resume Execution。
这里写图片描述

Eg:
创建aidl文件,注意Server和Client的aidl文件要相同(路径位置以及内容),可以一端创建完了,然后完整的复制到另外一端。
这里写图片描述

/**
* Server Process由Binder Thread Pool并行处理来自Client的请求,有可能给Client返回值,
* 但是Client Process是顺序的处理Server Process返回的结果
*/
interface ISynchronous {
    /**
     * Demonstrates some basic types that you can use as parameters
     * and return values in AIDL.
     */
    String getThreadNameFast();
    String getThreadNameSlow(long sleep);
    String getThreadNameBlocking();
    String getThreadNameUnblock();
}

Server端创建Service类,并修改AndroidManifest.xml文件

public class SynchronousRPCService extends Service {

    // Server端实现AIDL文件中的方法
    private final ISynchronous.Stub mBinder = new ISynchronous.Stub() {
        CountDownLatch mLatch = new CountDownLatch(1);

        @Override
        public String getThreadNameFast() throws RemoteException {
            Log.i("syncrpcservice", "Server # SynchronousRPCService # getThreadNameFast");
            return Thread.currentThread().getName();
        }

        @Override
        public String getThreadNameSlow(long sleep) throws RemoteException {
            Log.i("syncrpcservice", "Server # SynchronousRPCService # getThreadNameSlow");
            SystemClock.sleep(sleep);
            return Thread.currentThread().getName();
        }

        @Override
        public String getThreadNameBlocking() throws RemoteException {
            Log.i("syncrpcservice", "Server # SynchronousRPCService # getThreadNameBlocking # mLatch: " + mLatch);
            try {
                mLatch.await();
            }
            catch (InterruptedException e) {
                e.printStackTrace();
            }
            return Thread.currentThread().getName();
        }

        @Override
        public String getThreadNameUnblock() throws RemoteException {
            Log.i("syncrpcservice", "Server # SynchronousRPCService # getThreadNameUnblock # mLatch: " + mLatch);
            mLatch.countDown();
            return Thread.currentThread().getName();
        }
    };

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        // 返回Server的Binder,Client获取到此Binder来调用AIDL文件中定义的方法
        return mBinder;
    }

}
<!-- AIDL Sychronous RPC -->
<service android:name=".ipc.aidl.SynchronousRPCService"
         android:process=":synchronousremote"
         android:exported="true">
    <intent-filter>
        <action android:name="cn.wei.thread.ipc.aidl.synchronousrpc"></action>
    </intent-filter>
</service>

Client端开启Bind Server,使用aidl生成的方法建立与Server之间的连接

public class MainActivity extends AppCompatActivity {

    private Button mBoundService = null;
    private Button mUnboundService = null;
    private Button mFastBtn = null;
    private TextView mFastResult = null;
    private Button mSlowBtn = null;
    private TextView mSlowResult = null;
    private Button mBlockingBtn = null;
    private TextView mBlockingResult = null;
    private Button mUnblockBtn = null;
    private TextView mUnblockResult = null;

    private ISynchronous mSyncRPCService = null;

    // 建立Service连接
    private ServiceConnection serviceConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            Log.i("syncrpcclient", "Client # ServiceConnection # onServiceConnected # name: " + name + "; service: " + service);
            mSyncRPCService = ISynchronous.Stub.asInterface(service);
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            mSyncRPCService = null;
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mBoundService = (Button) findViewById(R.id.sync_rpc_bound_service);
        mUnboundService = (Button) findViewById(R.id.sync_rpc_unbound_service);

        mBoundService.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // 开启Bind Service
                Intent intent = new Intent("cn.wei.thread.ipc.aidl.synchronousrpc");
                //新版本(5.0后)必须显式intent启动 绑定服务
                // Service的包名和Service的文件名
                intent.setComponent(new ComponentName("cn.wei.thread","cn.wei.thread.ipc.aidl.SynchronousRPCService"));
                bindService(intent, serviceConnection, BIND_AUTO_CREATE);
            }
        });
        mUnboundService.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                unbindService(serviceConnection);
            }
        });

        mFastBtn = (Button) findViewById(R.id.sync_rpc_fast);
        mFastResult = (TextView) findViewById(R.id.sync_rpc_fast_result);

        mFastBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                try {
                    String threadName = mSyncRPCService.getThreadNameFast();
                    mFastResult.setText(threadName);
                }
                catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });

        mSlowBtn = (Button) findViewById(R.id.sync_rpc_slow);
        mSlowResult = (TextView) findViewById(R.id.sync_rpc_slow_result);

        mSlowBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                try {
                    String threadName = mSyncRPCService.getThreadNameSlow(3000);
            //下面的代码不会立即执行,要等上面的方法返回结果。顺序执行
                    mSlowResult.setText(threadName);
                }
                catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });

        mBlockingBtn = (Button) findViewById(R.id.sync_rpc_blocking);
        mBlockingResult = (TextView) findViewById(R.id.sync_rpc_blocking_result);

        mBlockingBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                try {
                    String threadName = mSyncRPCService.getThreadNameBlocking();
                    mBlockingResult.setText(threadName);
                }
                catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });

        mUnblockBtn = (Button) findViewById(R.id.sync_rpc_unblock);
        mUnblockResult = (TextView) findViewById(R.id.sync_rpc_unblock_result);

        mUnblockBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                try {
                    String threadName = mSyncRPCService.getThreadNameUnblock();
                    mUnblockResult.setText(threadName);
                }
                catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        unbindService(serviceConnection);
    }
}

推荐链接:
http://cjw-blog.net/2017/02/26/AIDL/ 代码:https://github.com/V1sk/AIDL/
http://www.jianshu.com/p/a5c73da2e9be

Asynchronous RPC

我们可以把每一个Remote method定义为异步执行来实现Asynchronous RPC(异步RPC)。Client Thread能通过Asynchronous RPC开启一个transaction,然后立即返回。Binder会把transactions给到Server Process,然后关闭Client和Server之间的Connection。

Asynchronous method的要求:

  • 由 oneway 关键字修饰。oneway关键字修饰方法时,那么只有这个方法是Asynchronous的;如果oneway关键字修饰aidl接口文件,那么这个文件中的所有方法都是Asynchronous的。
  • 方法必须返回void;
  • 方法不能有out或者inout修饰的参数。
    注意:我们可以通过方法回调来获取Asynchronous method的处理结果
    这里写图片描述

in,out,inout介绍:
这里写图片描述

Eg.
创建aidl文件
这里写图片描述
IAsynchronous.aidl

import cn.wei.thread.IAsynchronousCallback;

/**
* 使用oneway关键字修饰方法为Asynchronous method,Client调出此方法可以立即返回,而Server端异步处理,然后通过
* 回调接口的方式把结果返回给Client
*/
interface IAsynchronous {
    // Asynchronous method
    oneway void getThreadNameSlow(IAsynchronousCallback callback);
}

IAsynchronousCallback.aidl

/**
* 给Client返回结果的回调接口
*/
interface IAsynchronousCallback {
    // Asynchronous method处理结果的回调方法
    void handleResult(String name);
}

Server端创建Service类,并修改AndroidManifest.xml文件

public class AsynchronousRPCService extends Service {

    private IAsynchronous.Stub mBinder = new IAsynchronous.Stub() {

        @Override
        public void getThreadNameSlow(IAsynchronousCallback callback) throws RemoteException {
            Log.i("asyncserver", "Server # AsynchronousRPCService # getThreadNameSlow # callback: " + callback);
            SystemClock.sleep(3000);
            callback.handleResult(Thread.currentThread().getName());
        }
    };

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return mBinder;
    }
}
<!-- AIDL Asychronous RPC -->
<service android:name=".ipc.aidl.AsynchronousRPCService"
         android:process=":asyncremote"
         android:exported="true">
    <intent-filter>
        <action android:name="cn.wei.thread.ipc.aidl.asynchronousrpc"></action>
    </intent-filter>
</service>

Client端开启Bind Server,使用aidl生成的方法建立与Server之间的连接,实现IAsynchronousCallback回调接口接收结果

public class MainActivity extends AppCompatActivity {

    private Button mBoundAsyncBtn = null;
    private Button mUnboundAsyncBtn = null;
    private Button mAsyncSlowBtn = null;
    private TextView mAsyncSlowName = null;

    private IAsynchronous mAsyncService = null;

    // 建立Service连接
    private ServiceConnection serviceConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            Log.i("asyncclient", "Client # ServiceConnection # onServiceConnected # name: " + name + "; service: " + service);
            mAsyncService = IAsynchronous.Stub.asInterface(service);
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            mAsyncService = null;
        }
    };

    // 实现回调接口
    private IAsynchronousCallback.Stub mCallback = new IAsynchronousCallback.Stub() {

        @Override
        public void handleResult(final String name) throws RemoteException {
            Log.i("asyncclient", "Client # IAsynchronousCallback # handleResult # name: " + name + "; current thread: " + Thread.currentThread().getName());
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    mAsyncSlowName.setText(name);
                }
            });
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mBoundAsyncBtn = (Button) findViewById(R.id.async_rpc_bound_service);
        mUnboundAsyncBtn = (Button) findViewById(R.id.async_rpc_unbound_service);
        mAsyncSlowBtn = (Button) findViewById(R.id.async_rpc_slow);
        mAsyncSlowName = (TextView) findViewById(R.id.async_rpc_slow_result);

        mBoundAsyncBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent("cn.wei.thread.ipc.aidl.asynchronousrpc");
                intent.setComponent(new ComponentName("cn.wei.thread", "cn.wei.thread.ipc.aidl.AsynchronousRPCService"));
                bindService(intent, serviceConnection, BIND_AUTO_CREATE);
            }
        });

        mUnboundAsyncBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                unbindService(serviceConnection);
            }
        });

        mAsyncSlowBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                try {
                    mAsyncService.getThreadNameSlow(mCallback);
            //下面的代码会立即执行。getThreadNameSlow的结果通过回调接口获取
                    mAsyncSlowName.setText("Async get name slow...");
                }
                catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        unbindService(serviceConnection);
    }
}

推荐:
http://codetheory.in/android-interprocess-communication-ipc-with-aidl/
http://cjw-blog.net/2017/02/26/AIDL/ // 推荐

Messenger

Messenger支持Binder Framework,Messenger作为Client和Server交互的中间人。
Message能通过Messenger实现进程间通信,但是发送进程(Client)需要先从接收进程(Server)获取到Messenger引用。
Client和Server实现交互需要两步:
1. Client进程获取到Server进程中的Messenger引用;
2. Client通过Messenger引用发送Message到Server。如果交互是单方向的(Client -> Server),即Client发给Server,直接使用Messenger发送Message即可;
如果交互是相互的,即Client发送给Server,Server也会返回结果给Client的话,Client要设置Message.replyTo,在Client端新建个Messenger并把Client的Messenger发送给Server,然后Server可以使用Message.replyTo的Client Messenger把结果返回给Client。
这里写图片描述
## One Way Communication
Server端,下面的代码实现了和Client交互的代码。

public class WorkerThreadService extends Service {
    private WorkerThread mWorkerThread = null;
    private Messenger mWorkerMessenger = null;

    @Override
    public void onCreate() {
        super.onCreate();
        Log.i("messengerserver", "WorkerThreadService # onCreate");
        // 开启工作线程,处理Client通过Messenger发送来的消息
        mWorkerThread = new WorkerThread();
        mWorkerThread.start();
    }

    // 把Server端的Messenger通过Binder让Client端获取到
    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        Log.i("messengerserver", "WorkerThreadService # onBind # mWorkerMessenger: " + mWorkerMessenger + "; intent: " + intent);

        // 此例中onBind()调用时间比Messenger时间早,防止返回为空
        synchronized (this) {
            while (mWorkerMessenger == null) {
                try {
                    wait();
                }
                catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }

        return mWorkerMessenger.getBinder();
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        mWorkerThread.quit();
    }

    // 实例Server的Messenger,使用工作线程中的Handler来处理Client发送来的数据
    private void onWorkerPrepared() {
        Log.i("messengerserver", "WorkerThreadService # onWorkerPrepared");
        mWorkerMessenger = new Messenger(mWorkerThread.mWorkerHandler);

        // 此例中Messenger实例化比onBind()方法调用时间晚,为了防止onBind()返回空
        synchronized (this) {
            notifyAll();
        }
    }

    // 工作线程,处理Client通过Messenger发送来的消息
    private class WorkerThread extends Thread {
        Handler mWorkerHandler = null;

        @Override
        public void run() {
            super.run();
            Looper.prepare();

            Log.i("messengerserver", "WorkerThreadService # WorkerThread # run");
            // 实例化工作线程中的Handler,用来处理Client端通过Messenger发送过来的消息
            mWorkerHandler = new Handler() {
                @Override
                public void handleMessage(Message msg) {
                    super.handleMessage(msg);
                    switch (msg.what) {
                        case 1: // one way message
                            Log.i("messengerserver", "WorkerThreadService # WorkerThread # run # handleMessage # one way # msg.arg1: " + msg.arg1);
                            break;

                        case 2: // two way message
                            Log.i("messengerserver", "WorkerThreadService # WorkerThread # run # handleMessage # two way # msg.arg1: " + msg.arg1);
                            try {
                                Message replyMsg = Message.obtain();
                                replyMsg.what = 22;
                                replyMsg.arg1 = 22;
                                msg.replyTo.send(replyMsg);
                            }
                            catch (RemoteException e) {
                                e.printStackTrace();
                            }
                            break;

                        default:
                            break;
                    }
                }
            };

            // 工作线程的Handler实例化后,创建Messenger
            onWorkerPrepared();
            Looper.loop();
        }

        public void quit() {
            mWorkerHandler.getLooper().quit();
        }
    }
}

AndroidManifest.xml修改

<!-- Messenger One&Two Way -->
<service android:name=".ipc.messenger.WorkerThreadService"
         android:process=":messenger">
    <intent-filter>
        <action android:name="cn.wei.thread.ipc.messenger.IPC"></action>
    </intent-filter>
</service>

单向交互的Client代码:

public class MessengerOneWayActivity extends Activity {

    private Button mBoundMessengerOnewayBtn = null;
    private Button mUnboundMessengerOnewayBtn = null;
    private Button mSendOnewayBtn = null;

    private Messenger messenger = null;
    private boolean isBound = false;

    private ServiceConnection serviceConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            Log.i("messengeronewayclient", "MessengerOneWayActivity # ServiceConnection # name: " + name + "; service: " + service);
            messenger = new Messenger(service);
            isBound = true;
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            messenger = null;
            isBound = false;
        }
    };

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_messenger_oneway_service);

        mBoundMessengerOnewayBtn = (Button) findViewById(R.id.bound_messenger_oneway_service_test_btn);
        mUnboundMessengerOnewayBtn = (Button) findViewById(R.id.unbound_messenger_oneway_service_test_btn);
        mSendOnewayBtn = (Button) findViewById(R.id.send_oneway_test_btn);

        mBoundMessengerOnewayBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent("cn.wei.thread.ipc.messenger.IPC");
                //必须使用显示调用
                intent.setComponent(new ComponentName("cn.wei.thread", "cn.wei.thread.ipc.messenger.WorkerThreadService"));
                bindService(intent, serviceConnection, BIND_AUTO_CREATE);
            }
        });

        mUnboundMessengerOnewayBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                unbindService(serviceConnection);
            }
        });

        mSendOnewayBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Log.i("messengeronewayclient", "MessengerOneWayActivity # mSendOnewayBtn # isBound: " + isBound);
                if (isBound) {
                    try {
                        Message msg = Message.obtain();
                        msg.what = 1;
                        msg.arg1 = 111111;

                        messenger.send(msg);
                    }
                    catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        });
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        unbindService(serviceConnection);
    }
}

Two Way Communication

互相交互的Client代码:

public class MessengerTwoWayActivity extends Activity {

    private Button mBoundMessengerTwowayBtn = null;
    private Button mUnboundMessengerTwowayBtn = null;
    private Button mSendTwowayBtn = null;
    private TextView mTwowayReply = null;

    private Messenger messenger = null;
    private boolean isBound = false;

    private ServiceConnection serviceConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            Log.i("messengertwowayclient", "MessengerTwoWayActivity # ServiceConnection # name: " + name + "; service: " + service);
            messenger = new Messenger(service);
            isBound = true;
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            messenger = null;
            isBound = false;
        }
    };

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_messenger_twoway_service);

        mBoundMessengerTwowayBtn = (Button) findViewById(R.id.bound_messenger_twoway_service_test_btn);
        mUnboundMessengerTwowayBtn = (Button) findViewById(R.id.unbound_messenger_twoway_service_test_btn);
        mSendTwowayBtn = (Button) findViewById(R.id.send_twoway_test_btn);
        mTwowayReply = (TextView) findViewById(R.id.twoway_reply);

        mBoundMessengerTwowayBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent("cn.wei.thread.ipc.messenger.IPC");
                //必须使用显示调用
                intent.setComponent(new ComponentName("cn.wei.thread", "cn.wei.thread.ipc.messenger.WorkerThreadService"));
                bindService(intent, serviceConnection, BIND_AUTO_CREATE);
            }
        });

        mUnboundMessengerTwowayBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                unbindService(serviceConnection);
            }
        });

        mSendTwowayBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Log.i("messengertwowayclient", "MessengerTwoWayActivity # mSendTwowayBtn # isBound: " + isBound);
                if (isBound) {
                    try {
                        Message msg = Message.obtain();
                        msg.what = 2;
                        msg.arg1 = 222222;

                        // Server和Client通过Messenger双向交互时,Client使用Server的Messager发送message给Server时需要设置Message.replyTo(),
                        // 即设置Client的Messenger,让Server通过的发送来的消息
                        msg.replyTo = new Messenger(new Handler() {
                            @Override
                            public void handleMessage(final Message msg) {
                                super.handleMessage(msg);
                                switch (msg.what) {
                                    case 22:
                                        Log.i("messengertwowayclient", "MessengerTwoWayActivity # msg from Server # arg1: " + msg.arg1);
                                        runOnUiThread(new Runnable() {
                                            @Override
                                            public void run() {
                                                mTwowayReply.setText(msg.arg1 + "");
                                            }
                                        });
                                        break;

                                    default:

                                        break;
                                }
                            }
                        });

                        messenger.send(msg);
                    }
                    catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        });
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        unbindService(serviceConnection);
    }
}

推荐:
http://codetheory.in/android-interprocess-communication-ipc-messenger-remote-bound-services/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值