9.3.3    活动和服务进行通信

上一小节中我们学习了启动和停止服务的方法,不知道你有没有发现,虽然服务是在活 动里启动的,但在启动了服务之后,活动与服务基本就没有什么关系了。确实如此,我们在 活动里调用了 startService()方法来启动 MyService 这个服务,然后 MyService 的 onCreate()和 onStartCommand()方法就会得到执行。之后服务会一直处于运行状态,但具体运行的是什么 逻辑,活动就控制不了了。这就类似于活动通知了服务一下:“你可以启动了!”然后服务就 去忙自己的事情了,但活动并不知道服务到底去做了什么事情,以及完成的如何。

那么有没有什么办法能让活动和服务的关系更紧密一些呢?例如在活动中指挥服务去 干什么,服务就去干什么。当然可以,这就需要借助我们刚刚忽略的 onBind()方法了。

比如说目前我们希望在 MyService 里提供一个下载功能,然后在活动中可以决定何时开 始下载,以及随时查看下载进度。实现这个功能的思路是创建一个专门的 Binder 对象来对下 载功能进行管理,修改 MyService 中的代码,如下所示:

public class MyService extends Service {

private DownloadBinder mBinder = new DownloadBinder();

class DownloadBinder extends Binder {

public void startDownload() {

Log.d("MyService", "startDownload executed");

}

public int getProgress() {

Log.d("MyService", "getProgress executed");

return 0;

}

}

@Override

public IBinder onBind(Intent intent) {

return mBinder;

}

……

}

可以看到,这里我们新建了一个 DownloadBinder 类,并让它继承自 Binder,然后在它 的内部提供了开始下载以及查看下载进度的方法。当然这只是两个模拟方法,并没有实现真 正的功能,我们在这两个方法中分别打印了一行日志。

接着,在 MyService 中创建了 DownloadBinder 的实例,然后在 onBind()方法里返回了这 个实例,这样 MyService 中的工作就全部完成了。

下面就要看一看,在活动中如何去调用服务里的这些方法了。首先需要在布局文件里新 增两个按钮,修改 activity_main.xml 中的代码,如下所示:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"

android:orientation="vertical" >

……

<Button android:id="@+id/bind_service" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Bind Service" />

<Button android:id="@+id/unbind_service" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Unbind Service" />

</LinearLayout>

这两个按钮分别是用于绑定服务和取消绑定服务的,那到底谁需要去和服务绑定呢?当 然就是活动了。当一个活动和服务绑定了之后,就可以调用该服务里的 Binder 提供的方法了。 修改 MainActivity 中的代码,如下所示:

public class MainActivity extends Activity implements OnClickListener {

private Button startService; private Button stopService; private Button bindService; private Button unbindService;

private MyService.DownloadBinder downloadBinder;

private ServiceConnection connection = new ServiceConnection() {

@Override

public void onServiceDisconnected(ComponentName name) {

}

@Override

public void onServiceConnected(ComponentName name, IBinder service) { downloadBinder = (MyService.DownloadBinder) service; downloadBinder.startDownload();

downloadBinder.getProgress();

}

};

@Override

protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main);

……

bindService = (Button) findViewById(R.id.bind_service); unbindService = (Button) findViewById(R.id.unbind_service); bindService.setOnClickListener(this);

unbindService.setOnClickListener(this);

}

@Override

public void onClick(View v) {

switch (v.getId()) {

……

case R.id.bind_service:

Intent bindIntent = new Intent(this, MyService.class);

bindService(bindIntent, connection, BIND_AUTO_CREATE); // 绑定服务

break;

case R.id.unbind_service:

unbindService(connection); // 解绑服务

break;

default:

break;

}

}

}

可以看到,这里我们首先创建了一个 ServiceConnection 的匿名类,在里面重写了 onServiceConnected()方法和 onServiceDisconnected()方法,这两个方法分别会在活动与服务 成功绑定以及解除绑定的时候调用。在 onServiceConnected()方法中,我们又通过向下转型 得到了 DownloadBinder 的实例,有了这个实例,活动和服务之间的关系就变得非常紧密了。
现在我们可以在活动中根据具体的场景来调用 DownloadBinder 中的任何 public 方法,即实 现了指挥服务干什么,服务就去干什么的功能。这里仍然只是做了个简单的测试,在
onServiceConnected()方法中调用了 DownloadBinder 的 startDownload()和 getProgress()方法。

当然,现在活动和服务其实还没进行绑定呢,这个功能是在 Bind Service 按钮的点击事 件里完成的。可以看到,这里我们仍然是构建出了一个 Intent 对象,然后调用 bindService()
方法将 MainActivity 和 MyService 进行绑定。bindService()方法接收三个参数,第一个参数就
是刚刚构建出的 Intent 对象,第二个参数是前面创建出的 ServiceConnection 的实例,第三个
参数则是一个标志位,这里传入 BIND_AUTO_CREATE 表示在活动和服务进行绑定后自动 创建服务。这会使得 MyService 中的 onCreate()方法得到执行,但 onStartCommand()方法不 会执行。

然后如果我们想解除活动和服务之间的绑定该怎么办呢?调用一下 unbindService()方法 就可以了,这也是 Unbind Service 按钮的点击事件里实现的功能。

现在让我们重新运行一下程序吧,界面如图 9.9 所示。

图   9.9

点击一下 Bind Service 按钮,然后观察 LogCat 中的打印日志如图 9.10 所示:

图   9.10

