配色: 字号:
Android中Service使用bindService
2017-01-18 | 阅:  转:  |  分享 
  
Android中Service使用bindService



同个app间调用(只有一次启动该服务)

BinderActicityA

[java]viewplaincopy在CODE上查看代码片派生到我的代码片

publicclassBinderActicityAextendsActivityimplementsView.OnClickListener{

privateButtonbtn1;

privateButtonbtn2;

privateButtonbtn3;

privateButtonbtn4;

privateBindServicebindService=null;

privatebooleanisBound=false;



privateServiceConnectionconn=newServiceConnection(){



@Override

publicvoidonServiceConnected(ComponentNamename,IBinderservice){

isBound=true;

BindService.MyBinderbinder=(BindService.MyBinder)service;

bindService=binder.getService();

intnum=bindService.getRandomNumber();

Log.v("hjz","numA="+num);

}



//client和service连接意外丢失时,会调用该方法

@Override

publicvoidonServiceDisconnected(ComponentNamename){

Log.v("hjz","onServiceDisconnectedA");

}

};



@Override

protectedvoidonCreate(BundlesavedInstanceState){

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_binder_main);

findLayoutView();

setLister();

initData();



}



privatevoidfindLayoutView(){

btn1=(Button)findViewById(R.id.btn1);

btn2=(Button)findViewById(R.id.btn2);

btn3=(Button)findViewById(R.id.btn3);

btn4=(Button)findViewById(R.id.btn4);

}



privatevoidsetLister(){

btn1.setOnClickListener(this);

btn2.setOnClickListener(this);

btn3.setOnClickListener(this);

btn4.setOnClickListener(this);

}



privatevoidinitData(){



}



@Override

publicvoidonClick(Viewv){

Intentintent=null;

switch(v.getId()){

caseR.id.btn1:

intent=newIntent(BinderActicityA.this,BindService.class);

intent.putExtra("from","ActivityA");

bindService(intent,conn,BIND_AUTO_CREATE);

break;

caseR.id.btn2:

if(isBound){

isBound=false;

Log.v("hjz","ActicityAisunbindService");

unbindService(conn);

}

break;

caseR.id.btn3:

intent=newIntent(this,BinderActivityB.class);

startActivity(intent);

break;

caseR.id.btn4:

this.finish();

break;

}

}



@Override

protectedvoidonDestroy(){

super.onDestroy();

Log.i("hjz","ActivityA->onDestroy");

}

}



xml

[java]viewplaincopy在CODE上查看代码片派生到我的代码片




xmlns:tools="http://schemas.android.com/tools"

android:layout_width="match_parent"

android:layout_height="match_parent"

android:paddingBottom="@dimen/activity_vertical_margin"

android:paddingLeft="@dimen/activity_horizontal_margin"

android:paddingRight="@dimen/activity_horizontal_margin"

android:paddingTop="@dimen/activity_vertical_margin"

android:orientation="vertical"

tools:context="com.hh.servicedemo.MainActivity">




android:id="@+id/btn1"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:text="BinderService绑定"/>




android:id="@+id/btn2"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:text="BinderService解绑"/>




android:id="@+id/btn3"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:text="跳转到BinderActivityB"/>




android:id="@+id/btn4"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:text="finish"/>









BinderService

[java]viewplaincopy在CODE上查看代码片派生到我的代码片

publicclassBindServiceextendsService{



publicclassMyBinderextendsBinder{



publicBindServicegetService(){

returnBindService.this;

}

}

//通过binder实现了调用者(client)与service之间的通信

privateMyBinderbinder=newMyBinder();



privatefinalRandomgenerator=newRandom();



@Override

publicvoidonCreate(){

super.onCreate();

Log.i("hjz","BindService->onCreate,Thread:"+Thread.currentThread().getName());

}



@Override

publicIBinderonBind(Intentintent){

Log.i("hjz","BindService->onBind,Thread:"+Thread.currentThread().getName());

returnbinder;

}



@Override

publicbooleanonUnbind(Intentintent){

Log.i("hjz","BindService->onUnbind,from:"+intent.getStringExtra("from"));

returnfalse;

}



@Override

publicintonStartCommand(Intentintent,intflags,intstartId){

Log.i("hjz","BindService->onStartCommand,startId:"+startId+",Thread:"+Thread.currentThread().getName());

returnSTART_NOT_STICKY;

}



@Override

publicvoidonDestroy(){

Log.i("hjz","BindService->onDestroy,Thread:"+Thread.currentThread().getName());

super.onDestroy();

}



//在Service中暴露出去的方法,供client调用

publicintgetRandomNumber(){

returngenerator.nextInt();

}

}



