7. Binder, AIDL, 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.csdn.net/universus/article/details/6211589
http://blog.csdn.net/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/

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章