Android绑定式服务
Github:https://github.com/MADMAX110/Odometer
启动式服务对于后台操作很合适,不过需要一个更有交互性的服务。
接下来构建这样一个应用:
1、创建一个绑定式服务的基本版本,名为OdometerService
我们要为它增加一个方法getDistance(),这个方法会返回一个随机数
2、让活动MainActivity绑定到OdometerService,并调用它的getDistance方法。
将每秒调用一次这个方法,在MainActivity中用得到的结果更新一个文本视图。
3、更新OdometerService,改为使用Android的位置服务。
这个服务将得到用户当前位置的更新,并使用这些更新计算所走过的距离。
创建一个名为Odometer的Android新工程
创建一个新服务
要创建一个绑定式服务,需要扩展Service类。
如图所示,在com.hfad.odometer中创建一个服务。
不要选中Exported,因为只有当希望这个应用之外的服务能够访问这个服务时才需要将它设置为true。
确保选中Enabled,不选中的话活动将无法运行应用。
package com.hafd.odometer;import android.app.Service;
import android.content.Intent;
import android.os.IBinder;public class OdometerService extends Service {@Overridepublic IBinder onBind(Intent intent) {}
}
上面的代码实现了一个方法onBind,当一个组件希望绑定到这个服务时,会调用这个方法。这个方法有一个参数Intent,并返回一个IBinder对象。
IBinder是一个接口,用来将你的服务绑定到活动,需要在服务代码中提供它的一个实现。
实现一个绑定器
定义绑定器:
public class OdometerBinder extends Binder {OdometerService getOdometer() {return OdometerService.this;}}
更新OdometerService.java代码并增加一个getDistance方法
package com.hafd.odometer;import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import java.util.Random;public class OdometerService extends Service {private final IBinder binder = new OdometerBinder();private final Random random = new Random();//创建一个绑定式服务时,需要提供一个Binder实现public class OdometerBinder extends Binder {//活动将使用这个方法得到OdometerService的一个引用OdometerService getOdometer() {return OdometerService.this;}}@Overridepublic IBinder onBind(Intent intent) {return binder;}public double getDistance() {return random.nextDouble();}
}
更新MainActivity的布局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"tools:context=".MainActivity"android:orientation="vertical"android:padding="16dp"><TextViewandroid:id="@+id/distance"android:layout_width="wrap_content"android:layout_height="wrap_content"android:textSize="48sp"android:layout_gravity="center_horizontal"android:textAppearance="?android:attr/textAppearanceLarge" /></LinearLayout>
MainActivity需要做什么
1、创建一个ServiceConnection
ServiceConnection是一个接口,允许将活动绑定到一个服务。
它有两个方法需要你定义:
onServiceConnected():建立与服务的连接时会调用
onServiceDisconnected():断开服务连接时会调用
更新MainActivity.java
package com.hafd.odometer;import androidx.appcompat.app.AppCompatActivity;import android.content.ComponentName;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;public class MainActivity extends AppCompatActivity {private ServiceConnection connection = new ServiceConnection() {@Overridepublic void onServiceConnected(ComponentName componentName, IBinder iBinder) {}@Overridepublic void onServiceDisconnected(ComponentName componentName) {}}@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);}
}
onServiceConnected方法
在活动和服务之间建立连接时会调用这个方法。
有两个参数:一个ComponentName对象和一个IBinder对象,ComponentName对象描述所要连接的服务,IBinder对象由服务定义。
我们使用onServiceConnected方法做两件事:
1、使用它的IBinder参数得到所连接服务的一个引用,在这里就是OdometerService的引用。为此可以将IBinder强制转换为一个OdometerService.OdometerBinder,并调用它的getOdometer方法。
2、记录活动绑定到这个服务。
private OdometerService odometer;private boolean bound = false;private ServiceConnection connection = new ServiceConnection() {@Overridepublic void onServiceConnected(ComponentName componentName, IBinder iBinder) {OdometerService.OdometerBinder odometerBinder = (OdometerService.OdometerBinder) iBinder;odometer = odometerBinder.getOdometer(); //使用IBinder得到服务的一个引用bound = true;}@Overridepublic void onServiceDisconnected(ComponentName componentName) {bound = false;}};
onServiceDisconnected方法
记录活动不再绑定到服务。
public void onServiceDisconnected(ComponentName componentName) {bound = false;}
2、将活动绑定到服务
使用bindService绑定服务
通常会在两个地方将活动绑定到服务:
活动变得可见时,在活动的onStart方法中,如果只需要在活动可见时与活动交互,在这个方法中绑定服务就很合适。
活动创建时,在活动的onCreate方法中,如果需要从服务接受更新,即使活动已经停止也要继续接受更新,就要在这个方法中绑定服务。
在这里我们只需要在MainActivity可见时显示从OdometerService得到的更新,所以要在活动的onStart方法中绑定服务。
要绑定这个服务首先要创建一个显式意图,指定想要绑定的服务。然后使用活动的bindService方法绑定服务,传入这个意图,服务定义的ServiceConnection对象以及描述希望如何绑定的一个标志。
@Overrideprotected void onStart() {super.onStart();Intent intent = new Intent(this, OdometerService.class);bindService(intent, connection, Context.BIND_AUTO_CREATE);}
3、与服务交互
调用OdometerService的getDistance方法
一旦活动绑定到服务,我们要每秒调用一次OdometerService的getDistance方法,并将其值更新MainActivity的文本视图。
为MainActivity增加一个displayDistance方法:
@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);displayDistance();}private void displayDistance() {final TextView distanceView = (TextView) findViewById(R.id.distance);final Handler handler = new Handler();handler.post(new Runnable() {@Overridepublic void run() {double distance = 0.0;//如果得到OdometerService的一个引用,而且绑定到这个服务,则调用getDistance。if (bound && odometer != null)distance = odometer.getDistance();String distanceStr = String.format(Locale.getDefault(), "%1$,.2f miles", distance);distanceView.setText(distanceStr);//每秒运行一次handler.postDelayed(this, 1000);}});}
4、完成时与服务接触绑定
使用unbindService与服务解除绑定
将活动与服务解除绑定时,通常会把相应的代码增加到活动的onStop或onDestroy方法中。使用哪一个方法取决于你的bindService代码放在哪里:
如果在活动的onStart方法中绑定服务,则在onStop方法中解除绑定。
如果在onCreate方法中绑定服务,则在onDestroy方法中解除绑定。
所以这里在onStop方法与服务解除绑定。这个方法有一个参数,即ServiceConnection对象。需要向MainActivity增加以下代码:
protected void onStop() {super.onStop();if (bound) {unbindService(connection);bound = false;}}
试一试应用
运行这个应用时会在MainActivity显示一个随机数,这个数每秒改变一次。
安卓绑定式服务的生命周期
1、服务创建。
2、onCreate(): 当服务第一次被创建时执行。这个方法可以在服务创建时进行一些初始化操作。
3、onBind(): 当其他组件通过调用bindService()方法与服务绑定时执行。在这个方法中,服务会返回一个IBinder接口实例,客户端可以通过这个接口与服务进行通信。
4、服务绑定。
5、onUnbind(): 当其他组件通过调用unbindService()方法与服务解绑时执行。在这个方法中,服务可以执行一些清理操作,例如停止在后台运行的任务等。
6、onDestroy(): 当服务不再被使用或被销毁时执行。注意,如果服务同时被启动和绑定,那么即使所有的客户端都解绑了服务,服务也不会被销毁,除非服务用stopSelf()方法或其他组件调用stopService()方法来终止自己。
7、服务撤销。
总的来说,绑定式服务的生命周期与启动式服务的生命周期略有不同,主要区别在于绑定式服务需要与其他组件进行绑定和解绑操作,并且服务的生命周期会受到这些操作的影响。
相关文章:

Android绑定式服务
Github:https://github.com/MADMAX110/Odometer 启动式服务对于后台操作很合适,不过需要一个更有交互性的服务。 接下来构建这样一个应用: 1、创建一个绑定式服务的基本版本,名为OdometerService 我们要为它增加一个方法getDistance()&#x…...

系统韧性研究(1)| 何谓「系统韧性」?
过去十年,系统韧性作为一个关键问题被广泛讨论,在数据中心和云计算方面尤甚,同时它对赛博物理系统也至关重要,尽管该术语在该领域不太常用。大伙都希望自己的系统具有韧性,但这到底意味着什么?韧性与其他质…...

使用Perl脚本编写爬虫程序的一些技术问题解答
网络爬虫是一种强大的工具,用于从互联网上收集和提取数据。Perl 作为一种功能强大的脚本语言,提供了丰富的工具和库,使得编写的爬虫程序变得简单而灵活。在使用的过程中大家会遇到一些问题,本文将通过问答方式,解答一些…...

SAP内部转移价格(利润中心转移价格)的条件
SAP内部转移价格(利润中心转移价格) SAP内部转移价格(利润中心转移价格) SAP内部转移价格(利润中心转移价格)这个听了很多人说过,但是利润中心转移定价需要具备什么条件。没有找到具体的文档。…...
WRF如何批量输出文件添加或删除文件名后缀
1. 批量添加文件名后缀 #1----批量添加文件名后缀(.nc)。#指定wrfout文件所在的文件夹 path "/mnt/wtest1/"#列出路径path下所有的文件 file_names os.listdir(path) #遍历在path路径下所有以wrfout_d01开头的文件,在os.path…...

Ubuntu右上角不显示网络的图标解决办法
一.line5改为true sudo vim /etc/NetworkManager/NetworkManager.conf 二.重启网卡 sudo service network-manager stop sudo mv /var/lib/NetworkManager/NetworkManager.state /tmp sudo service network-manager start...
AM@数列极限
文章目录 abstract极限👺极限的主要问题 数列极限数列极限的定义 ( ϵ − N ) (\epsilon-N) (ϵ−N)语言描述极限表达式成立的证明极限发散证明常用数列极限数列极限的几何意义例 函数的极限 abstract 数列极限 极限👺 极限分为数列的极限和函数的极限…...

Vue-2.3v-model原理
原理:v-model本质上是一个语法糖,例如应用在输入框上,就是value属性和input事件的合写。 作用:提供数据的双向绑定 1)数据变,视图跟着变:value 2)视图变,数据跟着变input 注意&a…...

左手 Serverless,右手 AI,7 年躬身的古籍修复之路
作者:宋杰 “AI 可以把我们思维体系当中,过度专业化、过度细分的这些所谓的知识都替代掉,让我们集中精力去体验自己的生命。我挺幸运的,代码能够有 AI 辅助,也能够有 Serverless 解决我的运营成本问题。Serverless 它…...
计算mask的体素数量
import numpy as np import nibabel as nib # 用于处理神经影像数据的库 # 从文件中加载mask图像 mask_image nib.load(rE:\mask.nii.gz) # 获取图像数据 mask_data mask_image.get_fdata() # 计算非零像素的数量,即白质骨架的体素总数 voxel_count np.count_no…...

VR全景营销颠覆传统营销,让消费者身临其境
随着VR的普及,各种VR产品、功能开始层出不穷,并且在多个领域都有落地应用,例如文旅、景区、酒店、餐饮、工厂、地产、汽车等,在这个“内容为王”的时代,VR全景展示也是一种新的内容表达方式。 VR全景营销让消费者沉浸式…...

FreeRTOS学习笔记——四、任务的定义与任务切换的实现
FreeRTOS学习笔记——四、任务的定义与任务切换的实现 0 前言1 什么是任务2 创建任务2.1 定义任务栈2.2 定义任务函数2.3 定义任务控制块2.4 实现任务创建函数2.4.1 任务创建函数 —— xTaskCreateStatic()函数2.4.2 创建新任务——prvInitialiseNewTask()函数2.4.3 初始化任务…...

js 之让人迷惑的闭包 03
文章目录 一、闭包是什么? 🤦♂️二、闭包 😎三、使用场景 😁四、使用场景(2) 😁五、闭包的原理六、思考总结一、 更深层次了解闭包,分析以下代码执行过程二、闭包三、闭包定义四、…...
10月10日上课内容 Docker--harbor私有仓库部署与管理
Docker--harbor私有仓库部署与管理 ------------------ 1、搭建本地私有仓库 ------------------------------ #首先下载 registry 镜像 docker pull registry #在 daemon.json 文件中添加私有镜像仓库地址 vim /etc/docker/daemon.json { "insecure-registries"…...
Java 序列化和反序列化为什么要实现 Serializable 接口
第一、序列化和反序列化 序列化:把对象转换为字节序列的过程称为对象的序列化. 反序列化:把字节序列恢复为对象的过程称为对象的反序列化. 第二、什么时候需要用序列化和反序列化呢? 当我们只在本地JVM里运行下Java实例, 这个时候是不需要什么序列化和…...

vite+vue3+ts中使用require.context | 报错require is not defined | 获取文件夹中的文件名
vitevue3ts中使用require.context|报错require is not defined|获取文件夹中的文件名 目录 vitevue3ts中使用require.context|报错require is not defined|获取文件夹中的文件名一、问题背景二、报错原因三、解决方法 一、问题背景 如题在vitevue3ts中使用required.context时报…...

C#(Csharp)我的基础教程(四)(我的菜鸟教程笔记)-Windows项目结构分析、UI设计和综合事件应用的探究与学习
目录 windows项目是我们.NET学习一开始必备的内容。 1、窗体类(主代码文件窗体设计器后台代码文件) 主窗体对象的创建:在Program类里面: Application.Run(new FrmMain());这句代码就决定了,当前窗体是项目的主窗体。…...
Flink: Only supported for operators
Exception in thread "main" java.lang.UnsupportedOperationException: Only supported for operators.at org.apache.flink.streaming.api.scala.DataStream.name(...

NSIDC定义的海冰相关概念
文章目录 相关概念Matlab绘图结果展示 相关概念 NSIDC 表示 “National Snow and Ice Data Center”,即美国国家雪和冰数据中心。NSIDC 是一个位于美国科罗拉多大学波尔得分校的研究中心,致力于收集、管理和分发全球雪和冰的科学数据。 Matlab绘图 cl…...

【码银送书第八期】《Python数据挖掘:入门进阶与实用案例分析》
摘要:本案例将主要结合自动售货机的实际情况,对销售的历史数据进行处理,利用pyecharts库、Matplotlib库进行可视化分析,并对未来4周商品的销售额进行预测,从而为企业制定相应的自动售货机市场需求分析及销售建议提供参…...

基于uniapp+WebSocket实现聊天对话、消息监听、消息推送、聊天室等功能,多端兼容
基于 UniApp + WebSocket实现多端兼容的实时通讯系统,涵盖WebSocket连接建立、消息收发机制、多端兼容性配置、消息实时监听等功能,适配微信小程序、H5、Android、iOS等终端 目录 技术选型分析WebSocket协议优势UniApp跨平台特性WebSocket 基础实现连接管理消息收发连接…...

visual studio 2022更改主题为深色
visual studio 2022更改主题为深色 点击visual studio 上方的 工具-> 选项 在选项窗口中,选择 环境 -> 常规 ,将其中的颜色主题改成深色 点击确定,更改完成...
JVM垃圾回收机制全解析
Java虚拟机(JVM)中的垃圾收集器(Garbage Collector,简称GC)是用于自动管理内存的机制。它负责识别和清除不再被程序使用的对象,从而释放内存空间,避免内存泄漏和内存溢出等问题。垃圾收集器在Ja…...

P3 QT项目----记事本(3.8)
3.8 记事本项目总结 项目源码 1.main.cpp #include "widget.h" #include <QApplication> int main(int argc, char *argv[]) {QApplication a(argc, argv);Widget w;w.show();return a.exec(); } 2.widget.cpp #include "widget.h" #include &q…...

从零开始打造 OpenSTLinux 6.6 Yocto 系统(基于STM32CubeMX)(九)
设备树移植 和uboot设备树修改的内容同步到kernel将设备树stm32mp157d-stm32mp157daa1-mx.dts复制到内核源码目录下 源码修改及编译 修改arch/arm/boot/dts/st/Makefile,新增设备树编译 stm32mp157f-ev1-m4-examples.dtb \stm32mp157d-stm32mp157daa1-mx.dtb修改…...

ServerTrust 并非唯一
NSURLAuthenticationMethodServerTrust 只是 authenticationMethod 的冰山一角 要理解 NSURLAuthenticationMethodServerTrust, 首先要明白它只是 authenticationMethod 的选项之一, 并非唯一 1 先厘清概念 点说明authenticationMethodURLAuthenticationChallenge.protectionS…...
sqlserver 根据指定字符 解析拼接字符串
DECLARE LotNo NVARCHAR(50)A,B,C DECLARE xml XML ( SELECT <x> REPLACE(LotNo, ,, </x><x>) </x> ) DECLARE ErrorCode NVARCHAR(50) -- 提取 XML 中的值 SELECT value x.value(., VARCHAR(MAX))…...

新能源汽车智慧充电桩管理方案:新能源充电桩散热问题及消防安全监管方案
随着新能源汽车的快速普及,充电桩作为核心配套设施,其安全性与可靠性备受关注。然而,在高温、高负荷运行环境下,充电桩的散热问题与消防安全隐患日益凸显,成为制约行业发展的关键瓶颈。 如何通过智慧化管理手段优化散…...

让AI看见世界:MCP协议与服务器的工作原理
让AI看见世界:MCP协议与服务器的工作原理 MCP(Model Context Protocol)是一种创新的通信协议,旨在让大型语言模型能够安全、高效地与外部资源进行交互。在AI技术快速发展的今天,MCP正成为连接AI与现实世界的重要桥梁。…...
聊一聊接口测试的意义有哪些?
目录 一、隔离性 & 早期测试 二、保障系统集成质量 三、验证业务逻辑的核心层 四、提升测试效率与覆盖度 五、系统稳定性的守护者 六、驱动团队协作与契约管理 七、性能与扩展性的前置评估 八、持续交付的核心支撑 接口测试的意义可以从四个维度展开,首…...