分类:C#、Android、VS2015;

创建日期:2016-03-03

一、简介

除了上一节介绍的基本绑定以外,你还可以创建一个同时支持started和bound的服务。也就是说,服务可以通过调用 StartService() 来启动,这会使它一直保持运行,同时它也允许客户端通过调用BindService() 来与之绑定。

虽然你通常应该要实现 OnBind() 或 OnStartCommand() 中的一个,但有时需要同时实现两者。比如,音乐播放器的服务也许就需要同时实现后台运行和支持绑定。这样,activity就可以启动服务来播放音乐,并且音乐会一直播放下去,即使用户离开该应用程序也没关系,这个activity可以绑定播放服务来重新获得播放控制权。

另外,如果你的服务是started和bound的,那么服务启动后,系统将不会在所有客户端解除绑定时销毁它。取而代之的是,你必须通过调用StopSelf() 或 StopService() 显式终止此服务。

服务只在为绑定的应用程序组件工作时才会存活,因此,只要没有组件绑定到服务,系统就会自动销毁服务(你不需要像started服务中那样通过OnStartCommand()来终止一个bound服务)。

一旦OnBind方法返回绑定的实例,Android就会引发实现IServiceConnection接口的对象的ServiceConnected事件,然后,客户端就可以通过Binder引用它。

多个客户端可以同时连接到同一个服务上。不过,只有在第一个客户端绑定时,系统才会调用服务的 OnBind() 方法来获取 IBinder 。然后,系统会向后续请求绑定的客户端传送这同一个 IBinder ,而不再调用 OnBind() 。当最后一个客户端解除绑定后,系统会自动销毁服务(除非服务是同时通过 StartService() 启动的)。

二、示例2运行截图

该例子演示如何绑定到一个started服务。

单击【启动服务】按钮后,就会在左上角出现一个通知图标,下拉展开该图标,就可以看到来自服务的通知信息。

 

单击【调用服务中提供的方法】按钮,会显示调用服务中对应方法返回的结果,单击【停止服务】按钮,左上角的通知图标也会同时消失。

三、主要设计步骤

1、添加ch1702_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<Button
android:id="@+id/ch1702_startService"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="启动服务" />
<Button
android:id="@+id/ch1702_callService"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="调用服务中提供的方法" />
<Button
android:id="@+id/ch1702_stopService"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="停止服务" />
</LinearLayout>

2、添加ch1702Service.cs

using Android.App;
using Android.Content;
using Android.OS;
using Android.Widget;
using System.Threading; namespace MyDemos.SrcDemos
{
[Service]
[IntentFilter(new string[] { action })]
public class ch1702Service : Service
{
public const string action = "ServiceDemo.ch1702Service";
ch1702ServiceBinder binder; public override StartCommandResult OnStartCommand(Intent intent, StartCommandFlags flags, int startId)
{
Notification notification = GetNotification();
//启动前台任务
StartForeground((int)NotificationFlags.ForegroundService, notification); var t = new Thread(() =>
{
//发送通知
var m = (NotificationManager)GetSystemService(NotificationService);
m.Notify((int)NotificationFlags.ForegroundService, notification); Thread.Sleep(); //延时50秒模拟长时间运行的服务 //停止前台任务
StopForeground(true);
//停止后台服务
StopSelf();
});
t.Start();
return StartCommandResult.NotSticky;
} private Notification GetNotification()
{
var pendingIntent = PendingIntent.GetActivity(this,
(int)NotificationFlags.ForegroundService,
new Intent(this, typeof(MainActivity)),
PendingIntentFlags.UpdateCurrent);
Notification.Builder builder = new Notification.Builder(this)
.SetContentTitle("来自ch1702Service的通知")
.SetContentText("正在前台运行ch1702Service")
.SetContentIntent(pendingIntent)
.SetSmallIcon(Resource.Drawable.Icon);
Notification notification = builder.Build();
return notification;
} public override IBinder OnBind(Android.Content.Intent intent)
{
binder = new ch1702ServiceBinder(this);
return binder;
} public string GetText()
{
return "这是来自ch1702Service的信息";
} public override void OnDestroy()
{
var myHandler = new Handler();
myHandler.Post(() =>
{
Toast.MakeText(this, "正在停止ch1702Service", ToastLength.Long).Show();
});
base.OnDestroy();
}
} public class ch1702ServiceBinder : Binder
{
ch1702Service service; public ch1702ServiceBinder(ch1702Service service)
{
this.service = service;
} public ch1702Service GetMyService()
{
return service;
}
}
}

3、添加ch1702MainActivity.cs

