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 类图关系
1.3 测试运行时序
1、点击按钮Start启动服务
2、点击按钮绑定服务
3、点击unbind服务
4、点击服务---Strat服务后再调用Binder服务,需要先unbind服务,然后再调用stop服务,才能运行服务的onDestory销毁服务
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才会执行。
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 类图
2.2 调用时序
如果服务里面有绑定其他服务,在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,就会出现上面的错误。