Android笔记二十八.Service组件入门(二).绑定本地Service并与之通信

绑定本地Service通信
本文介绍如何通过bindService方法实现Android中Service与客户端的绑定及通信过程。包括ServiceConnection的使用、IBinder对象的创建与传递,以及客户端如何通过IBinder与Service交互。
绑定本地Service并与之通信
转载请表明出处:http://blog.youkuaiyun.com/u012637501
   通过上一篇博文的前3步,我们就算完成了一个Service及使用该Service的应用程序(Service为该应用程序的组成部分)。但当程序通过startService()和stopService()启动、关闭Service时,Service与访问者之间基本上不存在太多的关联,因此Service和访问者之间也无法进行通信、数据交换。如果我们希望开发的Service能与访问者之间实现方法调用或数据交换,我们可以让访问者使用bindService()和unbindService()方法启动、关闭Service,从而实现访问者与本地Service之间的绑定。
1.启动Service方法
Context.bindService(Intent service,ServiceConnection conn,int flags)
参数说明:
service:该参数用于设置Activity通过Intent指定启动哪个Service;
conn:该参数是一个ServiceConnection对象,该对象用于监听访问者与Service之间的连接情况。当访问者与Service之间连接成功时将回调该ServiceConnection对象的onServiceConnected(ComponentName name,IBinder service)方法;当Service所在的宿主进程由于异常中止或由于其他原因终止,导致该Service与访问者之间断开连接时回调ServiceConnection对象的onServiceDisconnected(ComponentName name)方法
注意:当调用者主动通过unBindService()方法断开与Service的连接时,ServiceConnection对象的onServiceDisconnected(ComponentName name)方法并不会被调用。
flags:指定绑定时是否自动创建Service(如果Service还未创建)。flags=0,不自动创建;flags=BIND_AUTO_CREATE,自动创建。

2.源码分析
(1)在Service子类中,通过继承Binder的方式实现IBinder类并声明一个IBinder对象;
(2)当访问者绑定该Service后,Service通过onBind()方法返回一个IBinder对象给访问者;
(3)在访问者子类中,当访问者与Service连接成功将回调ServiceConnection对象的onServiceConnected(ComponentName name,IBinder service)方法来获取Service的onBind方法所返回的Binder子类对象,该IBinder对象可访问该Service状态数据,即count的值。

3.源码实战
(1)/com/exanple/android_service_bind/BindService.java
功能:实现一个Service子类,并再其实现一个IBinder内部类和一个线程
[java]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. <span style="font-family:Times New Roman;font-size:18px;">package com.example.android_service_bind;  
  2. import android.app.Service;  
  3. import android.content.Intent;  
  4. import android.os.Binder;  
  5. import android.os.IBinder;  
  6. public class BindService extends Service {  
  7.  private int count;  
  8.  private boolean quit;  
  9.  private MyIBinder binder=new MyIBinder();  //声明一个IBinder对象  
  10.  //1.定义一个IBinder子类并实现一个获取Service运行状态(count)的方法  
  11.  public class MyIBinder extends Binder  
  12.  {  
  13.   public int getCount()  
  14.   {  
  15.    return count;     //返回Service运行状态:count  
  16.   }  
  17.  }  
  18.  //2.Service子类必须实现的一个类,用于返回IBinder对象  
  19.  public IBinder onBind(Intent intent) {  
  20.   System.out.println("Service is Binded!");  
  21.   return binder;    //返回IBinder对象  
  22.  }  
  23.  //3.Service被创建时回调该方法  
  24.  @Override  
  25.  public void onCreate() {  
  26.   super.onCreate();  
  27.   System.out.println("Service is Created.");  
  28.   //创建并启动一个线程,实现动态修改count状态值  
  29.   new Thread()  
  30.   {  
  31.    @Override  
  32.    public void run()  
  33.    {  
  34.     while(!quit)    //标识Service关闭启动状态  
  35.     {  
  36.      try  
  37.      {  
  38.       Thread.sleep(1000);  
  39.      }catch(InterruptedException e)  
  40.      {  
  41.      }  
  42.      count++;  
  43.     }  
  44.    }  
  45.   }.start();  
  46.  }  
  47.  //4.Service被断开连接时回调方法  
  48.  @Override  
  49.  public boolean onUnbind(Intent intent) {  
  50.   System.out.println("Service is Unbinded");  
  51.   return true;  
  52.  }  
  53.  //5.Service被关闭之前回调该方法  
  54.  @Override  
  55.  public void onDestroy() {  
  56.   super.onDestroy();  
  57.   this.quit=true;    //当调用该方法后(!quit)为假,线程结束  
  58.   System.out.println("Service is Destroy");  
  59.  }  
  60. }</span>  
