在上一篇中介绍了Service与Activity的区别及Service两种启动方式中的第一种启动方式startService().

我们会发现用startService()、stopService()方法启动和关闭一个Service时,Service与访问者之间基本上不存在太多的关联,因此Service和访问者之间也无法进行通信和数据交换。如果要实现Service与Activity之间的通信就要使用第二种启动方式(绑定启动)bindService()启动、unbindService()关闭。

下面我们来看一下bindService方法的各个参数的含义:(下图是API中关于该方法的说明)

官方说明地址:http://developer.android.com/reference/android/content/Context.html#bindService(android.content.Intent, android.content.ServiceConnection, int)

各个参数的大致含义如下:

service:通过Intent指定要启动的Service.

conn:该参数是一个ServiceConnection对象,该对象用于监听访问者与Service对象的onServiceConnected(ComponentName name, IBinder service)方法:当Service所在的宿主进程由于异常终止或者由其他原因终止,导致该Service与访问者之间断开连接时回调该ServiceConnection对象的onServiceDisconnected(ComponentName name)方法。

	private ServiceConnection conn = new ServiceConnection() {

		@Override
public void onServiceDisconnected(ComponentName name) {
System.out.println("--Service Disconnected--");
} @Override
public void onServiceConnected(ComponentName name, IBinder service) {
System.out.println("--Service Connected--");
binder = (MyBinder) service;
}
};

flags:指定绑定时是否自动创建Service.该参数为0则不自动创建,为BIND_AUTO_CREATE(自动创建)

注意:当调用者主动通过nubindService()方法断开与Service的连接时,ServiceConnection对象的onServiceDisconnected(ComponentName name)方法不会被调用。

可以看到上面onServiceConnected方法中有一个IBinder的参数对象,实际上Activity与Service之间的绑定是通过该参数进行绑定和通信的。这时候可能有的朋友就有点迷糊了,这到底是怎样实现通信的呢?

其实,当你在开发一个Service的时候Service类会强制你实现一个方法onBind(Intent intent).在绑定本地(没有跨越进程)Service的情况下,onBind(Intent intent)方法返回的IBinder对象将会传给上面介绍的bindService()方法参数ServiceConnection对象的o中的IBinder.这样访问者就可以通过操作该参数中IBinder对象来实现对Service中数据的读取。

在实际开发中通常会采用继承Binder(IBinder的实现类)的方式实现自己的IBinder对象。

下面我们来实现一个绑定的Service与Activity之间的通信:

(1)建立一个service返回Binder对象

package com.example.testservice;

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;
//定义onBinder方法所返回的对象
private MyBinder binder = new MyBinder();
//通过继承Binder来实现IBinder类
public class MyBinder extends Binder{
public int getCount(){
return count;
}
} @Override
public IBinder onBind(Intent intent) {
System.out.println("Service is Binded");
return binder;
} @Override
public void onCreate() { super.onCreate();
System.out.println("Service is Created");
new Thread(){
public void run() {
while(!quit){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
count++;
}
};
}.start();
} @Override
public boolean onUnbind(Intent intent) {
System.out.println("Service is UnBinded");
return super.onUnbind(intent);
} @Override
public void onDestroy() {
super.onDestroy();
this.quit = true;
System.out.println("Service is Destroyed");
} }

(2)创建ServiceConnection接口实例对象,并将该对象的实例作为参数传给bindService()方法,通过调用ServiceConnection接口实例中的nServiceConnected方法的参数获得IBinder对象。

package com.example.testservice;

import android.app.Activity;
import android.app.Service;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.IBinder;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.Toast; import com.example.testservice.BindService.MyBinder; public class BindServiceTest extends Activity{
Button bind, unbind, getServiceStatus; BindService.MyBinder binder; private ServiceConnection conn = new ServiceConnection() { @Override
public void onServiceDisconnected(ComponentName name) {
System.out.println("--Service Disconnected--");
} @Override
public void onServiceConnected(ComponentName name, IBinder service) {
System.out.println("--Service Connected--");
binder = (MyBinder) service;
}
}; protected void onCreate(android.os.Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main); bind = (Button)findViewById(R.id.button1);
unbind = (Button) findViewById(R.id.button2);
getServiceStatus = (Button) findViewById(R.id.button3); final Intent intent = new Intent(); intent.setAction("com.meritit.service.BIND_SERVICE"); bind.setOnClickListener(new OnClickListener() { @Override
public void onClick(View arg0) {
bindService(intent, conn, Service.BIND_AUTO_CREATE);
}
}); unbind.setOnClickListener(new OnClickListener() { @Override
public void onClick(View v) {
unbindService(conn);
}
}); getServiceStatus.setOnClickListener(new OnClickListener() { @Override
public void onClick(View v) {
Toast.makeText(BindServiceTest.this, "Service的count值是:" + binder.getCount(),
Toast.LENGTH_SHORT).show();
}
});
};
}

通过该方法Activity可以非常方便的访问到Service的运行状态,这里的IBinder可以看成Service组件所返回的代理对象。

下一篇将介绍:Service的生命周期

