Android StrongBinderデュプレクス通信を実現

9364 ワード

クライアントがサービス側が提供するインタフェースにアクセスする必要があるが、サービス側がクライアントをコールバックする方法は、このときどのように実現すればよいのだろうか.たとえば、Activity Management Serviceでは、クライアントがactivityを起動するように要求していますが、元のactivityにはpauseが必要です.このとき、サービス側はクライアントに通知する必要があります.これはどのように実現されていますか.androidを通じてapp.IApplicationThread.ここではStrongBinderを用い,最も簡単なStrongBinderの使用を実証する.
私たちのニーズは、クライアントがサービス側が提供するインタフェースにアクセスし、その後、サービス側がクライアントをコールバックする方法です.
具体的には,クライアントがサービス側インタフェースにアクセスする際に,サービス側に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