概述

Service启动方式分两种,一种启动服务startService()的方式,一种绑定服务bindService()*的方式。

启动 Service 并传递数据

通过startService()来启动一个Service服务,以这种方式启动的服务,Service会一直无限期运行下去,只有外部调用了stopService()方法时,该Service才会停止运行并销毁。

startService()和startActivity()类似,传入一个Intent对象,使用Intent对象来进行数据的传递。

Intent i = new Intent(this, MyService.class);
 i.putExtra("data", "测试数据");
 startService(i);

Service接收数据需要实现onStartCommand(Intent, int, int)方法,第一个参数Intent就是传递过来的Intent对象,使用getStringExtra()的方法获取传递过来的数据。

String data = intent.getStringExtra("data");
 Log.d(TAG, "onStartCommand: 传递过来的数据: " + data);

绑定 Service 进行通信

bindService启动服务特点:

  1. bindService启动的服务和调用者之间是典型的client-server模式。调用者是client,service则是server端。service只有一个,但绑定到service上面的client可以有一个或很多个。这里所提到的client指的是组件,比如某个Activity。
  2. client可以通过IBinder接口获取Service实例,从而实现在client端直接调用Service中的方法以实现灵活交互,这在通过startService()方法启动中是无法实现的。
  3. bindService启动服务的生命周期与其绑定的client息息相关。当client销毁时,client会自动与Service解除绑定。当然,client也可以明确调用Context的unbindService()方法与Service解除绑定。当没有任何client与Service绑定时,Service会自行销毁。

bindService绑定服务是需要传入三个参数Intent、ServiceConnection、int,其中Intent就是普通的Intent对象,与startService()传入的Intent对象一样,这个就不多说了;第三个参数是一个int类型的flag标志,固定传值Context.BIND_AUTO_CREATE。

重点说一下第二个参数ServiceConnection,传递数据通信也是在这个参数中实现的。ServiceConnection需要重写onServiceConnected和onServiceDisconnected两个方法,先说后者,Android系统在同service的连接意外丢失时调用这个.比如当service崩溃了或被强杀了,但是当客户端解除绑定时,这个方法不会被调用;前者参数中的IBinder参数就是Service中onBind()方法返回的IBinder对象,运用Ibinder对象,就可以实现组件和Service之间的数据通信了。

private MyService.MyBinder mBindService;

    //MyConn实现ServiceConnection与Service创建连接
    class MyConn implements ServiceConnection {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            //service是返回的IBinder类型的参数,需要使用MyBinder类型进行转换,MyBinder为MyBindService中的匿名内部类
            mBindService = (MyService.MyBinder) service;

        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            // TODO Auto-generated method stub
            // service的连接意外丢失时调用这个.比如当service崩溃了或被强杀了
            // 当客户端解除绑定时,这个方法不会被调用.
        }

    }

上述代码中的MyService.MyBinder对象是MyService中创建的匿名内部类,也就是onBind()方法return的IBinder对象。

MyBinder类中定义一个setData()方法,用于获取组件Activity设置的数据。

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

    public class MyBinder extends Binder{

        public void setData(String data){
            mData = data;
        }
    }

那么,绑定Service是如何绑定的呢?传递数据又是具体如何传递呢?

绑定Service使用bindService()来进行绑定,使用unbindService()进行解绑操作,传递数据时只需要使用上述代码中返回的MyBinder对象mBindService,来调用setData()方法即可,注意调用之前先进行非空判断。

case R.id.button3:
    // 绑定Service
    mConn = new MyConn();
    bindService(new Intent(this, MyService.class), mConn, Context.BIND_AUTO_CREATE);
    break;
 case R.id.button4:
    // 解绑Service
    unbindService(mConn);
    break;
 case R.id.button5:
    // bindService传递数据
    if (mBindService != null){
        mBindService.setData("bindService传递的测试数据");
    }
    break;

最后,附上整体代码:

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    private MyConn mConn;
    private MyService.MyBinder mBindService;

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

        findViewById(R.id.button).setOnClickListener(this);
        findViewById(R.id.button2).setOnClickListener(this);
        findViewById(R.id.button3).setOnClickListener(this);
        findViewById(R.id.button4).setOnClickListener(this);
        findViewById(R.id.button5).setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.button:
                // 启动Service
                Intent i = new Intent(this, MyService.class);
                i.putExtra("data", "测试数据");
                startService(i);
                break;
            case R.id.button2:
                // 停止Service
                stopService(new Intent(this, MyService.class));
                break;
            case R.id.button3:
                // 绑定Service
                mConn = new MyConn();
                bindService(new Intent(this, MyService.class), mConn, Context.BIND_AUTO_CREATE);
                break;
            case R.id.button4:
                // 解绑Service
                unbindService(mConn);
                break;
            case R.id.button5:
                // bindService传递数据
                if (mBindService != null){
                    mBindService.setData("bindService传递的测试数据");
                }
                break;

        }
    }

    //MyConn实现ServiceConnection与Service创建连接
    class MyConn implements ServiceConnection {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            //service是返回的IBinder类型的参数,需要使用MyBinder类型进行转换,MyBinder为MyBindService中的匿名内部类
            mBindService = (MyService.MyBinder) service;

        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            // TODO Auto-generated method stub
            // service的连接意外丢失时调用这个.比如当service崩溃了或被强杀了
            // 当客户端解除绑定时,这个方法不会被调用.
        }

    }
}

Service代码:

public class MyService extends Service {

    private static final String TAG = "MyService";
    private String mData = "默认数据";

    public MyService() {
    }

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

    public class MyBinder extends Binder{

        public void setData(String data){
            mData = data;
        }
    }
    
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        mData = intent.getStringExtra("data");
        Log.d(TAG, "onStartCommand: 传递过来的数据: " + mData);
        new Thread(){
            @Override
            public void run() {
                super.run();
                while (true){
                    Log.d(TAG, "run: " + mData);
                }
            }
        }.start();
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public void onCreate() {
        super.onCreate();
        Log.d(TAG, "onCreate: ");
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.d(TAG, "onDestroy: ");
    }
}