我正在尝试在Android中创建一个与远程服务快速通信的程序(〜40,000 / sec),但是所有Android IPC似乎都无法完成此任务。我的第一个尝试是使用标准Messenger系统,该系统无法以约2000 /秒的速度运行,同样糟糕的是,它似乎间歇性地出现了点差。
MainActivity(对Messenger进行测试)
public class MainActivity extends Activity implements ServiceConnection{
Messenger mServiceMessenger;
Messenger mClientMessenger = new Messenger(new ClientHandler());
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Intent intent = new Intent(this,TestService.class);
bindService(intent,this, Context.BIND_AUTO_CREATE);
}
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
mServiceMessenger = new Messenger(service);
Message m = Message.obtain();
m.replyTo = mClientMessenger;
try {
mServiceMessenger.send(m);
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
public void onServiceDisconnected(ComponentName name) {}
public class ClientHandler extends Handler {
@Override
public void handleMessage(Message msg) {
Log.d("Spam","Message Received");
}
}
}
RemoteService(对Messenger进行测试)
public class TestService extends Service {
private Messenger mServiceMessenger = new Messenger(new ServiceHandler());
private Messenger mClientMessenger;
private Random r = new Random();
public TestService() {
super();
}
@Override
public void onCreate() {
super.onCreate();
}
@Override
public IBinder onBind(Intent intent) {
return mServiceMessenger.getBinder();
}
public void initSpam(){
for(int i=0;i<10;i++) {
TimerTask task = new TimerTask() {
@Override
public void run() {
Bundle b = new Bundle();
b.putInt("INT",r.nextInt());
b.putLong("LONG",r.nextLong());
b.putBoolean("BOOL",r.nextBoolean());
b.putFloat("FLOAT",r.nextFloat());
b.putDouble("DOUBLE",r.nextDouble());
b.putString("STRING",String.valueOf(r.nextInt()));
Message msg = Message.obtain();
msg.setData(b);
try {
mClientMessenger.send(msg);
} catch (RemoteException e) {
e.printStackTrace();
}
}
};
Timer timer = new Timer();
timer.scheduleAtFixedRate(task,1,1);
}
}
public class ServiceHandler extends Handler {
@Override
public void handleMessage(Message msg) {
mClientMessenger = msg.replyTo;
initBarrage();
}
}
}
第二次尝试是使用AIDL完成的。尽管这也实现了IPC绑定程序,但我认为开销要少得多。但是,事实证明,AIDL的效率不比Messengers高得多,并且它也无法解决口吃问题。
MainActivity(使用AIDL测试)
public class MainActivity extends Activity implements ServiceConnection{
IRemoteService mService;
TextView countTextView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Intent intent = new Intent(this,TestService.class);
bindService(intent,this, Context.BIND_AUTO_CREATE);
}
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
mService = IRemoteService.Stub.asInterface(service);
try {
mService.registerCallback(mClientBinder);
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
public void onServiceDisconnected(ComponentName name) {}
public final IServiceAidlCallback.Stub mClientBinder = new IServiceAidlCallback.Stub(){
public void basicTypes(int anInt, long aLong, boolean aBoolean,
float aFloat, double aDouble, String aString){
Log.d("Spam","Callback Received");
}
};
}
RemoteService(使用AIDL测试)
public class TestService extends Service {
private Random r = new Random();
private IServiceAidlCallback mClientCallback;
public TestService() {
super();
}
@Override
public void onRebind(Intent intent) {
super.onRebind(intent);
}
@Override
public void onCreate() {
super.onCreate();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
return super.onStartCommand(intent, flags, startId);
}
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
public final IRemoteService.Stub mBinder = new IRemoteService.Stub(){
public void registerCallback(IBinder callback){
mClientCallback = IServiceAidlCallback.Stub.asInterface(callback);
initSpam();
}
};
public void initSpam(){
for(int i=0;i<10;i++) {
TimerTask task = new TimerTask() {
@Override
public void run() {
try {
mClientCallback.basicTypes(
r.nextInt(),
r.nextLong(),
r.nextBoolean(),
r.nextFloat(),
r.nextDouble(),
String.valueOf(r.nextInt()));
} catch (RemoteException e) {
e.printStackTrace();
}
}
};
Timer timer = new Timer();
timer.scheduleAtFixedRate(task,1,1);
}
}
}
在这两种情况下我都做错了什么,这会阻止我每秒超过5,000个?还是有我不知道的另一种Android IPC系统?
做类似的事情:
MainActivity
// use it for writing: stream.write(byte[])
// (make sure to write as biggest data chunks as possible)
// or wrap it around some other streams like DataOutputStream
private OutputStream stream;
// ServiceConnection implementation
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
try {
ParcelFileDescriptor[] pipe = ParcelFileDescriptor.createPipe();
stream = new ParcelFileDescriptor.AutoCloseOutputStream(pipe[1]);
Parcel data = Parcel.obtain();
FileDescriptor readFileDescriptor = pipe[0].getFileDescriptor();
data.writeFileDescriptor(readFileDescriptor);
service.transact(IBinder.FIRST_CALL_TRANSACTION, data, null, 0);
} catch (Exception e) {
e.printStackTrace();
}
Log.d(TAG, "onServiceConnected " + stream);
}
RemoteService
@Override
public IBinder onBind(Intent intent) {
Log.d(TAG, "onBind ");
return binder;
}
IBinder binder = new Binder() {
@Override
protected boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
ParcelFileDescriptor pfd = data.readFileDescriptor();
final InputStream stream = new ParcelFileDescriptor.AutoCloseInputStream(pfd);
// do something with a 'stream', start a new Thread for example and read data in a loop
...
...
return true;
}
};
@@ pskink这是我的代码。一旦您阅读,我就会删除它。
我的目标是将在同一应用中运行但以两个不同过程运行的两个活动进行交互。我有一类叫做MainActivity和DirectoryExplorer ...
class MainActivity extends Activity { ... }
class DirectoryExplorer extends Activity { ... }
DirectoryExplorer处于其自身的过程中,因为它与MainActivity处于同一任务中,并且如果死亡,MainActivity将不会被Android重新生成。
MainActivity启动DirectoryExplorer以便导入文件...
class MainActivity extends Activity
implements GlobalConstants
{
@Override public boolean onOptionsItemSelected(MenuItem item)
{
switch(item.getItemId())
{
case R.id.import:
DirectoryExplorer.show(this, IMPORT, new BinderParcelable(this));
return true;
}
}
}
class DirectoryExplorer extends Activity
implements GlobalConstants
{
IBinder binder ;
public static void show(MainActivity activity,String action,IBinder binder)
{
Intent intent = new Intent(activity,DirectoryExplorer.class);
intent.setAction(action);
if(binder != null) intent.putExtra("binder",new BinderParcelable(binder));
if(action == EXPORT) intent.putExtra("content_path",activity.content.getDataFile());
activity.startActivity(intent);
}
@Override protected void onCreate(Bundle state)
{
super.onCreate(state);
binder = ((BinderParcelable)getIntent().getParcelableExtra("binder")).binder;
}
// This is where I test the binder
// commented out code are alternatives I tried
final void onConfirm()
{
Parcel data = Parcel.obtain(); data.writeInt(1000);
Parcel reply = Parcel.obtain();
switch(getIntent().getAction())
{
case "IMPORT": try{ "transact result : " + binder.transact(ON_FINISH_IMPORT,Parcel.obtain(),null,0); }
catch(RemoteException e){ }
. // This simply works. But I want to use raw Binder
// Message msg = Message.obtain();
// try{messenger.send(msg);}
//catch(RemoteException e){ }
// This fails
//try{ dirExplInterface.print("Interface working"); }
//catch(RemoteException e) { }
break;
}
data.recycle();
reply.recycle();
}
}
class BinderParcelable implements Parcelable
{
IBinder binder;
...a
}