1.先讲讲怎么使用bindService()绑定服务
应用组件(客户端)可以调用bindService()绑定到一个service.Android系统之后调用service的onBind()方法,它返回一个用来与service交互的IBinder
绑定是异步的.bindService()会立即返回,它不会返回IBinder给客户端.要接收IBinder,客户端必须创建一个ServiceConnection的实例并传
给bindService().ServiceConnection包含一个回调方法,系统调用这个方法来传递要返回的IBinder.
注:只有activities,services,和contentproviders可以绑定到一个service—你不能从一个broadcastreceiver绑定到service.
所以,从你的客户端绑定到一个service,你必须:
1实现ServiceConnection.
你的实现必须重写两个回调方法:
onServiceConnected()
系统调用这个来传送在service的onBind()中返回的IBinder.
OnServiceDisconnected()
Android系统在同service的连接意外丢失时调用这个.比如当service崩溃了或被强杀了.当客户端解除绑定时,这个方法不会被调用.
2调用bindService(),传给它ServiceConnection的实现.
3当系统调用你的onServiceConnected()方法时,你就可以使用接口定义的方法们开始调用service了.
4要与service断开连接,调用unbindService().
当你的客户端被销毁,它将从service解除绑定,但是你必须总是在你完成与service的交互时或当你的activity暂停于是service在不被使用时可以关闭此两种情况下解
除绑定.(下面会讨论更多在适当的时候绑定和解除绑定的问题.
使用这个ServiceConnection,客户端可以绑定到一个service,通过把它传给bindService().例如:
Intentintent = new Intent(this, LocalService.class);
bindService(intent,mConnection, Context.BIND_AUTO_CREATE);
第一个bindService()的参数是一个明确指定了要绑定的service的Intent.
第二个参数是ServiceConnection对象.
第三个参数是一个标志,它表明绑定中的操作.它一般应是BIND_AUTO_CREATE,这样就会在service不存在时创建一个.其它可选的值是BIND_DEBUG_UNBIND和BIND_NOT_FOREGROUND,不想指定时设为0即可.。
下面是一些关于绑定到service的重要事项:
你总是需要捕获DeadObjectException异常.它会在连接被打断时抛出.这是被远程方法抛出的唯一异常.
对象引用计数是跨进程的作用的.
你应该在客户端的生命期内使绑定和解除绑定配对进行,例如:
如果你需要在你的activity可见时与service交互,你应该在onStart()绑定并在onStop()中解除绑定.
如果你想让你的activity即使在它停止时也能接收回应,那么你可以在onCreate()中绑定并在onDestroy()中解除绑定.注意这意味着你的activity需要使用在自己整
个运行期间使用service(即使位于后台),所以如果service在另一个进程中,那么你增加了这个进程的负担而使它变得更容易被系统杀掉.
注:你一般不应该在你的activity的onResume()和onPause()中绑定和解除绑定到service,因为这些回调方法,出现在每个生命期变化中,并且你需要使发生在这
些变化中的处理最小化.还有,如果你应用中的多个activity绑定到同一个service,并且有一个变化发生在其中两个activity之间,service可能在当前activity解除绑
定(pause中)和下一个绑定前(rusume中)被销毁又重建.
当一个service的所有客户端都解除绑定,Android系统就销毁它(除非它是从onStartCommand()启动).如果你的service是一个纯boundservice,你不需管理它的生命
期—Android系统会为你管理它.。
然而,如果你选择了实现onStartCommand()回调方法,那么你必须明确地停止service,因为service现在被认为是"开始的".在此情况下,service会一直运行,直
到service使用stopSelf()停止它自己或另外的组件调用了stopService()停止了它,不管是否有客户端绑定了它.
另外,如果你的service已经启动并且接受绑定,那么当系统调用你的onUnbind()方法,你可以选择返回true表示你想在客户端下一次绑定到service时接受一个
对onRebind()的调用(而不是一个对onBind()的调用).onRebind()返回void,但是客户端依然会在它的onServiceConnected()回调中接收到IBinder.下图演示了这种生命其的
逻辑:
3。bindService和startService混合使用时
1.如果先bindService,再startService:
在bind的Activity退出的时候,Service会执行unBind方法而不执行onDestory方法,因为有startService方法调用过,所以Activity与Service解除绑定后会有一个与调用者没有关连的Service存在
2.如果先bindService,再startService,再调用Context.stopService
Service的onDestory方法不会立刻执行,因为有一个与Service绑定的Activity,但是在Activity退出的时候,会执行onDestory,如果要立刻执行stopService,就得先解除绑定
---------------------------
把上面的"如果先bindService,再startService"换成"如果先startService,再bindService",结果是一样的
问题:
如果在一个Activity的onCreate方法中,
先
bindService(serviceIntent, conn, Context.BIND_AUTO_CREATE);
再startService(serviceIntent);
退出这个Activity时,会执行onUnBind
但是再次进入这个Activity的时候,为什么不执行onBind方法了?只有在这个Service销毁后(执行onDestory),再进这个Activity才会执行onBind,还有就是当有两个客户端时,在第一个客户端startServie启动服务再bindService绑定服务,这时跳到第二个客户端里(启动时会调用onBind()),再客户端startServie启动服务再bindService绑定服务,启动时不会调用用onBind()了(因为之前客户端已经启动后没有onDestory()销毁Service,所以再客户端第二次绑定服务时,只会返回IBinder对象给onServiceConnected()),而且要注意的是当,当第一个服务启动并绑定一个服务时,再跳去第二个服务端启动并绑定这个服务时,第二个服务端再解绑时,不会调用onUnbind(),只有回到第一个客户端时,解绑这是才会调用onUnbind(),顺序反过来结果是一样的。得出一个结论是:当一个服务没被onDestory()销毁之前,只有第一个启动它的客户端能调用它的onBind()和onUnbind()
package yy.android.service; import org.apache.http.conn.ClientConnectionManager; import android.app.Activity; import android.content.ComponentName; import android.content.Intent; import android.content.ServiceConnection; import android.content.SharedPreferences.Editor; import android.os.Binder; import android.os.Bundle; import android.os.IBinder; import android.util.Log; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.EditText; import android.widget.TextView; public class ServiceActivity extends Activity { // private final String TAG = "ServiceActivity"; private Button unbind; public static IService iService=null; private Button mSkiptoClient; private Button mStart; public static EditText medit; private Button mBind; private Button mStop; public static ServiceConnection connection=new ServiceConnection() { public void onServiceDisconnected(ComponentName name) { Log.d("LOG","Activity ->Disconnected the LocalService"); } public void onServiceConnected(ComponentName name, IBinder service) { // TODO Auto-generated method stub //获取连接的服务对象 //System.out.println("Connection!!!"); iService=(IService)service; medit.setText(iService.getName()); Log.d("LOG","Activity ->Connected the Service"); } }; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); Log.d("LOG","Activity ->OnCreate"); unbind = (Button)findViewById(R.id.unbind); mSkiptoClient = (Button)findViewById(R.id.skip); mStart = (Button)findViewById(R.id.start); mStop = (Button )findViewById(R.id.stop); medit = (EditText)findViewById(R.id.edit); mBind = (Button)findViewById(R.id.connection); mBind.setOnClickListener(new OnClickListener() { public void onClick(View v) { // TODO Auto-generated method stub Intent intent=new Intent(ServiceActivity.this,LocalService.class); bindService(intent,connection, BIND_AUTO_CREATE); } }); mStart.setOnClickListener(new OnClickListener() { public void onClick(View v) { // TODO Auto-generated method stub Intent intent=new Intent(ServiceActivity.this,LocalService.class); startService(intent); } }); mStop.setOnClickListener(new OnClickListener() { public void onClick(View v) { // TODO Auto-generated method stub Intent intent=new Intent(ServiceActivity.this,LocalService.class); stopService(intent); } }); mSkiptoClient.setOnClickListener(new OnClickListener() { public void onClick(View v) { Intent intent = new Intent("android.intent.action.YClient"); startActivity(intent); } }); unbind.setOnClickListener(new OnClickListener() { public void onClick(View v) { // TODO Auto-generated method stub unbindService(connection); } }); } @Override protected void onDestroy() { // TODO Auto-generated method stub super.onDestroy(); Log.d("LOG","Activity ->OnDestory"); } @Override protected void onPause() { // TODO Auto-generated method stub // unbindService(connection); Log.d("LOG","Activity ->OnPause"); super.onPause(); } @Override protected void onRestart() { // TODO Auto-generated method stub super.onRestart(); Log.d("LOG","Activity ->OnRestart"); } @Override protected void onResume() { // TODO Auto-generated method stub Log.d("LOG","Activity ->OnResume"); // Intent intent=new Intent(ServiceActivity.this,LocalService.class); // bindService(intent,connection, BIND_AUTO_CREATE); super.onResume(); } protected void onStart() { // TODO Auto-generated method stub super.onStart(); Log.d("LOG","Activity ->OnSatrt"); } @Override protected void onStop() { // TODO Auto-generated method stub super.onStop(); Log.d("LOG","Activity ->OnStop"); } } //////////////////////////////////////////////////////////////////////////// package yy.android.service; import android.app.Activity; import android.content.ComponentName; import android.content.Intent; import android.content.ServiceConnection; import android.os.Bundle; import android.os.IBinder; import android.util.Log; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.EditText; public class CLient extends Activity{ private IService iService2=null; private Button unbind2; private Button mStart2; private EditText medit2; private Button mBind2; private Button mStop2; ServiceConnection connection2=new ServiceConnection() { public void onServiceDisconnected(ComponentName name) { Log.d("LOG","Client ->Disconnected the LocalService"); } public void onServiceConnected(ComponentName name, IBinder service) { // TODO Auto-generated method stub //获取连接的服务对象 //System.out.println("Connection!!!"); iService2=(IService)service; medit2.setText(iService2.getName()); Log.d("LOG","Client ->Connected the Service"); } }; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.client); Log.d("LOG","Client ->OnCreate"); unbind2 = (Button)findViewById(R.id.unbind2); mStart2 = (Button)findViewById(R.id.start2); mStop2 = (Button )findViewById(R.id.stop2); medit2 = (EditText)findViewById(R.id.edit2); mBind2 = (Button)findViewById(R.id.connection2); mBind2.setOnClickListener(new OnClickListener() { public void onClick(View v) { // TODO Auto-generated method stub Intent intent=new Intent(CLient.this,LocalService.class); bindService(intent,connection2, BIND_AUTO_CREATE); } }); mStart2.setOnClickListener(new OnClickListener() { public void onClick(View v) { // TODO Auto-generated method stub Intent intent=new Intent(CLient.this,LocalService.class); startService(intent); } }); mStop2.setOnClickListener(new OnClickListener() { public void onClick(View v) { // TODO Auto-generated method stub Intent intent=new Intent(CLient.this,LocalService.class); stopService(intent); } }); unbind2.setOnClickListener(new OnClickListener() { public void onClick(View v) { // TODO Auto-generated method stub Log.e("LOG", "Unbind"); unbindService(connection2); Log.e("LOG", "Unbind"); } }); } @Override protected void onDestroy() { // TODO Auto-generated method stub //unbindService(connection2); Log.d("LOG","Client ->OnDestory"); super.onDestroy(); } @Override protected void onPause() { // TODO Auto-generated method stub super.onPause(); Log.d("LOG","Client ->OnPause"); } @Override protected void onRestart() { // TODO Auto-generated method stub super.onRestart(); Log.d("LOG","Client ->OnRestart"); } @Override protected void onResume() { // TODO Auto-generated method stub super.onResume(); Log.d("LOG","Client ->OnResume"); } @Override protected void onStart() { // TODO Auto-generated method stub super.onStart(); Log.d("LOG","Client ->OnSatrt"); } @Override protected void onStop() { // TODO Auto-generated method stub super.onStop(); Log.d("LOG","Client ->OnStop"); } } /////////////////////////////////////////////////////////////////// package yy.android.service; import android.app.Service; import android.content.Intent; import android.os.Binder; import android.os.IBinder; import android.util.Log; public class LocalService extends Service{ private MyBind myBind=new MyBind(); public IBinder onBind(Intent intent) { //System.out.println("Service onBind!!!"); Log.d("LOG","LocalService ->onBind"); return myBind; } @Override public void onCreate() { // TODO Auto-generated method stub Log.d("LOG","LocalService ->onCreate"); super.onCreate(); } @Override public void onDestroy() { // TODO Auto-generated method stub Log.d("LOG","LocalService ->onDestory"); super.onDestroy(); } @Override public void onStart(Intent intent, int startId) { // TODO Auto-generated method stub Log.d("LOG","LocalService ->onSatrt"); super.onStart(intent, startId); } @Override public boolean onUnbind(Intent intent) { // TODO Auto-generated method stub Log.d("LOG","LocalService ->onUnbind"); return super.onUnbind(intent); //return true; } @Override public void onRebind(Intent intent) { // TODO Auto-generated method stub Log.d("LOG","LocalService ->onRebind"); super.onRebind(intent); } public class MyBind extends Binder implements IService{ public String getName() { // TODO Auto-generated method stub return "YUZHIBOYI"; } } }
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="yy.android.service" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="10" /> <application android:icon="@drawable/ic_launcher" android:label="@string/app_name" > <activity android:name=".ServiceActivity" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <activity android:name=".CLient" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.YClient" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> </activity> <service android:name=".LocalService"> <intent-filter> <action android:name="com.yy.yy"/> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> </service> </application> </manifest> ///////////////////////////////////////////////////////// <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <EditText android:id="@+id/edit2" android:layout_width="fill_parent" android:layout_height="wrap_content" ></EditText> <Button android:id = "@+id/connection2" android:layout_width = "wrap_content" android:layout_height = "wrap_content" android:text = "@string/Bind" /> <Button android:id = "@+id/start2" android:layout_width = "wrap_content" android:layout_height = "wrap_content" android:text = "@string/Start" /> <Button android:id = "@+id/stop2" android:layout_width = "wrap_content" android:layout_height = "wrap_content" android:text = "@string/StopService" /> <Button android:id = "@+id/unbind2" android:layout_width = "wrap_content" android:layout_height = "wrap_content" android:text = "@string/UnbindService" /> </LinearLayout> ////////////////////////////////////////////////////// <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > <EditText android:id="@+id/edit" android:layout_width="fill_parent" android:layout_height="wrap_content" ></EditText> <Button android:id = "@+id/connection" android:layout_width = "wrap_content" android:layout_height = "wrap_content" android:text = "@string/Bind" /> <Button android:id = "@+id/start" android:layout_width = "wrap_content" android:layout_height = "wrap_content" android:text = "@string/Start" /> <Button android:id = "@+id/stop" android:layout_width = "wrap_content" android:layout_height = "wrap_content" android:text = "@string/StopService" /> <Button android:id = "@+id/skip" android:layout_width = "wrap_content" android:layout_height = "wrap_content" android:text = "@string/Skip" /> <Button android:id = "@+id/unbind" android:layout_width = "wrap_content" android:layout_height = "wrap_content" android:text = "@string/UnbindService" /> </LinearLayout>