分类:C#、Android、VS2015;

创建日期:2016-03-03

一、简介

如果服务是你的应用程序所私有的,即服务(Service)与客户端(Activity)都在同一个项目中(大部分应用程序的情况都是如此),这种服务称为本地服务。

对于本地服务,应该在继承自Binder的类中创建接口,并从重写的OnBind()方法中返回一个Binder的实例。客户端接收这个Binder对象并用它来直接访问Binder甚至Service中可用的公共(public)方法。

二、示例1运行截图

 

三、主要设计步骤

1、添加ch1701_main.xml文件

在layout文件夹下添加该文件,模板选择【XML】,因为布局比较简单,就不让它带设计界面了。当然也可以添加ch1701_main.axml文件让其带设计界面。

<?xml version="1.0" encoding="utf-8" ?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:padding="4dip"
android:gravity="center_horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:id="@+id/ch1701_bind"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="启动服务绑定">
<requestFocus />
</Button>
<Button
android:id="@+id/ch1701_call"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="调用服务提供的方法">
<requestFocus />
</Button>
<Button
android:id="@+id/ch1701_unbind"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="解除服务绑定" />
</LinearLayout>

2、创建服务—ch1701Service

要创建一个可被绑定的服务(bound service),必须在提供的服务中实现OnBind()回调方法,并在该方法中返回一个IBinder类型的对象,此对象定义了与服务进行通信的接口,该接口用于指明客户端如何与服务进行通信。

ch1701Service.cs文件的代码如下:

using Android.App;
using Android.Content;
using Android.OS;
namespace MyDemos.SrcDemos
{
[Service]
public class ch1701LocalService : Service
{
// 用于让客户端绑定的IBinder接口
private readonly IBinder binder;
// 用于获取随机数
private readonly System.Random r = new System.Random(); public ch1701LocalService()
{
binder = new ch1701LocalBinder(this);
} public override IBinder OnBind(Intent intent)
{
return binder;
} // 声明让客户端调用的公共方法
public int GetRandomNumber()
{
return r.Next(100);
}
} // 因为本服务总是运行于与客户端相同的进程中,因此不需要用IPC进行处理。
public class ch1701LocalBinder : Binder
{
// 客户端可通过它调用服务提供的公共方法
public ch1701LocalService localService { get; private set; } public ch1701LocalBinder(ch1701LocalService service)
{
localService = service;
}
}
}

(1)代码解释

(a)在MyService中包含可供客户端调用的公共方法。

既然是服务,就要在Service中包含可供客户端调用的公共方法,该例子仅仅用GetRandomNumber()方法来演示。当然,也可以通过这些公共方法方返回其它类的实例。

(b)从回调方法OnBind()中返回Binder的实例。

在客户端中,通过在回调方法OnServiceConnected()中接收Binder并调用服务提供的方法,即可实现对绑定的服务进行调用。

ch1701LocalBinder为客户端提供了localService属性,通过该属性得到ch1701LocalService的实例后,客户端就可以通过它调用服务中提供的公共方法(比如调用服务示例代码中的GetRandomNumber()方法)。

(c)注意事项。

服务和客户端之所以必须位于同一个应用程序中(同一个项目中),是为了让客户端能够正确转换(cast)返回的对象并调用对象的API。 另外,服务和客户端也必须位于同一个进程中,因为这种方式不能执行任何跨进程的序列化(marshalling)操作。要实现跨进程的序列化操作,可利用消息传递来实现。

(2)创建继承自Binder的类

要实现可被绑定的服务,除了创建服务外,还需要自定义一个继承自Binder的子类,在该子类中提供一个返回服务实例的方法。该子类是IBinder接口的默认实现。

Binder子类通过返回的Service实例响应客户端请求。

例如,在ch1701Service.cs文件中定义了一个名为ch1701ServiceBind的类,当客户端第1次连接服务时,Android会自动调用服务中提供的OnBind方法。这样以来,客户端就可以通过Service调用服务提供的公共方法了。

3、创建客户端—ch1701BindingActivity.cs

ch1701BindingActivity.cs文件的代码如下:

using Android.App;
using Android.Content;
using Android.OS;
using Android.Widget;
namespace MyDemos.SrcDemos
{
[Activity(Label = "【例17-1】绑定到本地服务")]
public class ch1701BindingActivity : Activity
{
ch1701LocalService mService;
ch1701ServiceConnection mConnection;
bool mBound = false;
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
SetContentView(Resource.Layout.ch1701_main);
mConnection = new ch1701ServiceConnection(this); var btnBind = FindViewById<Button>(Resource.Id.ch1701_bind);
btnBind.Click += delegate
{
if (mBound == false)
{
// 绑定到LocalService
Intent intent = new Intent(this, typeof(ch1701LocalService));
BindService(intent, mConnection, Bind.AutoCreate);
}
Toast.MakeText(this, "已绑定", ToastLength.Short).Show();
}; var btnCall = FindViewById<Button>(Resource.Id.ch1701_call);
btnCall.Click += delegate
{
if(mBound==false)
{
Toast.MakeText(this, "请先绑定", ToastLength.Short).Show();
return;
}
// 注意如果该调用会导致某些操作的挂起,应该在单独的线程中调用它,
// 以免降低activity的性能。
int num = mService.GetRandomNumber();
Toast.MakeText(this, "获取的值为: " + num, ToastLength.Short).Show();
}; var btnUnbind = FindViewById<Button>(Resource.Id.ch1701_unbind);
btnUnbind.Click += delegate
{
// 与服务解除绑定
if (mBound == true)
{
UnbindService(mConnection);
Toast.MakeText(this, "绑定已解除", ToastLength.Short).Show();
}
}; } public class ch1701ServiceConnection : Java.Lang.Object, IServiceConnection
{
private ch1701BindingActivity activity;
public ch1701ServiceConnection(ch1701BindingActivity activity)
{
this.activity = activity;
} public void OnServiceConnected(ComponentName name, IBinder service)
{
ch1701LocalBinder binder = (ch1701LocalBinder)service;
activity.mService = binder.localService;
activity.mBound = true;
} public void OnServiceDisconnected(ComponentName name)
{
activity.mBound = false;
}
}
}
}

(1)代码解释

该例子展示了客户端如何利用 ServiceConnection 和 OnServiceConnected() 回调方法绑定到服务。

(2)将客户端绑定到服务

客户端可以通过调用BindService() 方法来绑定服务。当客户端完成交互时,可调用UnbindService()来解除绑定。

调用BindService() 方法来绑定服务时,必须提供一个 ServiceConnection 的实现代码,用于监控与服务的连接。

BindService() 将会立即返回,没有返回值。但是Android系统在创建客户端与服务之间的连接时,会自动调用 ServiceConnection 中的 OnServiceConnected() 方法传递一个 IBinder ,客户端利用它即可与服务进行通信。

ch1701ServiceConnection类负责提供客户端和服务之间的调用接口,注意该类实现了IServiceConnection接口,由于ServiceConnection类是通过Java定义的,所以ch1701ServiceConnection类必须继承自Java.Lang.Object。

BindService方法实现的功能是:如果存在绑定,就使用Bind.AutoCreate值自动创建服务(Android 5.0及更高版本才有此选项)。该方法是一个异步调用,如果没有可绑定的服务该方法将返回false,如果有可绑定的服务,则通过回调将建立的连接发送到ch1701ServiceConnection类中的OnServiceConnected()方法。

MyServiceConnection类继承自ServiceConnection类,在这个类中,重写了OnServiceConnected方法。在这种情况下,IBinder是MyServiceBinder的一个实例。MyServiceBinder用于获取对MyService的引用,以便客户端可以利用它调用服务中定义的方法。

注意在MyServiceConnection的构造函数中,将MainActivity的实例传递到本类中声明的activity(例子中只是以MainActivity为例,但也可以是其他的Activity),这是为了可以在Activity中通过它自身定义的OnServiceConnected回调方法得到对服务的引用,这样以来,Activity就可以调用服务中提供的方法了。

(3)调用服务提供的方法

客户端通过Binder实例获取被绑定的服务的引用后,就可以调用服务中提供的方法了。在这个例子中,ch1701Service服务只定义了一个GetRandomNumber()方法。一旦Activity通过OnServiceConnected方法实现了绑定,这个Activity就可以利用binder来获取对服务的引用,随后就可以调用服务中提供的GetRandomNumber()方法了。

(4)取消服务绑定(Unbinding from the Service)

客户端(Activity)完成对服务的调用后,必须取消对该服务的绑定(即:在不使用服务时要及时关闭服务)。服务断开连接后,会自动调用ServiceConnection类的OnServiceDisconnected方法。

要解除被绑定的服务,客户端调用UnbindService方法即可,通过它可传递在绑定中使用的ServiceConnection实例。

如果没有Activity通过StartService方法调用该服务,也没有其他客户端绑定到该服务,则安卓系统将自动关闭该服务。

