Android 服务启动和绑定

1、Android 服务的启动和绑定

1.1 服务demo代码

public class MyService extends Service {
    public static final String MYSERVICE_STOP_FLAG = "MyService_tag";
    private DownloadBinder mBinder;
    @Override
    public void onCreate(){
        super.onCreate();
        Log.d("MyService" ,"onCreate");
        Intent intent = new Intent(this ,MainActivity.class);
        PendingIntent pi = PendingIntent.getActivity(this ,0 ,intent ,0);
        Notification notification = new NotificationCompat.Builder(this)
                .setContentText("This is Text!")
                .setContentTitle("This is Title!")
                .setWhen(System.currentTimeMillis())
                .setSmallIcon(R.mipmap.ic_launcher)
                .setLargeIcon(BitmapFactory.decodeResource(getResources() ,R.mipmap.ic_launcher))
                .setContentIntent(pi)
                .build();

        startForeground(1 ,notification);
        mBinder = new DownloadBinder();
    }

    @Override
    public boolean onUnbind(Intent intent) {
        Log.d("MyService", "onUnbind");
        return super.onUnbind(intent);
    }

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

    @Override
    public IBinder onBind(Intent intent) {
        Log.d("MyService", "onBind");
        return mBinder;
    }

    class DownloadBinder extends Binder{
        public void startDownload(){
            Log.d("MyService" ,"DownloadBinder-startDownload");
        }



        public int getProgress(){
            Log.d("MyService" ,"DownloadBinder-getProgress");
            return 1;
        }
    }
}
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
    private MyService.DownloadBinder downloadBinder;
    private ServiceConnection connection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            Log.d("MainActivity" ,"onServiceConnected");
            downloadBinder = (MyService.DownloadBinder)(service);
            downloadBinder.startDownload();
            downloadBinder.getProgress();
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            Log.d("MainActivity" ,"onServiceDisconnected");
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Button startBtn = (Button)(findViewById(R.id.start_service));
        startBtn.setOnClickListener(this);
        Button stopBtn = (Button)(findViewById(R.id.stop_service));
        stopBtn.setOnClickListener(this);
        Button bindBtn = (Button)(findViewById(R.id.bind_service));
        bindBtn.setOnClickListener(this);
        Button unBindBtn = (Button)(findViewById(R.id.unbind_service));
        unBindBtn.setOnClickListener(this);
        Button startIntentBtn = (Button)(findViewById(R.id.start_intentservice));
        startIntentBtn.setOnClickListener(this);
    }

    @Override
    //startService和stopService是在Context类中定义的
    public void onClick(View v){
        switch(v.getId()){
            case R.id.start_service:
                Intent startIntent = new Intent(this ,MyService.class);
                startService(startIntent);//启动服务
                break;
            case R.id.stop_service:
                Intent stopIntent = new Intent(this ,MyService.class);
                stopService(stopIntent);//停止服务
                Log.d("MainActivity" ,"stopService");
                break;
            case R.id.bind_service:
                Intent bindIntent = new Intent(this ,MyService.class);
                Log.d("MainActivity" ,"bindService");
                bindService(bindIntent ,connection ,BIND_AUTO_CREATE);//绑定服务
                break;
            case R.id.unbind_service:
                Log.d("MainActivity" ,"onClick-R.id.unbind_service");
                unbindService(connection);//解绑定服务
                break;
            case R.id.start_intentservice:
                Log.d("MainActivity" ,"current_id =" + Thread.currentThread().getId());
                Intent intentService = new Intent(this ,MyIntentService.class);
                startService(intentService);
                break;
            default:
               break;
        }
    }

1.2 类图关系

Android 服务启动和绑定

1.3 测试运行时序

Android 服务启动和绑定

1、点击按钮Start启动服务

2、点击按钮绑定服务

3、点击unbind服务

4、点击服务---Strat服务后再调用Binder服务,需要先unbind服务,然后再调用stop服务,才能运行服务的onDestory销毁服务

Android 服务启动和绑定

1.4 服务生命周期

   一旦在项目的任何位置调用了Context的startService方法,相应的服务就会启动起来,并回调

onStartCommand()方法。如果这个服务之前还没有创建过,onCreate()方法会先于onStartCommand

方法执行。服务启动了之后会一直保持运行状态,直到stopServie或者stopSelf()方法被调用

    Note:每次调用startService()方法,onStartCommand()就会执行一次,但是实际上每个服务都只会存在一个实例。

不过调用几次straService(),只需要调用一次stopServie或者stopSelf(),服务就会停止下来

    当调用了startService之后,又去调用stopService,服务中的onDestory就会执行,表示服务已经销毁。类似地,当

调用了bindService后,又去调用unbindService,onDestory也会执行。

    如果调用了startService之后,又调用了bindService,则需要同时调用stopService和unbindService,onDestory才会执行。 

Android 服务启动和绑定 

 2、服务中bind绑定服务

