简体   繁体   中英

Android communication between activity and service

I'm trying to implement a system service on Android with inter-process communication based on binding a messenger. For this I'm following this tutorial:

http://www.survivingwithandroid.com/2014/01/android-bound-service-ipc-with-messenger.html

But no matter what I'm trying, i can't get it to work. I found different tutorials online but in the end they are all based on the same procedure.

The app will crash right away when I'm trying to communicate with the service.

Error message

10-09 15:40:33.490    3468-3468/com.example.stenosis.testservice E/AndroidRuntime﹕ FATAL EXCEPTION: main
    Process: com.example.stenosis.testservice, PID: 3468
    java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.stenosis.testservice/com.example.stenosis.testservice.MyActivity}: java.lang.NullPointerException
            at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2184)
            at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2233)
            at android.app.ActivityThread.access$800(ActivityThread.java:135)
            at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1196)
            at android.os.Handler.dispatchMessage(Handler.java:102)
            at android.os.Looper.loop(Looper.java:136)
            at android.app.ActivityThread.main(ActivityThread.java:5001)
            at java.lang.reflect.Method.invokeNative(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:515)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:785)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:601)
            at dalvik.system.NativeStart.main(Native Method)
     Caused by: java.lang.NullPointerException
            at com.example.stenosis.testservice.MyActivity.sendMsg(MyActivity.java:87)
            at com.example.stenosis.testservice.MyActivity.onCreate(MyActivity.java:49)
            at android.app.Activity.performCreate(Activity.java:5231)
            at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1087)
            at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2148)
            at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2233)
            at android.app.ActivityThread.access$800(ActivityThread.java:135)
            at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1196)
            at android.os.Handler.dispatchMessage(Handler.java:102)
            at android.os.Looper.loop(Looper.java:136)
            at android.app.ActivityThread.main(ActivityThread.java:5001)
            at java.lang.reflect.Method.invokeNative(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:515)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:785)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:601)
            at dalvik.system.NativeStart.main(Native Method)

MyActivity.java:

public class MyActivity extends Activity {

    private ServiceConnection sConn;
    private Messenger messenger;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_my);


        // Service Connection to handle system callbacks
        sConn = new ServiceConnection() {

            @Override
            public void onServiceDisconnected(ComponentName name) {
                messenger = null;
            }

            @Override
            public void onServiceConnected(ComponentName name, IBinder service) {
                // We are conntected to the service
                messenger = new Messenger(service);

            }
        };

        // We bind to the service
        bindService(new Intent(this, MyService.class), sConn, Context.BIND_AUTO_CREATE);

        // Try to send a message to the service
        sendMsg();
    }


    // This class handles the Service response
    class ResponseHandler extends Handler {

        @Override
        public void handleMessage(Message msg) {
            int respCode = msg.what;
            String result = "";

            switch (respCode) {
                case MyService.TO_UPPER_CASE_RESPONSE: {
                    result = msg.getData().getString("respData");
                    System.out.println("result");
                    Toast.makeText(getApplicationContext(), result, Toast.LENGTH_LONG).show();
                }
            }
        }

    }


    public void sendMsg() {

        String val = "This is a test";
        Message msg = Message
                .obtain(null, MyService.TO_UPPER_CASE);

        msg.replyTo = new Messenger(new ResponseHandler());
        // We pass the value
        Bundle b = new Bundle();
        b.putString("data", val);

        msg.setData(b);

        try {
            messenger.send(msg);
        } catch (RemoteException e) {
            e.printStackTrace();
        }

    }
}

MyService.java

public class MyService extends Service {

    public static final int TO_UPPER_CASE = 0;
    public static final int TO_UPPER_CASE_RESPONSE = 1;

    private Messenger msg = new Messenger(new ConvertHanlder());;

    @Override
    public IBinder onBind(Intent intent) {
        return msg.getBinder();
    }

    class ConvertHanlder extends Handler {

        @Override
        public void handleMessage(Message msg) {
            // This is the action
            int msgType = msg.what;

            switch (msgType) {
                case TO_UPPER_CASE: {
                    try {
                        // Incoming data
                        String data = msg.getData().getString("data");
                        Message resp = Message.obtain(null, TO_UPPER_CASE_RESPONSE);
                        Bundle bResp = new Bundle();
                        bResp.putString("respData", data.toUpperCase());
                        resp.setData(bResp);

                        msg.replyTo.send(resp);
                    } catch (RemoteException e) {

                        e.printStackTrace();
                    }
                    break;
                }
                default:
                    super.handleMessage(msg);
            }
        }
    }
}

AndroidManifest.xml

    <service android:name=".MyService" android:process=":convertprc"/>

Your problem is that the messanger property is null. You are experiencing concurrency problem. The bindService method is asynchronous - it returns immediately and performs the binding in a background thread. When the binding is done, the onServiceConnected method is invoked. When you try to send the message, the messanger is still not initialized because the onServiceConnected method is hasn't been executed yet.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM