【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,如图所示:

service.png

调用Messenger的send方法,即可在维护handler里面拿到数据。
是不是很简单,这段示例代码就是ApiDemos里面所示。

上一篇下一篇

猜你喜欢

热点阅读