public class MyService extends Service {
    public static final String MYSERVICE_STOP_FLAG = "MyService_tag";
    private DownloadBinder mBinder;
    @Override
    public void onCreate(){
        super.onCreate();
        Log.d("MyService" ,"onCreate");
        Intent intent = new Intent(this ,MainActivity.class);
        PendingIntent pi = PendingIntent.getActivity(this ,0 ,intent ,0);
        Notification notification = new NotificationCompat.Builder(this)
                .setContentText("This is Text!")
                .setContentTitle("This is Title!")
                .setWhen(System.currentTimeMillis())
                .setSmallIcon(R.mipmap.ic_launcher)
                .setLargeIcon(BitmapFactory.decodeResource(getResources() ,R.mipmap.ic_launcher))
                .setContentIntent(pi)
                .build();
        startForeground(1 ,notification);
        mBinder = new DownloadBinder();
    }
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.d("MyService", "onStartCommand");
        if (intent == null) {
            Log.d("MyService", "onStartCommand ignoring null intent.");
            return 2;
        }

        if (intent.getBooleanExtra(MYSERVICE_STOP_FLAG, false)){//stop  MyService时先stop MyServiceConn服务
            Intent stopIntentConn = new Intent(this, MyServiceConn.class);
            stopIntentConn.putExtra(MyServiceConn.MYSERVICECONN_STOP_FLAG, true);
            startService(stopIntentConn);
        }else{//Start  MyService时先Start MyServiceConn服务
            Intent startIntent = new Intent(this ,MyServiceConn.class);
            startService(startIntent);//启动服务
        }
        return 1;
    }
    @Override
    public boolean onUnbind(Intent intent) {
        Log.d("MyService", "onUnbind");
        return super.onUnbind(intent);
    }
    @Override
    public void onDestroy(){
        Log.d("MyService" ,"onDestroy");
        super.onDestroy();
    }
    @Override
    public IBinder onBind(Intent intent) {
        Log.d("MyService", "onBind");
        return mBinder;
    }

    class DownloadBinder extends Binder{
        public void startDownload(){
            Log.d("MyService" ,"DownloadBinder-startDownload");
        }
        public int getProgress(){
            Log.d("MyService" ,"DownloadBinder-getProgress");
            return 1;
        }
    }
}
public class MyServiceConn extends Service {
    public static final String MYSERVICECONN_STOP_FLAG = "MyServiceConn_tag";
    private MyServiceClient myServiceClient;
    public MyServiceConn() {
    }
    @Override
    public IBinder onBind(Intent intent) {
        Log.d("MyServiceConn" ,"onBind");
        // TODO: Return the communication channel to the service.
        throw new UnsupportedOperationException("Not yet implemented");
    }
    @Override
    public void onCreate() {
        super.onCreate();
        Log.d("MyServiceConn" ,"onCreate");//在MyServiceConn服务里面绑定MyService
        myServiceClient = new MyServiceClient(this);
    }
    @Override
    public int onStartCommand(Intent intent, int falgs ,int startId){
        Log.d("MyServiceConn" ,"onStartCommand falgs = " + falgs);
        boolean flag = intent.getBooleanExtra(MYSERVICECONN_STOP_FLAG,
                false);
        Log.d("MyServiceConn" ,"flag = " + flag);
        if (intent != null && intent.getBooleanExtra(MYSERVICECONN_STOP_FLAG,
                false)) {
            Log.d("MyServiceConn" ,"stopSelf");
            stopSelf();
            return 0;
        }
        return 0;
    }



    @Override
    public void onDestroy(){
        Log.d("MyServiceConn" ,"onDestroy");
        super.onDestroy();
        try {
            Thread.sleep(2);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        Log.d("MyServiceConn" ,"onDestroy end");
    }
}
public class MyServiceClient {
    private Context mContext;
    private MyService.DownloadBinder downloadBinder;
    public MyServiceClient(Context context){
        mContext = context;
        doBind();
    }

    private ServiceConnection connection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            Log.d("MyServiceClient" ,"onServiceConnected");
            downloadBinder = (MyService.DownloadBinder)(service);
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            Log.d("MyServiceClient" ,"onServiceDisconnected");
        }
    };


    public boolean doBind(){
        Intent bindIntent = new Intent(mContext ,MyService.class);
        Log.d("MyServiceClient" ,"bindService");
        mContext.bindService(bindIntent ,connection ,BIND_AUTO_CREATE);//绑定服务
        return true;
    }
}

2.1 类图

Android 服务启动和绑定

2.2 调用时序

Android 服务启动和绑定

 

如果服务里面有绑定其他服务,在stop该服务之前需要先unbinder其他服务,否则在stop运行onDestory销毁服务时,会报错servicetest.MyServiceConn has leaked ServiceConnection [email protected] that was originally bound here

比如MyServiceConn服务里面,Start服务创建MyService时创建MyServiceClient

public void onCreate() {
    super.onCreate();
    Log.d("MyServiceConn" ,"onCreate");
    myServiceClient = new MyServiceClient(this);
}

而MyServiceClient中有去绑定了MyService服务。所以当停止MyServiceConn服务时,如果没有unbinder MyService,就会出现上面的错误。