点击BinderService绑定,再点击BinderService解绑,最后点击finish,打印日志

[java]viewplaincopy在CODE上查看代码片派生到我的代码片

07-0911:46:49.36029714-29714/com.hh.servicedemoI/hjz:BindService->onCreate,Thread:main

07-0911:46:49.36029714-29714/com.hh.servicedemoI/hjz:BindService->onBind,Thread:main

07-0911:46:49.38029714-29714/com.hh.servicedemoV/hjz:numA=1859239539

07-0911:46:50.65029714-29714/com.hh.servicedemoV/hjz:ActicityAisunbindService

07-0911:46:50.65029714-29714/com.hh.servicedemoI/hjz:BindService->onUnbind,from:ActivityA

07-0911:46:50.65029714-29714/com.hh.servicedemoI/hjz:BindService->onDestroy,Thread:main

07-0911:46:52.29029714-29714/com.hh.servicedemoI/hjz:ActivityA->onDestroy



点击BinderService绑定,再点击finish

[java]viewplaincopy在CODE上查看代码片派生到我的代码片

07-0911:48:07.26029714-29714/com.hh.servicedemoI/hjz:BindService->onCreate,Thread:main

07-0911:48:07.26029714-29714/com.hh.servicedemoI/hjz:BindService->onBind,Thread:main

07-0911:48:07.27029714-29714/com.hh.servicedemoV/hjz:numA=-341510490

07-0911:48:09.29029714-29714/com.hh.servicedemoI/hjz:ActivityA->onDestroy

07-0911:48:09.31029714-29714/com.hh.servicedemoI/hjz:BindService->onUnbind,from:ActivityA

07-0911:48:09.31029714-29714/com.hh.servicedemoI/hjz:BindService->onDestroy,Thread:main



先从BinderService来分析,从打印可以看出,先调用onCreate,接着在调用onBind方法,你会发现使用binderStart来启动,onStartCommand这方法不调用;在Service中执行顺序:

1、先得到相应的binder对象,可以在Service内部用内部类得到相应的binder,如下所示:

[java]viewplaincopy在CODE上查看代码片派生到我的代码片

publicclassMyBinderextendsBinder{



publicBindServicegetService(){

returnBindService.this;

}

}

//通过binder实现了调用者(client)与service之间的通信

privateMyBinderbinder=newMyBinder();

2、在onBind方法中返回IBinder实例,返回实例可以是Service实例本身或者通过binder暴露出Service公共方法。通常情况下,就是讲binder弄成Service内部类,然后在binder中创建一个类似getService的方法并返回包含binder的Service对象,如上面那种情况,这样client(客户端)可以通过该方法得到相应的Service实例



接着调用者(client客户端)执行的流程

1、先创建ServiceConnetion实例,并重写其方法,如下面所示:

[java]viewplaincopy在CODE上查看代码片派生到我的代码片

//创建ServiceCowww.baiyuewang.netnnection类型的实例

privateServiceConnectionconn=newServiceConnection(){



@Override

publicvoidonServiceConnected(ComponentNamename,IBinderservice){

isBound=true;

BindService.MyBinderbinder=(BindService.MyBinder)service;

bindService=binder.getService();

intnum=bindService.getRandomNumber();

Log.v("hjz","numA="+num);

}



//client和service连接意外丢失时,会调用该方法

@Override

publicvoidonServiceDisconnected(ComponentNamename){

Log.v("hjz","onServiceDisconnectedA");

}

};

这是因为使用bindServer中使用到该对象,bindServer源码

[java]viewplaincopy在CODE上查看代码片派生到我的代码片

@Override

publicbooleanbindService(Intentservice,ServiceConnectionconn,

intflags){//调用bindServer,发现第二个传参就是ServiceConnection对象

returnmBase.bindService(service,conn,flags);

}



