在上一篇中介绍了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. 【MemSQL Start[c]UP 3.0 - Round 1 A】 Declined Finalists

    [链接]h在这里写链接 [题意] 在这里写题意 [题解] max(最大值-25,0) [错的次数] 0 [反思] 在这了写反思 [代码] #include <bits/stdc++.h> ...

  2. x264代码剖析(十五):核心算法之宏块编码中的变换编码

    x264代码剖析(十五):核心算法之宏块编码中的变换编码 为了进一步节省图像的传输码率.须要对图像进行压缩,通常採用变换编码及量化来消除图像中的相关性以降低图像编码的动态范围.本文主要介绍变换编码的相 ...

  3. swift 利用 Reflect(字典转模型)

    1.  导入Reflect(字典转模型)框架 2. 让它继承Reflect这个类,如下代码所示: class IWUser: Reflect { /** *  用户的ID */ var idstr:N ...

  4. HDU 1251统计难题 字典树

    字典树的应用. 数据结构第一次课的作业竟然就需要用到树了!!!这不科学啊.赶紧来熟悉一下字典树. 空间开销太大T T #include<cstdio> #include<cstrin ...

  5. shrio 权限管理filterChainDefinitions过滤器配置(转)

    shrio 权限管理filterChainDefinitions过滤器配置 /** * Shiro-1.2.2内置的FilterChain * @see ======================= ...

  6. Declarative Widgets is a QML plugin that adds Qt Widgets support to QML

     05.04.2018  Nathan Collins  8 comments FacebookTwitterGoogle+LinkedInEmail Declarative Widgets is a ...

  7. 29、从零写USB摄像头驱动之通过urb接受数据后上报数据是函数中fid的作用

    原因分析如下: 视频数据是由一帧一帧数据组成,为了防止数据错乱,会给每一帧数据分配一个frameid,从第0帧开始,接着是第1帧,接着又是第0帧这样交错进行的,对usb摄像头来说每一帧数据来源于多个包 ...

  8. Unity(IOC)学习笔记

    原文:Unity(IOC)学习笔记 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/m0_37591671/article/details/79432 ...

  9. [TypeStyle] Use fallback values in TypeStyle for better browser support

    You can increase the browser support of your CSS using fallback values and vendor prefixes. This les ...

  10. android获取一个用于打开Word文件的intent

    近期在做项目使用webview显示后,有写文档须要打开,找了一些资料,研究了一下,弄出来了! 以下贴一下主要代码: param为文档的主要路径 public static Intent getWord ...