Android菜鸟的成长笔记(18)——绑定本地Service并与之通信的更多相关文章

  1. Android菜鸟的成长笔记(16)——Service简介

    Service是Android四大组件之一 1.Service与Activity的区别在:Service一直在后台运行,没有用户界面. 2.选择Activity与Service的标准:如果某个程序组件 ...

  2. Android菜鸟的成长笔记(19)——Service的生命周期

    前面两篇文章介绍了关于Service的两种启动方式,简要总结如下: Context.startService() Context.bindService() 1. startService()的目的是 ...

  3. Android菜鸟的成长笔记(17)—— 再看Android中的Unbounded Service

    原文:Android菜鸟的成长笔记(17)-- 再看Android中的Unbounded Service 前面已经写过关于startService(Unbounded Service)的一篇文章:&l ...

  4. Android菜鸟的成长笔记(1)——Android开发环境搭建从入门到精通

    原文:Android菜鸟的成长笔记(1)--Android开发环境搭建从入门到精通 今天在博客中看到好多Android的初学者对Android的开发环境的搭建不熟悉而导致不能进行学习,所以我决定自己写 ...

  5. Android菜鸟的成长笔记(7)——什么是Activity

    原文:[置顶] Android菜鸟的成长笔记(7)——什么是Activity 前面我们做了一个小例子,在分析代码的时候我们提到了Activity,那么什么是Activity呢? Activity是An ...

  6. Android菜鸟的成长笔记(3)——给QQ登录界面说So Easy

    原文:Android菜鸟的成长笔记(3)--给QQ登录界面说So Easy 上一篇:Android菜鸟的成长笔记(2)--第一个Android应用 我们前面已经做了第一个Android应用程序,虽然有 ...

  7. Android菜鸟的成长笔记(2)——第一个Android应用

    原文:Android菜鸟的成长笔记(2)--第一个Android应用 上一篇:Android菜鸟的成长笔记(1)--Anddroid环境搭建从入门到精通 在上一篇Android菜鸟的成长笔记(1)中我 ...

  8. Android菜鸟的成长笔记(14)—— Android中的状态保存探究(上)

    原文:[置顶] Android菜鸟的成长笔记(14)—— Android中的状态保存探究(上) 我们在用手机的时候可能会发现,即使应用被放到后台再返回到前台数据依然保留(比如说我们正在玩游戏,突然电话 ...

  9. Android菜鸟的成长笔记(13)——异步任务(Async Task)

    原文:[置顶] Android菜鸟的成长笔记(13)——异步任务(Async Task) Android的UI线程主要负责处理用户的事件及图形显示,因此主线程UI不能阻塞,否则会弹出一个ANR(App ...

  10. Android菜鸟的成长笔记(12)——Handler、Loop、MessageQueue

    原文:[置顶] Android菜鸟的成长笔记(12)——Handler.Loop.MessageQueue 当一个程序第一次启动时,Android会启动一条主线程(Main Thread),主线程主要 ...

随机推荐

  1. 如何把传统写法改成框架形式 es6

    每天思考的问题: 1.什么是组件 2.什么是插件 3.如何把传统写法改成框架形式 4.前端为什么要使用框架,使用框架的好处是什么? Image.png http://www.zhihu.com/que ...

  2. Oracle游标进行循环效率比较

    对300万一张表数据,用游标进行循环,不同写法的效率比较 对300万一张表数据,用游标进行循环,不同写法的效率比较   1.显示游标   declare     cursor cur_2 is sel ...

  3. C语言结构体的字节对齐原则

    为什么要对齐? 现代计算机中内存空间都是按照byte划分的,从理论上讲似乎对任何类型的变量的访问可以从任何地址开始,但实际情况是在访问特定类型变量的时候经常在特 定的内存地址访问,这就需要各种类型数据 ...

  4. 《机器学习实战》---NumPy

    NumPy库函数基础: 机器学习算法涉及很多线性代数知识. NumPy库中有很多线性代数计算. 之所以用到线性代数只是为了简化不同的数据点上执行的相同数学运算.将数据表示为矩阵形式, 只需要执行简单的 ...

  5. linux安装anaconda

    打开网址:https://repo.continuum.io/archive/ 下载对应版本: 然后把下载的文件放到linux系统上 在终端执行: bash Anaconda3-5.1.0-Linux ...

  6. 【AtCoder ABC 075 C】Bridge

    [链接] 我是链接,点我呀:) [题意] 让你求出桥的个数 [题解] 删掉这条边,然后看看1能不能到达其他所有的点就可以了 [代码] #include <bits/stdc++.h> us ...

  7. The behavior of App killed or restored by Android System or by users

    What's the behavior of App killed or restored by Android System or by users? First, user kills the a ...

  8. 12.2 linux USB框架分析(详细注册match匹配过程)

     首先我们先来简单说一说USB的框架,之后在来具体分析源码,以便加深理解!其实USB的框架比较像“平台总线.设备.驱动”的框架,也分为总线.设备.驱动三大块.其中总线驱动是已经由内核完成的,一旦接入u ...

  9. MySql Order By 多个字段 排序规则

    版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/xlxxcc/article/details/52250963 说在前面 突发奇想,想了解一下mysq ...

  10. jquery-12 jquery的ajax如何使用

    jquery-12 jquery的ajax如何使用 一.总结 一句话总结:就是$.get()和$.post()方法的使用,看参考手册就好,与php的交互. 1.删除元素的时候如何设置删除特效? ani ...