【Android】一种简单方法跨进程访问另一个app的Servi
2018-01-15 本文已影响0人
李翾
先看代码另一个App的Service写法:
public class MyService extends Service {
static String TAG = "远程服务端";
/**
* Holds last value set by a client.
*/
int mValue = 0;
/**
* Command to the service to register a client, receiving callbacks
* from the service. The Message's replyTo field must be a Messenger of
* the client where callbacks should be sent.
*/
static final int MSG_REGISTER_CLIENT = 1;
/**
* Command to the service to unregister a client, ot stop receiving callbacks
* from the service. The Message's replyTo field must be a Messenger of
* the client as previously given with MSG_REGISTER_CLIENT.
*/
static final int MSG_UNREGISTER_CLIENT = 2;
/**
* Command to service to set a new value. This can be sent to the
* service to supply a new value, and will be sent by the service to
* any registered clients with the new value.
*/
static final int MSG_SET_VALUE = 3;
/**
* Target we publish for clients to send messages to IncomingHandler.
*/
final Messenger mMessenger = new Messenger(new IncomingHandler());
public MyService() {
}
ArrayList<Messenger> mClients = new ArrayList<>();
@Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
Log.i(TAG, "远程服务onBind");
return mMessenger.getBinder();
}
/**
* Handler of incoming messages from clients.
*/
class IncomingHandler extends Handler {
@Override
public void handleMessage(Message msg) {
Log.i(TAG, "IncomingHandler收到消息" + msg.what + "");
switch (msg.what) {
case MSG_REGISTER_CLIENT:
mClients.add(msg.replyTo);
break;
case MSG_UNREGISTER_CLIENT:
mClients.remove(msg.replyTo);
break;
case MSG_SET_VALUE:
mValue = msg.arg1;
mValue++;
Log.d(TAG, " mValue=%d" + mValue + "");
for (int i = mClients.size() - 1; i >= 0; i--) {
try {
mClients.get(i).send(Message.obtain(null,
MSG_SET_VALUE, mValue, 0));
} catch (RemoteException e) {
// The client is dead. Remove it from the list;
// we are going through the list from back to front
// so this is safe to do inside the loop.
Log.i(TAG, msg.what + "IncomingHandler异常了RemoteException");
mClients.remove(i);
}
}
break;
default:
super.handleMessage(msg);
}
}
}
@Override
public void onCreate() {
super.onCreate();
Log.i(TAG, "服务端创建了onCreate");
}
}
关键代码:
@Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
Log.i(TAG, "远程服务onBind");
return mMessenger.getBinder();
}
我们在onBind返回了一个Messenger,因为Messenger实现了AIDL.再看客户端app如何写:
public class InnerActivityTest {
public static class InnerActivity extends AppCompatActivity {
static String TAG = "客户端";
/**
* Messenger for communicating with service.
*/
Messenger mService = null;
int i;
int msgArg1 = 10;
boolean isSuccess;
long forStartTime;
long forEndTime;
long startTime;
long endTime;
private TextView textView;
/**
* Target we publish for clients to send messages to IncomingHandler.
*/
final Messenger mMessenger = new Messenger(new IncomingHandler());
/**
* Class for interacting with the main interface of the service.
*/
private ServiceConnection mConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className,
IBinder service) {
// This is called when the connection with the service has been
// established, giving us the service object we can use to
// interact with the service. We are communicating with our
// service through an IDL interface, so get a client-side
// representation of that from the raw service object.
mService = new Messenger(service);
isSuccess = true;
// We want to monitor the service for as long as we are
// connected to it. v
try {
Message msg = Message.obtain(null,
1);
msg.replyTo = mMessenger;
mService.send(msg);
// Give it some value as an example.
msg = Message.obtain(null,
3, msgArg1, 0);
mService.send(msg);
} catch (RemoteException e) {
// In this case the service has crashed before we could even
// do anything with it; we can count on soon being
// disconnected (and then reconnected if it can be restarted)
// so there is no need to do anything here.
Log.i(TAG, "客户端连接服务器异常了");
}
// As part of the sample, tell the user what happened.
// Toast.makeText(InnerActivity.this,"RemoteException",
// Toast.LENGTH_SHORT).show();
}
public void onServiceDisconnected(ComponentName className) {
// This is called when the connection with the service has been
// unexpectedly disconnected -- that is, its process crashed.
mService = null;
// As part of the sample, tell the user what happened.
Toast.makeText(InnerActivity.this, "onServiceDisconnected",
Toast.LENGTH_SHORT).show();
}
};
/**
* Handler of incoming messages from service.
*/
class IncomingHandler extends Handler {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case 3:
msgArg1 = msg.arg1;
textView.setText("显示服务端返回的数据:" + msgArg1);
default:
super.handleMessage(msg);
}
}
}
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
textView = new TextView(this);
textView.setText("显示服务端返回的数据:");
textView.setTextColor(getResources().getColor(R.color.black));
Button button = new Button(this);
button.setText("往远程服务发信息");
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (isSuccess) {
Message msg = Message.obtain();
msg.replyTo = mMessenger;
msg.arg1 = msgArg1;
msg.what = 3;
try {
mService.send(msg);
} catch (RemoteException e) {
e.printStackTrace();
}
} else {
bindService(new Intent().setComponent(new ComponentName("com.martin.matrix", "com.martin.matrix.MyService")), mConnection, Context.BIND_AUTO_CREATE);
}
}
});
LinearLayout linearLayout = new LinearLayout(this);
linearLayout.setOrientation(LinearLayout.VERTICAL);
linearLayout.addView(button);
linearLayout.addView(textView);
setContentView(linearLayout);
}
}
看关键代码:
我们在客户端app里面也维护了一个Messenger, final Messenger mMessenger = new Messenger(new IncomingHandler());
发送消息就利用服务端onBind返回的Messenger,如图所示:
调用Messenger的send方法,即可在维护handler里面拿到数据。
是不是很简单,这段示例代码就是ApiDemos里面所示。