Android StrongBinderデュプレクス通信を実現
9364 ワード
クライアントがサービス側が提供するインタフェースにアクセスする必要があるが、サービス側がクライアントをコールバックする方法は、このときどのように実現すればよいのだろうか.たとえば、Activity Management Serviceでは、クライアントがactivityを起動するように要求していますが、元のactivityにはpauseが必要です.このとき、サービス側はクライアントに通知する必要があります.これはどのように実現されていますか.androidを通じてapp.IApplicationThread.ここではStrongBinderを用い,最も簡単なStrongBinderの使用を実証する.
私たちのニーズは、クライアントがサービス側が提供するインタフェースにアクセスし、その後、サービス側がクライアントをコールバックする方法です.
具体的には,クライアントがサービス側インタフェースにアクセスする際に,サービス側にStrongBinderを送信し,サービス側がこのStrongBinderを取得した後,このStrongBinderのメソッドを呼び出すことができる.
まず、BinderオブジェクトAppを定義します.コードは次のとおりです.
AppはBinderを継承し,Logメソッドを実現した.
Binderの実装には、自分を唯一表すdescriptorが必要であることに注意してください.
次に、クライアントがサービス側インタフェースにアクセスするときに、次のように相手に渡されます.
すなわち,クライアントはサービス側ssメソッドにアクセスする際に,過去に伝達する.
次はサービスがどのようにAppを取得するかです.
に合格
IBiderオブジェクトを取得し、IBinderのtransactメソッドを使用してlogメソッドにアクセスします.
remote.transact(1, _data, _reply, 0); ここの1は実はAppのLOG_TRANSACTION .
完全なコードは次のとおりです.
App.java
Client.java
aa.java
以上の3つのファイルは1つのプロジェクトの中にあります.次はサービスです.
MyService.java
IApp.JAvaは、サービスとクライアントに1部ずつ置くインタフェースを実装する必要があります.
登録:
qq 81553652
私たちのニーズは、クライアントがサービス側が提供するインタフェースにアクセスし、その後、サービス側がクライアントをコールバックする方法です.
具体的には,クライアントがサービス側インタフェースにアクセスする際に,サービス側にStrongBinderを送信し,サービス側がこのStrongBinderを取得した後,このStrongBinderのメソッドを呼び出すことができる.
まず、BinderオブジェクトAppを定義します.コードは次のとおりです.
package com.example.test4;
import android.os.Binder;
import android.os.IBinder;
import android.os.Parcel;
import android.os.RemoteException;
import android.util.Log;
public class App extends Binder {
String descriptor = "com.example.test4.IApp";
private static final String TAG = "App";
public static final int LOG_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+0;
public void log() {
Log.e(TAG,"Called from other side");
}
protected boolean onTransact(int code, Parcel data, Parcel reply,
int flags) throws RemoteException {
switch (code) {
case INTERFACE_TRANSACTION: {
reply.writeString(descriptor);
return true;
}
case LOG_TRANSACTION: {
data.enforceInterface(descriptor);
log();
reply.writeNoException();
return true;
}
}
return super.onTransact(code, data, reply, flags);
}
}
AppはBinderを継承し,Logメソッドを実現した.
Binderの実装には、自分を唯一表すdescriptorが必要であることに注意してください.
次に、クライアントがサービス側インタフェースにアクセスするときに、次のように相手に渡されます.
public int ss(int i) {
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
int _result=-1;
try {
_data.writeInterfaceToken(DESCRIPTOR);
_data.writeInt(i);
_data.writeStrongBinder(new App());
mRemote.transact(TRANSACTION_ss, _data, _reply, 0);
_reply.readException();
_result = _reply.readInt();
} catch (RemoteException e) {
e.printStackTrace();
} finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
すなわち,クライアントはサービス側ssメソッドにアクセスする際に,過去に伝達する.
_data.writeStrongBinder(new App());
次はサービスがどのようにAppを取得するかです.
class MyBinder extends Binder {
@Override
protected boolean onTransact(int code, Parcel data, Parcel reply,
int flags) throws RemoteException {
switch (code) {
case INTERFACE_TRANSACTION: {
reply.writeString(DESCRIPTOR);
return true;
}
case TRANSACTION_ss: {
data.enforceInterface(DESCRIPTOR);
reply.writeNoException();
int i = data.readInt();
IBinder app = data.readStrongBinder();
/// app log
{
log(app);
}
Log.e(TAG, "MyService3 " + i);
reply.writeInt(i);
return true;
}
}
return super.onTransact(code, data, reply, flags);
}
}
に合格
IBinder app = data.readStrongBinder();
IBiderオブジェクトを取得し、IBinderのtransactメソッドを使用してlogメソッドにアクセスします.
public void log(android.os.IBinder remote) {
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
try {
_data.writeInterfaceToken("com.example.test4.IApp");
remote.transact(1, _data, _reply, 0);
_reply.readException();
} catch (RemoteException e) {
e.printStackTrace();
} finally {
_reply.recycle();
_data.recycle();
}
}
remote.transact(1, _data, _reply, 0); ここの1は実はAppのLOG_TRANSACTION .
完全なコードは次のとおりです.
App.java
package com.example.test4;
import android.os.Binder;
import android.os.IBinder;
import android.os.Parcel;
import android.os.RemoteException;
import android.util.Log;
public class App extends Binder {
String descriptor = "com.example.test4.IApp";
private static final String TAG = "App";
public static final int LOG_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+0;
public void log() {
Log.e(TAG,"Called from other side");
}
protected boolean onTransact(int code, Parcel data, Parcel reply,
int flags) throws RemoteException {
switch (code) {
case INTERFACE_TRANSACTION: {
reply.writeString(descriptor);
return true;
}
case LOG_TRANSACTION: {
data.enforceInterface(descriptor);
log();
reply.writeNoException();
return true;
}
}
return super.onTransact(code, data, reply, flags);
}
}
Client.java
package com.example.test4;
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.View;
import android.view.View.OnClickListener;
public class Client extends Activity implements OnClickListener {
private static final String TAG = "MainActivity";
aa mProxy ;
private static final java.lang.String DESCRIPTOR = "com.example.test3.aa";
static final int TRANSACTION_ss = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
ServiceConnection conn ;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.setContentView(R.layout.activity_main);
this.findViewById(R.id.button1).setOnClickListener(this);
Intent service = new Intent("com.example.test3.MyService2");
conn = new ServiceConnection() {
@Override
public void onServiceDisconnected(ComponentName name) {
}
@Override
public void onServiceConnected(ComponentName name, IBinder obj) {
mProxy =new Proxy(obj);
}
};
this.bindService(service, conn, Context.BIND_AUTO_CREATE);
}
private static class Proxy implements aa {
private android.os.IBinder mRemote;
Proxy(android.os.IBinder remote) {
mRemote = remote;
}
public int ss(int i) {
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
int _result=-1;
try {
_data.writeInterfaceToken(DESCRIPTOR);
_data.writeInt(i);
_data.writeStrongBinder(new App());
mRemote.transact(TRANSACTION_ss, _data, _reply, 0);
_reply.readException();
_result = _reply.readInt();
} catch (RemoteException e) {
e.printStackTrace();
} finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
}
@Override
protected void onDestroy() {
this.unbindService(conn);
super.onDestroy();
}
@Override
public void onClick(View v) {
Log.e(TAG, "" + mProxy.ss(752));
}
}
aa.java
package com.example.test4;
public interface aa{
int ss(int i);
}
以上の3つのファイルは1つのプロジェクトの中にあります.次はサービスです.
MyService.java
package com.example.test3;
import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.os.Parcel;
import android.os.RemoteException;
import android.util.Log;
public class MyService extends Service {
private static final java.lang.String DESCRIPTOR = "com.example.test3.aa";
static final int TRANSACTION_ss = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
private static final String TAG = "MyService3";
@Override
public IBinder onBind(Intent intent) {
Log.e(TAG, "onBind");
return new MyBinder();
}
class MyBinder extends Binder {
@Override
protected boolean onTransact(int code, Parcel data, Parcel reply,
int flags) throws RemoteException {
switch (code) {
case INTERFACE_TRANSACTION: {
reply.writeString(DESCRIPTOR);
return true;
}
case TRANSACTION_ss: {
data.enforceInterface(DESCRIPTOR);
reply.writeNoException();
int i = data.readInt();
IBinder app = data.readStrongBinder();
AppProxy mAppProxy = new AppProxy(app);
// / app log
mAppProxy.log();
Log.e(TAG, "MyService3 " + i);
reply.writeInt(i);
return true;
}
}
return super.onTransact(code, data, reply, flags);
}
}
public class AppProxy implements IApp {
IBinder mRemote;
AppProxy(IBinder remote) {
this.mRemote = remote;
}
public void log() {
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
try {
_data.writeInterfaceToken(IApp.descriptor);
mRemote.transact(IApp.LOG_TRANSACTION, _data, _reply, 0);
_reply.readException();
} catch (RemoteException e) {
e.printStackTrace();
} finally {
_reply.recycle();
_data.recycle();
}
}
};
}
IApp.JAvaは、サービスとクライアントに1部ずつ置くインタフェースを実装する必要があります.
package com.example.test4;
import android.os.IBinder;
public interface IApp {
String descriptor = "com.example.test4.IApp";
public static final int LOG_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+0;
public void log() ;
}
登録:
qq 81553652