可以看到,首先是
MyService
的 onCreate() 方法得到了执行,然后 startDownload() 和getProgress()方法都得到了执行,说明我们确实已经在活动里成功调用了服务里提供的方法了。 另外需要注意,任何一个服务在整个应用程序范围内都是通用的,即 MyService 不仅可以和 MainActivity 绑定,还可以和任何一个其他的活动进行绑定,而且在绑定完成后它们都 可以获取到相同的 DownloadBinder 实例。

android: 活动和服务进行通信的更多相关文章

  1. Android学习笔记--服务(Service)

    1.服务概述 1.服务是Android四大组件之一,在使用上可以分为本地服务和远程服务,本地服务是指在不影响用户操作的情况下在后台默默的执行一个耗时操作,例如下载,音频播放等.远程服务是指可以供其他应 ...

  2. 入职小白随笔之Android四大组件——服务(Service)

    Service Android多线程编程 当我们在程序中执行一些耗时操作时,比如发起一条网络请求,考虑到网速等原因,服务器未必会立刻响应我们的请求,此时我们就需要将这些操作放在子线程中去运行,以防止主 ...

  3. Android学习_服务

    一.           服务1.         Android多线程 每一个Android应用程序都会分别运行在一个独立的Dalvik(或ART?)虚拟机中,而每个虚拟机在启动时会运行一个UI主线 ...

  4. Android学习之服务初体验

    •概念 Service(服务)是一个长期运行在后台,没有用户界面的应用组件,即使切换到另一个应用程序或者后台,服务也可以正常运行: 因此,服务适合执行一些不需要显示界面的后台耗时操作,比如下载网络数据 ...

  5. 10月9日Android学习笔记:活动与服务之间的通信

    最近在照着<第一行代码>这本书来学安卓,顺便记下笔记.主要的内容是Android中服务的第二种启动方式,通过活动绑定服务来启动服务,实现活动与服务之间的通信. 一. 首先创建一个服务类 p ...

  6. Android四大组件之Service --- 活动与服务的绑定

    Acticity与Service进行通信如何在活动中指挥service去做事情? 这里就借助onBind()方法了比如说,目前我们希望在MyService里提供一个下载功能,然后在活动中可以决定何时开 ...

  7. Android BLE与终端通信(三)——客户端与服务端通信过程以及实现数据通信

    Android BLE与终端通信(三)--客户端与服务端通信过程以及实现数据通信 前面的终究只是小知识点,上不了台面,也只能算是起到一个科普的作用,而同步到实际的开发上去,今天就来延续前两篇实现蓝牙主 ...

  8. Android BLE与终端通信(三)——client与服务端通信过程以及实现数据通信

    Android BLE与终端通信(三)--client与服务端通信过程以及实现数据通信 前面的终究仅仅是小知识点.上不了台面,也仅仅能算是起到一个科普的作用.而同步到实际的开发上去,今天就来延续前两篇 ...

  9. Android中Service(服务)详解

    http://blog.csdn.net/ryantang03/article/details/7770939 Android中Service(服务)详解 标签: serviceandroidappl ...

随机推荐

  1. Data Base MongoDB 无法创建抽象类的问题,

     无法创建抽象类BsonClassMap.RegisterClassMap 大家都知道抽象类是无法实例化的,即:不能new. 在以下这些情况会遇到这种问题: 1.基类是抽象类: 2.基类是接口: 由于 ...

  2. 2015/9/9 js继续学习

    var book={                 //对象是由花括号括起来的 topic:“JavaScript”://属性“topic”的值是“JavaScript” fat:true:     ...

  3. 面试知识点总结之Java语言

    1.如果某个对象出现在字符串表达式中,如System.out.println(this+".class");,则会自动调用this.toString() 2.所有的类都是在对其第一 ...

  4. iOS模拟各种网络状态

    在iOS开发中我们有在各种不同网络状态下测试app运行状态的需求.苹果给我们提供了在模拟器和真机状态下,模拟各种网络状态的软件. 在模拟器中 苹果提供的模拟网络状态的工具官网地址下载该工具需要登录Ap ...

  5. session的使用方法

    概念:session把客户资料存在服务器中,给浏览器一个加密凭证,每次登录生成的凭证都不相同,浏览器用cookie保存凭证.下次访问时服务器收到凭证后,打开文件读取session信息.session_ ...

  6. SparkContext的初始化(叔篇)——TaskScheduler的启动

    <深入理解Spark:核心思想与源码分析>一书前言的内容请看链接<深入理解SPARK:核心思想与源码分析>一书正式出版上市 <深入理解Spark:核心思想与源码分析> ...

  7. 【Map】MapTest

    package cn.itcast.p1.map.test; import java.util.HashMap; import java.util.Map; public class MapTest2 ...

  8. 使用jquery的trigger方法优化页面代码

    我们做页面级联的时候经常会用到ajax处理数据,会为下拉菜单编写change事件. //城市和区域联动 $("#City").change(function () { var ci ...

  9. 斯坦福第六课:逻辑回归(Logistic Regression)

    6.1  分类问题 6.2  假说表示 6.3  判定边界 6.4  代价函数 6.5  简化的成本函数和梯度下降 6.6  高级优化 6.7  多类分类:一个对所有 6.1  分类问题 在分类问题中 ...

  10. PHP如何连接Access数据库

    PHP代码: <?php $connstr="DRIVER={Microsoft Access Driver (*.mdb)}; DBQ=" .realpath(" ...