Binder 概述
Binder的應用
一個簡單的Binder應用的實例
public class SampleService extends Service
{
private static final String TAG = "BINDServer";
private static final String DESCRIPTOR = "TESTING";
public ServiceBinder mBinder = new ServiceBinder();
private static int m_CallingTimes = 0;
@Override
public void onCreate()
{
Log.d(TAG, "SampleService::onCreate()");
super.onCreate();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId)
{
Log.d(TAG, "SampleService::onStartCommand()");
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy()
{
Log.d(TAG, "SampleService::onDestroy()");
super.onDestroy();
}
@Override
public IBinder onBind(Intent arg0)
{
return mBinder;
}
public class ServiceBinder extends Binder
{
protected boolean onTransact(int code, Parcel data, Parcel reply,
int flags) throws RemoteException
{
Log.d(TAG, "ServiceBinder::onTransact() code=" + code);
String strResult = "";
switch (code)
{
case 0x01:
{
data.enforceInterface(DESCRIPTOR);
String _arg0;
_arg0 = data.readString();
strResult = getInfo(_arg0, "===>");
reply.writeNoException();
reply.writeString(strResult);
Log.d(TAG, "ServiceBinder::onTransact() result=" + strResult);
return true;
}
default:
break;
}
return super.onTransact(code, data, reply, flags);
}
public String getInfo(String strRecv, String strCode)
{
Date date = new Date();
String strResult = new String(date.toString());
strResult = m_CallingTimes + "::" + strRecv + strCode + strResult;
return strResult;
}
}
}
public class MainActivity extends Activity
{
private static final String TAG = "BinderClient";
private IBinder mBinder;
private ServiceConnection mServiceConn = new ServiceConnection()
{
@Override
public void onServiceDisconnected(ComponentName name)
{
Log.d(TAG, "mServiceConn onServiceDisconnected");
}
@Override
public void onServiceConnected(ComponentName name, IBinder service)
{
Log.d(TAG, "mServiceConn onServiceConnected");
mBinder = service;
}
};
public void bindService(View view)
{
Log.d(TAG, "bindService");
Intent intent = new Intent();
intent.setAction("com.example.bindersample.TestInterface");
boolean bindFlag = bindService(intent, mServiceConn, Context.BIND_AUTO_CREATE);
Log.e(TAG, "bindService() = " + bindFlag);
}
public void unbindService(View view)
{
unbindService(mServiceConn);
}
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void testClick(View view)
{
if (mBinder == null)
{
Log.d(TAG, "testClick() mBinder is NULL");
}
else
{
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
String _result;
try
{
Date date = new Date();
_data.writeInterfaceToken("TESTING");
_data.writeString(date.toString());
mBinder.transact(0x01, _data, _reply, 0);
_reply.readException();
_result = _reply.readString();
Toast.makeText(this, _result + "", Toast.LENGTH_SHORT).show();
}
catch (RemoteException e)
{
e.printStackTrace();
}
finally
{
_reply.recycle();
_data.recycle();
}
}
}
}
Binder運行的基本流程
- 獲取Binder對象
public void bindService(View view)
{
Log.d(TAG, "bindService");
Intent intent = new Intent();
intent.setAction("com.example.bindersample.TestInterface");
boolean bindFlag = bindService(intent, mServiceConn, Context.BIND_AUTO_CREATE);
Log.e(TAG, "bindService() = " + bindFlag);
}
<service android:name="SampleService">
<intent-filter>
<action android:name="com.example.bindersample.TestInterface" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</service>
- Client 與 Server交互
關於 android.os.Parcel
Retrieve a new Parcel object from the pool. 使用pool的方式效率一定是比創建/釋放的方式要高許多。
Special function for reading an exception result from the header of a parcel, to be used after receiving the result of a transaction. This will throw the exception for you if it had been written to the Parcel, otherwise return and let you read the normal result data from the Parcel.