【Android】17.2 Activity与Local Service的绑定的更多相关文章

  1. Android中Local Service最本质的作用是什么?

    把Service等同于thread或process是一个非常常见的误解.需要强调又强调的第一点是,Android的Service是一个Context,并不必然等于一个额外的thread.如果你有仔细看 ...

  2. 【转】 Pro Android学习笔记(七七):服务(2):Local Service

    目录(?)[-] Local service代码 调用Local ServiceLocal Service client代码 AndroidManifestxml定义Serviceacitivty的l ...

  3. Android开机启动Activity或者Service方法

    本文出自 “Bill_Hoo专栏” 博客,请务必保留此出处http://billhoo.blog.51cto.com/2337751/761230 这段时间在做Android的基础开发,现在有一需求是 ...

  4. android 中activity调用本地service中的方法。

    1.自定义一个接口,暴露服务中的方法 public interface IService {    /**服务中对外暴露的方法 */    void methodInService();} 2.自定一 ...

  5. Android开机启动Activity或者Service方法(转载)

    这段时间在做Android的基础开发,现在有一需求是开机启动,按照网上某些博文教程做了下,始终不成功,一开机总是提示所启动的应用程序意外终止,于是参考了Android SDK doc,终于解决问题,下 ...

  6. Android Activity与远程Service的通信学习总结

    当一个Service在androidManifest中被声明为 process=":remote", 或者是还有一个应用程序中的Service时,即为远程Service, 远程的意 ...

  7. Android 综合揭秘 —— 全面剖释 Service 服务

    引言 Service 服务是 Android 系统最常用的四大部件之一,Android 支持 Service 服务的原因主要目的有两个,一是简化后台任务的实现,二是实现在同一台设备当中跨进程的远程信息 ...

  8. Android中半透明Activity效果另法

    Android中的Activity有没有类似于像Windows程序样的窗口式显示呢? 答案当然是有. 下图就是一个窗口式Activity的效果图: 下面就说说实现过程: 首先看看AndroidMani ...

  9. Android application 和 activity 标签详解

    extends:http://blog.csdn.net/self_study/article/details/54020909 Application 标签 android:allowTaskRep ...

随机推荐

  1. listView下拉刷新加载数据

    这个下拉效果在网上最早的例子恐怕就是Johan Nilsson的实现,http://johannilsson.com/2011/03/13/android-pull-to-refresh-update ...

  2. awk备忘

    awk是一个强大的文本分析工具,相对于grep的查找,sed的编辑,awk在其对数据分析并生成报告时,显得尤为强大.简单来说awk就是把文件逐行的读入,以空格为默认分隔符将每行切片,切开的部分再进行各 ...

  3. eclipse javaWeb项目如何引入jar包

      eclipse javaWeb项目如何引入jar包 CreateTime--2018年4月19日08:54:24 Author:Marydon 1.判断当前jar包是否已经引入到项目当中的3种方式 ...

  4. sqlplus命令手冊

    show和set命令是两条用于维护SQLPlus系统变量的命令 : SQL> show all --查看全部系统变量值 SQL>show user --显示当前连接用户 SQL>sh ...

  5. 微信小程序的零食商城

    概述 这是一个微信小程序的商城应用,功能包括了首页.分类.购物车.个人中心.商品列表.商品详情.订单.地址管理等 详细 代码下载:http://www.demodashi.com/demo/10353 ...

  6. IP数据包格式详解(转)

    摘自:http://blog.163.com/hlz_2599/blog/static/1423784742011112195857956/</> TCP/IP协议定义了一个在因特网上传输 ...

  7. 使用SafeIP隐藏自己的IP

    资料:http://www.cnblogs.com/KeenLeung/p/3482241.html 1.到网上下载SafeIP这个工具,安装,打开 2.选择自己熟悉的语言: 3.到www.ip138 ...

  8. MSSQL-SQL SERVER 分页原理

    项目中用到的, 用心琢磨一下此SQL语句即可: SELECT TOP $row * FROM (        SELECT ROW_NUMBER() OVER (ORDER BY [ID] desc ...

  9. skimage exposure模块解读

    exposure模块包括: 直方图均衡化 gamma调整.sigmoid调整.log调整 判断图像是否对比度太低 exposure模块包括以下函数: histogram 统计颜色的直方图,基于nump ...

  10. JavaScript 中定义变量时有无var声明的区别

    关于JavaScript中定义变量时有无var声明的区别 var a=5; //正确 a=5; //正确 在javascript中,以上两种方法都是定义变量的正确方法.微软的Script56.CHM中 ...