当前位置: 首页 > news >正文

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 启动式服务对于后台操作很合适&#xff0c;不过需要一个更有交互性的服务。 接下来构建这样一个应用&#xff1a; 1、创建一个绑定式服务的基本版本&#xff0c;名为OdometerService 我们要为它增加一个方法getDistance()&#x…...

系统韧性研究(1)| 何谓「系统韧性」?

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

使用Perl脚本编写爬虫程序的一些技术问题解答

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

SAP内部转移价格(利润中心转移价格)的条件

SAP内部转移价格&#xff08;利润中心转移价格&#xff09; SAP内部转移价格&#xff08;利润中心转移价格&#xff09; SAP内部转移价格&#xff08;利润中心转移价格&#xff09;这个听了很多人说过&#xff0c;但是利润中心转移定价需要具备什么条件。没有找到具体的文档。…...

WRF如何批量输出文件添加或删除文件名后缀

1. 批量添加文件名后缀 #1----批量添加文件名后缀&#xff08;.nc&#xff09;。#指定wrfout文件所在的文件夹 path "/mnt/wtest1/"#列出路径path下所有的文件 file_names os.listdir(path) #遍历在path路径下所有以wrfout_d01开头的文件&#xff0c;在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极限&#x1f47a;极限的主要问题 数列极限数列极限的定义 ( ϵ − N ) (\epsilon-N) (ϵ−N)语言描述极限表达式成立的证明极限发散证明常用数列极限数列极限的几何意义例 函数的极限 abstract 数列极限 极限&#x1f47a; 极限分为数列的极限和函数的极限…...

Vue-2.3v-model原理

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

​左手 Serverless,右手 AI,7 年躬身的古籍修复之路

作者&#xff1a;宋杰 “AI 可以把我们思维体系当中&#xff0c;过度专业化、过度细分的这些所谓的知识都替代掉&#xff0c;让我们集中精力去体验自己的生命。我挺幸运的&#xff0c;代码能够有 AI 辅助&#xff0c;也能够有 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() # 计算非零像素的数量&#xff0c;即白质骨架的体素总数 voxel_count np.count_no…...

VR全景营销颠覆传统营销,让消费者身临其境

随着VR的普及&#xff0c;各种VR产品、功能开始层出不穷&#xff0c;并且在多个领域都有落地应用&#xff0c;例如文旅、景区、酒店、餐饮、工厂、地产、汽车等&#xff0c;在这个“内容为王”的时代&#xff0c;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

文章目录 一、闭包是什么&#xff1f; &#x1f926;‍♂️二、闭包 &#x1f60e;三、使用场景 &#x1f601;四、使用场景&#xff08;2&#xff09; &#x1f601;五、闭包的原理六、思考总结一、 更深层次了解闭包&#xff0c;分析以下代码执行过程二、闭包三、闭包定义四、…...

10月10日上课内容 Docker--harbor私有仓库部署与管理

Docker--harbor私有仓库部署与管理 ------------------ 1、搭建本地私有仓库 ------------------------------ #首先下载 registry 镜像 docker pull registry #在 daemon.json 文件中添加私有镜像仓库地址 vim /etc/docker/daemon.json { "insecure-registries"…...

Java 序列化和反序列化为什么要实现 Serializable 接口

第一、序列化和反序列化 序列化&#xff1a;把对象转换为字节序列的过程称为对象的序列化. 反序列化&#xff1a;把字节序列恢复为对象的过程称为对象的反序列化. 第二、什么时候需要用序列化和反序列化呢? 当我们只在本地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、窗体类&#xff08;主代码文件窗体设计器后台代码文件&#xff09; 主窗体对象的创建&#xff1a;在Program类里面&#xff1a; Application.Run(new FrmMain());这句代码就决定了&#xff0c;当前窗体是项目的主窗体。…...

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”&#xff0c;即美国国家雪和冰数据中心。NSIDC 是一个位于美国科罗拉多大学波尔得分校的研究中心&#xff0c;致力于收集、管理和分发全球雪和冰的科学数据。 Matlab绘图 cl…...

【码银送书第八期】《Python数据挖掘:入门进阶与实用案例分析》

摘要&#xff1a;本案例将主要结合自动售货机的实际情况&#xff0c;对销售的历史数据进行处理&#xff0c;利用pyecharts库、Matplotlib库进行可视化分析&#xff0c;并对未来4周商品的销售额进行预测&#xff0c;从而为企业制定相应的自动售货机市场需求分析及销售建议提供参…...

