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

来源:互联网 发布:淘宝客佣金最低是多少 编辑:程序博客网 时间:2024/05/21 19:48
绑定本地Service并与之通信
转载请表明出处:http://blog.csdn.net/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内部类和一个线程
<span style="font-family:Times New Roman;font-size:18px;">package com.example.android_service_bind;import android.app.Service;import android.content.Intent;import android.os.Binder;import android.os.IBinder;public class BindService extends Service { private int count; private boolean quit; private MyIBinder binder=new MyIBinder();//声明一个IBinder对象 //1.定义一个IBinder子类并实现一个获取Service运行状态(count)的方法 public class MyIBinder extends Binder {  public int getCount()  {   return count; //返回Service运行状态:count  } } //2.Service子类必须实现的一个类,用于返回IBinder对象 public IBinder onBind(Intent intent) {  System.out.println("Service is Binded!");  return binder;//返回IBinder对象 } //3.Service被创建时回调该方法 @Override public void onCreate() {  super.onCreate();  System.out.println("Service is Created.");  //创建并启动一个线程,实现动态修改count状态值  new Thread()  {   @Override   public void run()   {    while(!quit)//标识Service关闭启动状态    {     try     {      Thread.sleep(1000);     }catch(InterruptedException e)     {     }     count++;    }   }  }.start(); } //4.Service被断开连接时回调方法 @Override public boolean onUnbind(Intent intent) {  System.out.println("Service is Unbinded");  return true; } //5.Service被关闭之前回调该方法 @Override public void onDestroy() {  super.onDestroy();  this.quit=true; //当调用该方法后(!quit)为假,线程结束  System.out.println("Service is Destroy"); }}</span>
(2)AndroidManifest.xml
实现:为Service子类配置一个Service组件,并为该Service组件的intent-filter配置action
<span style="font-family:Times New Roman;font-size:18px;"><?xml version="1.0" encoding="utf-8"?><manifest xmlns:android="http://schemas.android.com/apk/res/android"    package="com.example.android_service_bind"    android:versionCode="1"    android:versionName="1.0" >    <uses-sdk        android:minSdkVersion="8"        android:targetSdkVersion="19" />    <application        android:allowBackup="true"        android:icon="@drawable/ic_launcher"        android:label="@string/app_name"        android:theme="@style/AppTheme" >        <activity            android:name=".BindServiceTest"            android:label="@string/app_name" >            <intent-filter>                <action android:name="android.intent.action.MAIN" />                <category android:name="android.intent.category.LAUNCHER" />            </intent-filter>        </activity>       <!-- 配置一个Service组件 -->       <service android:name=".BindService">        <intent-filter>             <!-- 为该Service组件的intent-filter配置action -->             <action android:name="com.example.service.BIND_SERVICE"/>        </intent-filter>       </service>      </application></manifest></span>
(3)/com/exanple/android_service_bind/BindServiceTest.java
实现:定义一个ServiceConnection对象,通过该对象的onServiceConnected()方法获取Service返回的IBinder对象,并通过Intent对象启动和绑定指定Service。
<span style="font-family:Times New Roman;font-size:18px;">package com.example.android_service_bind;import android.app.Activity;import android.app.Service;import android.content.ComponentName;import android.content.Intent;import android.content.ServiceConnection;import android.os.Bundle;import android.os.IBinder;import android.view.View;import android.view.View.OnClickListener;import android.widget.Button;import android.widget.Toast;public class BindServiceTest extends Activity { Button bind,unbind,status; //1.保持所启动的Service的IBinder对象 BindService.MyIBinder binder; //2.定义一个ServiceConnection对象 private ServiceConnection conn = new ServiceConnection() {  //a.当该Activity与Service连接成功时回调该方法  @Override  public void onServiceConnected(ComponentName name    , IBinder service)  {   System.out.println("---Service is connected---");   //获取Service的onBind方法所返回的MyBinder对象   binder=(BindService.MyIBinder)service;  }  //b.当该Activity与Service连接不成功时回调该方法  @Override  public void onServiceDisconnected(ComponentName name) {   System.out.println("---Service is Disconnected---");  } }; @Override protected void onCreate(Bundle savedInstanceState) {  super.onCreate(savedInstanceState);  setContentView(R.layout.main);  //a.获取程序界面中的start、stop、getServiceStatus按钮  bind = (Button)findViewById(R.id.bind);  unbind = (Button)findViewById(R.id.unbind);  status = (Button)findViewById(R.id.getServiceStatus);  //b.创建启动Service的Intent  final Intent intent = new Intent();  intent.setAction("com.example.service.BIND_SERVICE");  //c.绑定指定Service  bind.setOnClickListener(new OnClickListener(){   @Override   public void onClick(View v) {    bindService(intent,conn,Service.BIND_AUTO_CREATE);   }  });  //d.解除绑定的Service  unbind.setOnClickListener(new OnClickListener(){   @Override   public void onClick(View v) {    unbindService(conn);   }  });  //e.获取Service的状态,显示Service的count值  status.setOnClickListener(new OnClickListener(){   @Override   public void onClick(View v) {    Toast.makeText(BindServiceTest.this,"Service的count值为:"+binder.getCount()       , Toast.LENGTH_SHORT).show();   }  }); } }</span>
(4)主界面布局/res/layout/main.xml
<span style="font-family:Times New Roman;font-size:18px;"><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:orientation="vertical"    android:layout_width="match_parent"    android:layout_height="match_parent"> <LinearLayout     android:orientation="horizontal"     android:layout_width="match_parent"     android:layout_height="match_parent">     <Button         android:id="@+id/bind"         android:layout_width="wrap_content"         android:layout_height="wrap_content"         android:layout_weight="1"         android:text="绑定service"/>      <Button         android:id="@+id/unbind"         android:layout_width="wrap_content"         android:layout_height="wrap_content"         android:layout_weight="1"         android:text="解除绑定"/>       <Button         android:id="@+id/getServiceStatus"         android:layout_width="wrap_content"         android:layout_height="wrap_content"         android:layout_weight="1"         android:text="获取状态"/>    </LinearLayout></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对象
参考:http://wear.techbrood.com/reference/android/app/Service.html
0 0