Androidのクロスプロセス通信の紹介---------------aidlは、複雑なオブジェクトとサーバとClicent間のコールバックを伝達します.
24751 ワード
Androidのクロスプロセス通信--aidl
Androidをやっていてもしばらくの間、ブログでこのようなまとめをしたことがありませんでしたが、ちょうどこの時間に勉強を始めてまとめたもので、簡単な質問を考えていると上にまとめられませんでしたが、前に書いたのはCに関するまとめで、Android関連はほとんど見られませんでした.今日はここで共有します.簡単なプロセス間通信の例、aidl
実はAndroidのIPCメカニズムは最初はLinuxのIpc概念から引用されたのではないでしょうか.Linuxの開発をした人はこのIPCに対して相対的にはっきりしているかもしれませんが、FIFO、PIPOパイプ、共有メモリエリアの操作など、Linuxから来ています.
最近はちょうどプロセス間通信でaidlを再構築して最適化するプロジェクトをしているので、これまでのaidlに対する理解よりも一歩深いかもしれません.以前は単純なバインドであり,serverとClient間のコールバックはほとんど用いられず,複雑すぎるオブジェクトのシーケンス化も用いられなかった.
まず全体の流れについてお話しします.
1:ClientデバインディングServerエンド2:Serverエンドバインディング後、aidlのインタフェースオブジェクトを返します3:Clientパラメータ(json文字列)をServerエンドに渡し、Serverエンドで4:Serverエンドを処理してから処理結果をClientにコールバックします
注意:Json文字列はもともとシーケンス化できるので、このとき複雑なシーケンス化の過程を断ち切ることができます.
問題を持って議論します.
1:aidlの複雑なオブジェクトを渡すにはシーケンス化が必要である,すなわちParcelableインタフェースであるが,このオブジェクトが複雑すぎると,オブジェクトに絶えず別のオブジェクトが含まれている場合,あるいはMapとListが多層ネストされている場合にシーケンス化が可能であるという問題がある2:CallBackに関するコールバック,すなわちサーバがClientにコールバックし,aidlファイルのようなインタフェースです.
これは私が書いたaidl全体の流れについて簡単なDemoであり、私がプロジェクトで使った大まかな流れでもあるでしょう.
IServer.aidlファイル
IServerCallback.aidlファイル:
Serverエンドコード:MyCustomServer.JAvaファイル
Plus.java
Client側のコードは以下の通りです.
Plus.java
以上から分かるように、複雑なオブジェクトのシーケンス化の代わりにjson文字列を使用してCallBackコールバックを使用してserverが処理した数値をClientにコールバックする注意:これはClientに対応する1つのサーバ端であるためですが、実際の操作では、多くの場合、複数のClientが1つのサーバ端をバインドすることに遭遇します.では、この時、私たちは複数のCallBackに遭遇します.この時、私たちの可能性があります.各CallBackは異なる結果をコールバックしてClient側に呼び出す必要があります.では、RemoteCallBackのブロードキャストメカニズムを使用して、すべてのCallBackをポーリングしてから、異なるClientに通知する必要があります.
以上の疑似コードと同様に、複雑なシーケンス化プロセスの代わりにJsonを使用することで、すべてのClientに全体的にコールバックできます.
ソースダウンロードアドレス:ソースアドレス
Androidをやっていてもしばらくの間、ブログでこのようなまとめをしたことがありませんでしたが、ちょうどこの時間に勉強を始めてまとめたもので、簡単な質問を考えていると上にまとめられませんでしたが、前に書いたのはCに関するまとめで、Android関連はほとんど見られませんでした.今日はここで共有します.簡単なプロセス間通信の例、aidl
実はAndroidのIPCメカニズムは最初はLinuxのIpc概念から引用されたのではないでしょうか.Linuxの開発をした人はこのIPCに対して相対的にはっきりしているかもしれませんが、FIFO、PIPOパイプ、共有メモリエリアの操作など、Linuxから来ています.
最近はちょうどプロセス間通信でaidlを再構築して最適化するプロジェクトをしているので、これまでのaidlに対する理解よりも一歩深いかもしれません.以前は単純なバインドであり,serverとClient間のコールバックはほとんど用いられず,複雑すぎるオブジェクトのシーケンス化も用いられなかった.
まず全体の流れについてお話しします.
1:ClientデバインディングServerエンド2:Serverエンドバインディング後、aidlのインタフェースオブジェクトを返します3:Clientパラメータ(json文字列)をServerエンドに渡し、Serverエンドで4:Serverエンドを処理してから処理結果をClientにコールバックします
注意:Json文字列はもともとシーケンス化できるので、このとき複雑なシーケンス化の過程を断ち切ることができます.
問題を持って議論します.
1:aidlの複雑なオブジェクトを渡すにはシーケンス化が必要である,すなわちParcelableインタフェースであるが,このオブジェクトが複雑すぎると,オブジェクトに絶えず別のオブジェクトが含まれている場合,あるいはMapとListが多層ネストされている場合にシーケンス化が可能であるという問題がある2:CallBackに関するコールバック,すなわちサーバがClientにコールバックし,aidlファイルのようなインタフェースです.
これは私が書いたaidl全体の流れについて簡単なDemoであり、私がプロジェクトで使った大まかな流れでもあるでしょう.
IServer.aidlファイル
package com.example.aidl;
import com.example.aidl.IServerCallback;
interface IServer{
void setAddNum(int num1,int num2);
void registerServerCallBack(IServerCallback callback);
void unregisterServerCallBack(IServerCallback callback);
void setString(String jsonString);
}
IServerCallback.aidlファイル:
package com.example.aidl;
interface IServerCallback{
void setResult(int result);
void setTransferString(String jsonString);
}
Serverエンドコード:MyCustomServer.JAvaファイル
package com.example.aidl2;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.util.Log;
import com.example.aidl.IServer;
import com.example.aidl.IServerCallback;
public class MyCustomServer extends Service{
int Result = 0;
IServerCallback cback;
private final RemoteCallbackList mCallbacks
= new RemoteCallbackList();
@Override
public void onCreate() {
// TODO Auto-generated method stub
Log.i("123", "oncreate");
super.onCreate();
}
@Override
public IBinder onBind(Intent arg0) {
Log.i("123", "onBind");
return new MyCustomImpl();
}
@Override
public boolean onUnbind(Intent intent) {
// TODO Auto-generated method stub
return super.onUnbind(intent);
}
Plus plus;
private class MyCustomImpl extends IServer.Stub{
@Override
public void setAddNum(int num1, int num2) throws RemoteException {
// TODO Auto-generated method stub
Result = num1 + num2;
Log.i("123", "RESULT:"+Result);
plus = new Plus(cback);
plus.add(num1, num2);
// if(cback != null){
// cback .setResult(plus.add(num1, num2));
// }
}
@Override
public void registerServerCallBack(IServerCallback callback) throws RemoteException {
// TODO Auto-generated method stub
Log.i("123","register callback");
if(callback != null){
mCallbacks.register(callback);
cback = callback;
}
}
@Override
public void unregisterServerCallBack(IServerCallback callback) throws RemoteException {
// TODO Auto-generated method stub
Log.i("123","unregister callback");
if(callback!=null){
mCallbacks.unregister(callback);
cback = null;
}
}
@Override
public void setString(String jsonString) throws RemoteException {
// TODO Auto-generated method stub
if(plus == null){
plus = new Plus(cback);
}
plus.getResult(jsonString);
}
}
@Override
public void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
}
}
Plus.java
package com.example.aidl2;
import android.os.RemoteException;
import com.example.aidl.IServerCallback;
import com.google.gson.Gson;
public class Plus {
IServerCallback cback;
public Plus(IServerCallback cback){
this.cback = cback;
}
public void add(int num1,int num2){
try {
cback.setResult(num1+num2);
} catch (RemoteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private int num1;
private int num2;
public int getNum1() {
return num1;
}
public void setNum1(int num1) {
this.num1 = num1;
}
public int getNum2() {
return num2;
}
public void setNum2(int num2) {
this.num2 = num2;
}
public Plus(int num1, int num2) {
super();
this.num1 = num1;
this.num2 = num2;
}
public void getResult(String jsonString){
Plus plus = new Gson().fromJson(jsonString, Plus.class);
try {
cback.setTransferString(plus.num1 +"+"+plus.num2 + "="+plus.getNum1()+plus.getNum2());
} catch (RemoteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Client側のコードは以下の通りです.
package com.example.aidl1;
import com.example.aidl.IServer;
import com.example.aidl.IServerCallback;
import com.google.gson.Gson;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
public class MainActivity extends Activity {
Button btnBind;
TextView tvResult;
Intent server;
IServer mServer = null;
Button btnTransfer ;
Button btnTransfeString;
iServerCallImpl callback = new iServerCallImpl();
private ServiceConnection conn = new ServiceConnection(){
@Override
public void onServiceConnected(ComponentName arg0, IBinder arg1) {
// TODO Auto-generated method stub
Log.i("123", "onServerConnected");
mServer = IServer.Stub.asInterface(arg1);
registerCallBack();
}
@Override
public void onServiceDisconnected(ComponentName arg0) {
// TODO Auto-generated method stub
ungisterCallBack();
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btnBind = (Button) findViewById(R.id.btn_bind);
tvResult = (TextView) findViewById(R.id.tv_result);
btnTransfer = (Button) findViewById(R.id.btn_transfer);
btnTransfeString = (Button) findViewById(R.id.btn_transferstring);
btnBind.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
server = new Intent("com.example.server");
bindService(server, conn, Context.BIND_AUTO_CREATE);
}
});
btnTransfer.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
if(mServer!=null){
try {
mServer.setAddNum(10, 22);
} catch (RemoteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
});
btnTransfeString.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
Plus plsPlus = new Plus(30, 50);
String json = new Gson().toJson(plsPlus);
try {
mServer.setString(json);
} catch (RemoteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
}
private class iServerCallImpl extends IServerCallback.Stub{
@Override
public void setResult(int result) throws RemoteException {
// TODO Auto-generated method stub
if(tvResult != null){
tvResult.setText(""+result);
}
}
@Override
public void setTransferString(String jsonString) throws RemoteException {
// TODO Auto-generated method stub
if(tvResult != null){
tvResult.setText(""+jsonString);
}
}
}
private void registerCallBack(){
if(mServer == null){
return;
}
try {
mServer.registerServerCallBack(callback);
} catch (RemoteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private void ungisterCallBack(){
if(mServer == null){
return;
}
try {
mServer.unregisterServerCallBack(callback);
} catch (RemoteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
}
Plus.java
package com.example.aidl1;
import android.os.RemoteException;
import com.example.aidl.IServerCallback;
import com.google.gson.Gson;
public class Plus {
private int num1;
private int num2;
public int getNum1() {
return num1;
}
public void setNum1(int num1) {
this.num1 = num1;
}
public int getNum2() {
return num2;
}
public void setNum2(int num2) {
this.num2 = num2;
}
public Plus(int num1, int num2) {
super();
this.num1 = num1;
this.num2 = num2;
}
IServerCallback cback;
public Plus(IServerCallback cback){
this.cback = cback;
}
public void add(int num1,int num2){
try {
cback.setResult(num1+num2);
} catch (RemoteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void getResult(String jsonString){
Plus plus = new Gson().fromJson(jsonString, Plus.class);
try {
cback.setTransferString(plus.num1 +"+"+plus.num2 + "="+plus.getNum1()+plus.getNum2());
} catch (RemoteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
以上から分かるように、複雑なオブジェクトのシーケンス化の代わりにjson文字列を使用してCallBackコールバックを使用してserverが処理した数値をClientにコールバックする注意:これはClientに対応する1つのサーバ端であるためですが、実際の操作では、多くの場合、複数のClientが1つのサーバ端をバインドすることに遭遇します.では、この時、私たちは複数のCallBackに遭遇します.この時、私たちの可能性があります.各CallBackは異なる結果をコールバックしてClient側に呼び出す必要があります.では、RemoteCallBackのブロードキャストメカニズムを使用して、すべてのCallBackをポーリングしてから、異なるClientに通知する必要があります.
final int N = mCallbacks.beginBroadcast();
for (int i=0; itry {
mCallbacks.getBroadcastItem(i).( );
} catch (RemoteException e) {
// The RemoteCallbackList will take care of removing
// the dead object for us.
}
}
mCallbacks.finishBroadcast();
以上の疑似コードと同様に、複雑なシーケンス化プロセスの代わりにJsonを使用することで、すべてのClientに全体的にコールバックできます.
ソースダウンロードアドレス:ソースアドレス