2、当执行了onServiceConnected回调时,我们可以通过IBinder实例得到Service实例对象或直接调用binder公共方法,这样就实现了client和service的连接

3、client和Service解除绑定时,onServiceDisconnected并不会被调用;onServiceDisconnected被调用的情况是发生在client和Service连接意外丢失时,这时client和Service一定是断开连接了。



同个app间调用(多次调用该服务)

BinderAcivityB

[java]viewplaincopy在CODE上查看代码片派生到我的代码片

publicclassBinderActivityBextendsActivityimplementsView.OnClickListener{

privateButtonbtn1;

privateButtonbtn2;

privateButtonbtn4;



privateBindServicebindService=null;

privatebooleanisBound=false;



privateServiceConnectionconn=newServiceConnection(){



@Override

publicvoidonServiceConnected(ComponentNamename,IBinderservice){

isBound=true;

BindService.MyBinderbinder=(BindService.MyBinder)service;

bindService=binder.getService();

intnum=bindService.getRandomNumber();

Log.v("hjz","numB="+num);

}



@Override

publicvoidonServiceDisconnected(ComponentNamename){

Log.v("hjz","onServiceDisconnectedB");

}

};



@Override

protectedvoidonCreate(BundlesavedInstanceState){

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_binder_b);

findLayoutView();

setLister();

initData();



}



privatevoidfindLayoutView(){

btn1=(Button)findViewById(R.id.btn1);

btn2=(Button)findViewById(R.id.btn2);

btn4=(Button)findViewById(R.id.btn4);

}



privatevoidsetLister(){

btn1.setOnClickListener(this);

btn2.setOnClickListener(this);

btn4.setOnClickListener(this);

}



privatevoidinitData(){



}



@Override

publicvoidonClick(Viewv){

Intentintent=null;

switch(v.getId()){

caseR.id.btn1:

intent=newIntent(BinderActivityB.this,BindService.class);

intent.putExtra("from","ActivityB");

bindService(intent,conn,BIND_AUTO_CREATE);

break;

caseR.id.btn2:

if(isBound){

isBound=false;

Log.v("hjz","ActicityBisunbindService");

unbindService(conn);

}

break;

caseR.id.btn4:

this.finish();

break;

}

}



@Override

protectedvoidonDestroy(){

super.onDestroy();

Log.i("hjz","ActivityB->onDestroy");

}

}

在binderA中,点击binderA绑定→跳转BinderAcitivityB→binderB绑定→binderB解绑→BinderBfinish→BinderA解绑→BinderAfinish的日志

[java]viewplaincopy在CODE上查看代码片派生到我的代码片

07-0913:16:10.0308593-8593/com.hh.servicedemoI/hjz:BindService->onCreate,Thread:main

07-0913:16:10.0308593-8593/com.hh.servicedemoI/hjz:BindService->onBind,Thread:main

07-0913:16:10.0508593-8593/com.hh.servicedemoV/hjz:numA=665064614

07-0913:16:13.6508593-8593/com.hh.servicedemoV/hjz:numB=1116469133

07-0913:16:16.5508593-8593/com.hh.servicedemoV/hjz:ActicityBisunbindService

07-0913:16:18.6808593-8593/com.hh.servicedemoI/hjz:ActivityB->onDestroy

07-0913:16:22.9208593-8593/com.hh.servicedemoV/hjz:ActicityAisunbindService

07-0913:16:22.9308593-8593/com.hh.servicedemoI/hjz:BindService->onUnbind,from:ActivityA

07-0913:16:22.9508593-8593/com.hh.servicedemoI/hjz:BindService->onDestroy,Thread:main

07-0913:16:25.6608593-8593/com.hh.servicedemoI/hjz:ActivityA->onDestroy

从打印日志中发现

在client(客户端)调用Service【同一个Service】情况下:

如果Service不存在,Service执行顺序是onCreate→onBind,接着client创建ServiceConnection实例并执行onServiceConnected这个方法。

如果Service已处于运行状态【说明在此之前已经在其他地方启动过该Service】,由于之前执行过的onBind回调获取IBinder实例,该IBinder实例在所有的client(客户端)之间是共享的,所以第二次执行onBind回调,直接使用上次已经获取的IBinder实例,并将其传入到与之对应的onServiceConnected方法中,标志着连接已经建立了起来,这时就有两个或者多个client(客户端)和Service绑定了。