(2)AndroidManifest.xml
实现:为Service子类配置一个Service组件,并为该Service组件的intent-filter配置action
[html]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. <span style="font-family:Times New Roman;font-size:18px;"><?xml version="1.0" encoding="utf-8"?>  
  2. <manifest xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     package="com.example.android_service_bind"  
  4.     android:versionCode="1"  
  5.     android:versionName="1.0" >  
  6.     <uses-sdk  
  7.         android:minSdkVersion="8"  
  8.         android:targetSdkVersion="19" />  
  9.     <application  
  10.         android:allowBackup="true"  
  11.         android:icon="@drawable/ic_launcher"  
  12.         android:label="@string/app_name"  
  13.         android:theme="@style/AppTheme" >  
  14.         <activity  
  15.             android:name=".BindServiceTest"  
  16.             android:label="@string/app_name" >  
  17.             <intent-filter>  
  18.                 <action android:name="android.intent.action.MAIN" />  
  19.                 <category android:name="android.intent.category.LAUNCHER" />  
  20.             </intent-filter>  
  21.         </activity>  
  22.        <!-- 配置一个Service组件 -->  
  23.        <service android:name=".BindService">  
  24.         <intent-filter>  
  25.              <!-- 为该Service组件的intent-filter配置action -->  
  26.              <action android:name="com.example.service.BIND_SERVICE"/>  
  27.         </intent-filter>  
  28.        </service>  
  29.       </application>  
  30. </manifest></span>  
(3)/com/exanple/android_service_bind/BindServiceTest.java
实现:定义一个ServiceConnection对象,通过该对象的onServiceConnected()方法获取Service返回的IBinder对象,并通过Intent对象启动和绑定指定Service。
[java]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. <span style="font-family:Times New Roman;font-size:18px;">package com.example.android_service_bind;  
  2. import android.app.Activity;  
  3. import android.app.Service;  
  4. import android.content.ComponentName;  
  5. import android.content.Intent;  
  6. import android.content.ServiceConnection;  
  7. import android.os.Bundle;  
  8. import android.os.IBinder;  
  9. import android.view.View;  
  10. import android.view.View.OnClickListener;  
  11. import android.widget.Button;  
  12. import android.widget.Toast;  
  13. public class BindServiceTest extends Activity {  
  14.  Button bind,unbind,status;  
  15.  //1.保持所启动的Service的IBinder对象  
  16.  BindService.MyIBinder binder;  
  17.  //2.定义一个ServiceConnection对象  
  18.  private ServiceConnection conn = new ServiceConnection()  
  19.  {  
  20.   //a.当该Activity与Service连接成功时回调该方法  
  21.   @Override  
  22.   public void onServiceConnected(ComponentName name  
  23.     , IBinder service)  
  24.   {  
  25.    System.out.println("---Service is connected---");  
  26.    //获取Service的onBind方法所返回的MyBinder对象  
  27.    binder=(BindService.MyIBinder)service;  
  28.   }  
  29.   //b.当该Activity与Service连接不成功时回调该方法  
  30.   @Override  
  31.   public void onServiceDisconnected(ComponentName name) {  
  32.    System.out.println("---Service is Disconnected---");  
  33.   }  
  34.  };  
  35.  @Override  
  36.  protected void onCreate(Bundle savedInstanceState) {  
  37.   super.onCreate(savedInstanceState);  
  38.   setContentView(R.layout.main);  
  39.   //a.获取程序界面中的start、stop、getServiceStatus按钮  
  40.   bind = (Button)findViewById(R.id.bind);  
  41.   unbind = (Button)findViewById(R.id.unbind);  
  42.   status = (Button)findViewById(R.id.getServiceStatus);  
  43.   //b.创建启动Service的Intent  
  44.   final Intent intent = new Intent();  
  45.   intent.setAction("com.example.service.BIND_SERVICE");  
  46.   //c.绑定指定Service  
  47.   bind.setOnClickListener(new OnClickListener(){  
  48.    @Override  
  49.    public void onClick(View v) {  
  50.     bindService(intent,conn,Service.BIND_AUTO_CREATE);  
  51.    }  
  52.   });  
  53.   //d.解除绑定的Service  
  54.   unbind.setOnClickListener(new OnClickListener(){  
  55.    @Override  
  56.    public void onClick(View v) {  
  57.     unbindService(conn);  
  58.    }  
  59.   });  
  60.   //e.获取Service的状态,显示Service的count值  
  61.   status.setOnClickListener(new OnClickListener(){  
  62.    @Override  
  63.    public void onClick(View v) {  
  64.     Toast.makeText(BindServiceTest.this,"Service的count值为:"+binder.getCount()  
  65.        , Toast.LENGTH_SHORT).show();  
  66.    }  
  67.   });  
  68.  }  
  69.    
  70. }</span>  