using Android.App;
using Android.Content;
using Android.OS;
using Android.Widget;
using Android.Content.Res; namespace MyDemos.SrcDemos
{
[Activity(Label = "ch1702MainActivity")]
public class ch1702MainActivity : Activity
{
bool isBound = false;
bool isConfigurationChange = false;
ch1702ServiceBinder binder;
ch1702ServiceConnection myServiceConnection;
Intent serviceIntent; protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
SetContentView(Resource.Layout.ch1702_main); var start = FindViewById<Button>(Resource.Id.ch1702_startService);
start.Click += delegate
{
serviceIntent = new Intent(ch1702Service.action);
StartService(serviceIntent);
}; var callService = FindViewById<Button>(Resource.Id.ch1702_callService);
callService.Click += delegate
{
if (isBound)
{
RunOnUiThread(() =>
{
string text = binder.GetMyService().GetText();
Toast.MakeText(this, text, ToastLength.Short).Show();
});
}
}; var stop = FindViewById<Button>(Resource.Id.ch1702_stopService);
stop.Click += delegate
{
StopService(serviceIntent);
if (isBound)
{
UnbindService(myServiceConnection);
isBound = false;
}
}; // 如果配置改变了(比如旋转了屏幕),则恢复连接
if (myServiceConnection != null)
{
binder = myServiceConnection.Binder;
}
} protected override void OnStart()
{
base.OnStart();
var myServiceIntent = new Intent(ch1702Service.action);
myServiceConnection = new ch1702ServiceConnection(this);
BindService(myServiceIntent, myServiceConnection, Bind.AutoCreate);
} public override void OnConfigurationChanged(Configuration newConfig)
{
isConfigurationChange = true;
base.OnConfigurationChanged(newConfig);
} protected override void OnDestroy()
{
base.OnDestroy(); if (!isConfigurationChange)
{
if (isBound)
{
UnbindService(myServiceConnection);
isBound = false;
}
}
} private class ch1702ServiceConnection : Java.Lang.Object, IServiceConnection
{
private ch1702MainActivity activity;
public ch1702ServiceBinder Binder { get; private set; } public ch1702ServiceConnection(ch1702MainActivity activity)
{
this.activity = activity;
} public void OnServiceConnected(ComponentName name, IBinder service)
{
var myServiceBinder = service as ch1702ServiceBinder;
if (myServiceBinder != null)
{
activity.binder = myServiceBinder;
activity.isBound = true; // 即使配置发生了改变,仍保持绑定到该实例
Binder = myServiceBinder;
}
} public void OnServiceDisconnected(ComponentName name)
{
activity.isBound = false;
}
}
}
}

【Android】17.3 Activity与StartedService的绑定的更多相关文章

  1. 【Android】17.4 Activity与IntentService的绑定

    分类:C#.Android.VS2015: 创建日期:2016-03-03 一.简介 本示例通过AlarmManager类以固定的时间间隔调用服务(每隔2秒更新一次随机生成的股票数据).如果将此示例的 ...

  2. Android 组件系列-----Activity的传值和回传值

    在这篇随笔里将讲解Activity的传值和回传值. 一.通过startActivity来进行Activity的传值 在Android中,如果我们要通过一个Activity来启动另一个Activity, ...

  3. Android Service与Activity之间通信的几种方式

    在Android中,Activity主要负责前台页面的展示,Service主要负责需要长期运行的任务,所以在我们实际开发中,就会常常遇到Activity与Service之间的通信,我们一般在Activ ...

  4. 【原创】Android 从一个Activity跳转到另外一个Activity

    Android四大组件activity使用,实现两个activity之间的跳转 基本流程:创建两个activity-将其中一个activity中组件作为事件源-通过组件事件的处理借助intent对象实 ...

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

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

  6. [Android笔记1]Activity+Layout+Button

    线性布局(LinearLayout)是指view对象在父view中可按水平或垂直方向线性排列. 相对布局(RelativeLayout)是指view对象的排列依赖于各对象之间的相对位置. 下面是展示两 ...

  7. android 基础02 - Activity 的生命周期及状态

    返回栈 Android 中的 Activity 是可以层叠的,当我们启动一个新的 Activity 时,就会覆盖在原有的 Activity 之上, 点击 Back 会销毁当前 Activity,下面的 ...

  8. Android application 和 activity 标签详解

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

  9. 【Android实验】第一个Android程序与Activity生命周期

    目录 第一个Android程序和Activity生命周期 实验目的 实验要求 实验过程 1. 程序正常启动与关闭 2. 外来电话接入的情况 3. 外来短信接入的情况 4. 程序运行中切换到其他程序(比 ...

随机推荐

  1. WebService SOAP、Restful和HTTP(post/get)请求区别

    web service(SOAP) Webservice的一个最基本的目的就是提供在各个不同平台的不同应用系统的协同工作能力. Web service 就是一个应用程序,它向外界暴露出一个能够通过We ...

  2. spring mvc返回jsonp内容

    代码如下: import com.alibaba.fastjson.JSONPObject; @RequestMapping(value = "/method1") @Respon ...

  3. eclipse导入web项目各种错误

    1.JavaWeb:报错信息The superclass "javax.servlet.http.HttpServlet" was not found on the Java Bu ...

  4. POJ 1436 Horizontally Visible Segments (线段树&#183;区间染色)

    题意   在坐标系中有n条平行于y轴的线段  当一条线段与还有一条线段之间能够连一条平行与x轴的线不与其他线段相交  就视为它们是可见的  问有多少组三条线段两两相互可见 先把全部线段存下来  并按x ...

  5. JAR,WAR,EAR区别

    JAR WAR EAR 英文 Java Archive file Web Archive file Enterprise Archive file 包含内容 class.properties文件,是文 ...

  6. iOS-APP启动页加载广告

    概述 加载广告页, 展现跳过按钮实现倒计时功能, 并判断广告页面是否更新. 详细 代码下载:http://www.demodashi.com/demo/10698.html 目前市场上很多APP(如淘 ...

  7. SDUT 2608 Alice and Bob (巧妙的二进制)

    Alice and Bob Time Limit: 1000ms   Memory limit: 65536K  有疑问?点这里^_^ 题目描述 Alice and Bob like playing ...

  8. 修改apache配置文件去除thinkphp url中的index.php(转)

    例如你的原路径是 http://localhost/test/index.php/index/add那么现在的地址是 http://localhost/test/index/add如何去掉index. ...

  9. Linux命令-下载文件的工具:wget

    Linux系统中的wget是一个下载文件的工具,它用在命令行下.对于Linux用户是必不可少的工具,我们经常要下载一些软件或从远程服务器恢复备份到本地服务器.wget支持HTTP,HTTPS和FTP协 ...

  10. Hadoop On Demand

    原文地址:http://hadoop.apache.org/docs/r1.0.4/cn/hod.html 简介 文档 简介 Hadoop On Demand(HOD)是一个能在大型物理集群上供应虚拟 ...