client(客户端)执行unbindServie的流程:

client与Service解除绑定时,Service先检测是否还与其他client(客户端)与其连接→

如果没有,Service执行onUnbind方法,然后在执行onDestroy方法

如果有,Service不会执行onUnbind和onDestroy方法(从打印的日志中可以得出这样结论)



点击binderA绑定→跳转BinderAcitivityB→binderB绑定→binderB解绑→BinderBfinish→BinderAfinish的日志

[java]viewplaincopy在CODE上查看代码片派生到我的代码片

07-0913:19:58.3408297-8297/com.hh.servicedemoI/hjz:BindService->onCreate,Thread:main

07-0913:19:58.3608297-8297/com.hh.servicedemoI/hjz:BindService->onBind,Thread:main

07-0913:19:58.3608297-8297/com.hh.servicedemoV/hjz:numA=2026321547

07-0913:20:02.1908297-8297/com.hh.servicedemoV/hjz:numB=-1586530569

07-0913:20:04.1408297-8297/com.hh.servicedemoV/hjz:ActicityBisunbindService

07-0913:20:05.8208297-8297/com.hh.servicedemoI/hjz:ActivityB->onDestroy

07-0913:20:07.0808297-8297/com.hh.servicedemoI/hjz:ActivityA->onDestroy

07-0913:20:07.1108297-8297/com.hh.servicedemoI/hjz:BindService->onUnbind,from:ActivityA

07-0913:20:07.1108297-8297/com.hh.servicedemoI/hjz:BindService->onDestroy,Thread:main

结论:当client与Service通过bindServer连接起来之后,如果client(客户端)执行(onDestroy)销毁,那么client会自动与Service解除绑定。

点击binderA绑定→跳转BinderAcitivityB→binderB绑定→BinderBfinish→BinderA解绑→BinderAfinish的日志

[java]viewplaincopy在CODE上查看代码片派生到我的代码片

07-0913:17:40.3208297-8297/com.hh.servicedemoI/hjz:BindService->onCreate,Thread:main

07-0913:17:40.3208297-8297/com.hh.servicedemoI/hjz:BindService->onBind,Thread:main

07-0913:17:40.3408297-8297/com.hh.servicedemoV/hjz:numA=-1117645606

07-0913:17:43.4608297-8297/com.hh.servicedemoV/hjz:numB=1774346322

07-0913:17:44.7708297-8297/com.hh.servicedemoI/hjz:ActivityB->onDestroy

07-0913:17:56.7808297-8297/com.hh.servicedemoV/hjz:ActicityAisunbindService

07-0913:17:56.7808297-8297/com.hh.servicedemoI/hjz:BindService->onUnbind,from:ActivityA

07-0913:17:56.7808297-8297/com.hh.servicedemoI/hjz:BindService->onDestroy,Thread:main

07-0913:17:58.0608297-8297/com.hh.servicedemoI/hjz:ActivityA->onDestroy



点击binderA绑定→跳转BinderAcitivityB→binderB绑定→BinderBfinish→BinderAfinish的日志

[java]viewplaincopy在CODE上查看代码片派生到我的代码片

07-0913:21:22.8908297-8297/com.hh.servicedemoI/hjz:BindService->onCreate,Thread:main

07-0913:21:22.8908297-8297/com.hh.servicedemoI/hjz:BindService->onBind,Thread:main

07-0913:21:22.9008297-8297/com.hh.servicedemoV/hjz:numA=1947324308

07-0913:21:26.6308297-8297/com.hh.servicedemoV/hjz:numB=-1343649013

07-0913:21:27.7308297-8297/com.hh.servicedemoI/hjz:ActivityB->onDestroy

07-0913:21:29.0408297-8297/com.hh.servicedemoI/hjz:ActivityA->onDestroy

07-0913:21:29.0608297-8297/com.hh.servicedemoI/hjz:BindService->onUnbind,from:ActivityA

07-0913:21:29.0608297-8297/com.hh.servicedemoI/hjz:BindService->onDestroy,Thread:main

献花(0)
+1
(本文系thedust79首藏)