【Oracle APEX开发小技巧12】

有如下需求&#xff1a; 有一个问题反馈页面&#xff0c;要实现在apex页面展示能直观看到反馈时间超过7天未处理的数据&#xff0c;方便管理员及时处理反馈。 我的方法&#xff1a;直接将逻辑写在SQL中&#xff0c;这样可以直接在页面展示 完整代码&#xff1a; SELECTSF.FE…...

python/java环境配置

环境变量放一起 python&#xff1a; 1.首先下载Python Python下载地址&#xff1a;Download Python | Python.org downloads ---windows -- 64 2.安装Python 下面两个&#xff0c;然后自定义&#xff0c;全选 可以把前4个选上 3.环境配置 1&#xff09;搜高级系统设置 2…...

如何在看板中体现优先级变化

在看板中有效体现优先级变化的关键措施包括&#xff1a;采用颜色或标签标识优先级、设置任务排序规则、使用独立的优先级列或泳道、结合自动化规则同步优先级变化、建立定期的优先级审查流程。其中&#xff0c;设置任务排序规则尤其重要&#xff0c;因为它让看板视觉上直观地体…...

深入解析C++中的extern关键字:跨文件共享变量与函数的终极指南

&#x1f680; C extern 关键字深度解析&#xff1a;跨文件编程的终极指南 &#x1f4c5; 更新时间&#xff1a;2025年6月5日 &#x1f3f7;️ 标签&#xff1a;C | extern关键字 | 多文件编程 | 链接与声明 | 现代C 文章目录 前言&#x1f525;一、extern 是什么&#xff1f;&…...

mysql已经安装,但是通过rpm -q 没有找mysql相关的已安装包

文章目录 现象&#xff1a;mysql已经安装&#xff0c;但是通过rpm -q 没有找mysql相关的已安装包遇到 rpm 命令找不到已经安装的 MySQL 包时&#xff0c;可能是因为以下几个原因&#xff1a;1.MySQL 不是通过 RPM 包安装的2.RPM 数据库损坏3.使用了不同的包名或路径4.使用其他包…...

ip子接口配置及删除

配置永久生效的子接口&#xff0c;2个IP 都可以登录你这一台服务器。重启不失效。 永久的 [应用] vi /etc/sysconfig/network-scripts/ifcfg-eth0修改文件内内容 TYPE"Ethernet" BOOTPROTO"none" NAME"eth0" DEVICE"eth0" ONBOOT&q…...

Spring是如何解决Bean的循环依赖:三级缓存机制

1、什么是 Bean 的循环依赖 在 Spring框架中,Bean 的循环依赖是指多个 Bean 之间‌互相持有对方引用‌,形成闭环依赖关系的现象。 多个 Bean 的依赖关系构成环形链路,例如: 双向依赖:Bean A 依赖 Bean B,同时 Bean B 也依赖 Bean A(A↔B)。链条循环: Bean A → Bean…...

解析奥地利 XARION激光超声检测系统:无膜光学麦克风 + 无耦合剂的技术协同优势及多元应用

在工业制造领域&#xff0c;无损检测&#xff08;NDT)的精度与效率直接影响产品质量与生产安全。奥地利 XARION开发的激光超声精密检测系统&#xff0c;以非接触式光学麦克风技术为核心&#xff0c;打破传统检测瓶颈&#xff0c;为半导体、航空航天、汽车制造等行业提供了高灵敏…...

适应性Java用于现代 API:REST、GraphQL 和事件驱动

在快速发展的软件开发领域&#xff0c;REST、GraphQL 和事件驱动架构等新的 API 标准对于构建可扩展、高效的系统至关重要。Java 在现代 API 方面以其在企业应用中的稳定性而闻名&#xff0c;不断适应这些现代范式的需求。随着不断发展的生态系统&#xff0c;Java 在现代 API 方…...

云原生周刊:k0s 成为 CNCF 沙箱项目

开源项目推荐 HAMi HAMi&#xff08;原名 k8s‑vGPU‑scheduler&#xff09;是一款 CNCF Sandbox 级别的开源 K8s 中间件&#xff0c;通过虚拟化 GPU/NPU 等异构设备并支持内存、计算核心时间片隔离及共享调度&#xff0c;为容器提供统一接口&#xff0c;实现细粒度资源配额…...