(4)主界面布局/res/layout/main.xml
[html]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. <span style="font-family:Times New Roman;font-size:18px;"><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  2.     android:orientation="vertical"  
  3.     android:layout_width="match_parent"  
  4.     android:layout_height="match_parent">  
  5.  <LinearLayout  
  6.      android:orientation="horizontal"  
  7.      android:layout_width="match_parent"  
  8.      android:layout_height="match_parent">  
  9.      <Button  
  10.          android:id="@+id/bind"  
  11.          android:layout_width="wrap_content"  
  12.          android:layout_height="wrap_content"  
  13.          android:layout_weight="1"  
  14.          android:text="绑定service"/>  
  15.       <Button  
  16.          android:id="@+id/unbind"  
  17.          android:layout_width="wrap_content"  
  18.          android:layout_height="wrap_content"  
  19.          android:layout_weight="1"  
  20.          android:text="解除绑定"/>  
  21.        <Button  
  22.          android:id="@+id/getServiceStatus"  
  23.          android:layout_width="wrap_content"  
  24.          android:layout_height="wrap_content"  
  25.          android:layout_weight="1"  
  26.          android:text="获取状态"/>  
  27.     </LinearLayout>  
  28. </LinearLayout></span>  

效果演示
(1)当点击绑定Service时,访问者调用bindService()方法启动指定Service并与之绑定。观察DDMS的LogCat:
(2)当点击获取Service状态时,访问者通过IBinder对象binder调用Service内部类MyIBinder的getCount()方法获取count值;
(3)当点击解除绑定后,访问者通过unbindService(ServiceConnection conn) 方法解除对某个Service的绑定时,系统会先回调该Service的onUnbind()方法,然后再回调onDestroy()方法,Service服务被关闭。


注意:这里所谓的Service状态,实际上就是在Service服务中运行的实现count值累加的一个线程(在Service的onCreate()方法中实现)。当访问者调用bindService()方法启动并绑定该Service后,这个线程开始运行且count不停的进行累加1,直到访问者解除Service的绑定。

升华笔记:关于IBinder对象?
   IBinder对象相当于Service组件的内部钩子,该钩子关联到绑定的Service组件,当其他程序组件绑定该Service时,Service子类将会把IBinder对象并返回给其他程序组件,其他程序组件通过该IBinder对象即可与Service组件进行实时通信
出生:Service采用继承Binder(IBinder的实现类)的方法实现自己的IBinder对象,由Service提供的IBinder onBinder(Intent intent)方法返回该IBinder对象,
去向:其他程序组件调用该ServiceConnection对象的onServiceConnected(ComponentName name,IBinder service)方法时,传入Service组件返回的IBinder对象,从而实现了其他程序组件与被绑定的Service之间的通信。

总结:
(1)当开发Service类时,该Service类必须提供一个onBind()方法,在绑定本地Service的情况下,onBind()方法所返回的IBinder对象将会传递给ServiceConnection对象里的onServiceConnected(ComponetName name,IBinder service)方法的service参数,这样访问者就可以通过IBinder对象与Service进行通信
(2)实际开发时通常会采用继承Binder(IBinder的实现类)的方式实现自己的IBinder对象
0
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值