Android中Service和Activity之间的通信

启动Service并传递数据进去:

Android中通过Intent来启动服务会传递一个Intent过去。

可以在Intent中通过putExtra()携带数据

                Intent startIntent = new Intent(MainActivity.this, MyService.class);
                startIntent.putExtra("data", etData.getText().toString());
                startService(startIntent);

在Service的onStartCommand中得到的Intent中获取这个传递过去的数据

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        System.out.println("Service.onStartCommand()");

        data = intent.getStringExtra("data");
        return super.onStartCommand(intent, flags, startId);
    }

绑定Sevice并传递数据进去:

当通过绑定启动服务的时候可以用另一种方式把Activity中的数据传递到Service中。

首先在Service中定义一个Binder类,继承自系统的Binder类,然后在onBind中返回这个类的一个实例。

    public class MyBinder extends android.os.Binder{

        public void setData(String data){
            MyService.this.data = data;
        }

        public MyService getService(){
            return MyService.this;
        }

    }

    @Override
    public IBinder onBind(Intent intent) {
        // TODO: Return the communication channel to the service.
        System.out.println("Service.onBind()");
        return new MyBinder();
    }

这个类的实例就会在Activity中onServiceConnected中的第二个参数返回,因此也就可以在Activity中用一个实例变量保存它,并调用里面的函数。

private MyService.MyBinder myBinder;

    @Override
    public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
        myBinder = (MyService.MyBinder)iBinder;
}


    @Override
    public void onClick(View view) {
...
            case R.id.btnSyncData:
                if (myBinder != null)
                    myBinder.setData(etData.getText().toString());
}

通过这种方式就可以把Activity中的数据传递给Service,这种方法要比直接用Intent传递要高效。

把Service中的数据传递出来:

还是利用刚刚在Sercie中创建的Binder类,用它返回一个Service的实例:

    public class MyBinder extends android.os.Binder{

        public void setData(String data){
            MyService.this.data = data;
        }

        public MyService getService(){
            return MyService.this;
        }

    }

同时在Service中定义一个钩子函数,用来给Activity取得Service的内部数据:

private CallBack callBack;

    public CallBack getCallBack() {
        return callBack;
    }

    public void setCallBack(CallBack callBack) {
        this.callBack = callBack;
    }

    public interface CallBack{
        void callBackFunc(String str);
    }

通过这种方法Service就可以调用这个CallBack方法:

                    if(callBack != null)
                        callBack.callBackFunc(str);

在Activity中得到了这个Service的实例以后就可以给它设置一个CallBack实例,这样每次Service调用这个函数就可以把这个数据发送出来:

    @Override
    public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
        myBinder = (MyService.MyBinder)iBinder;

        myBinder.getService().setCallBack(new MyService.CallBack() {
            @Override
            public void callBackFunc(String str) {
                Message message = new Message();
                Bundle b = new Bundle();
                b.putString("data", str);
                message.setData(b);
                handler.sendMessage(message);
            }
        });

    }

可以用它来更新UI:

private Handler handler = new Handler(){
        @Override
        public void handleMessage(Message msg) {
                tvOut.setText(msg.getData().getString("data"));
        }
    };
原文地址:https://www.cnblogs.com/dracohan/p/5837640.html