Android Service知识
一. 概览
Service 是一种可在后台执行长时间运行操作而不提供界面的应用组件。服务可由其他应用组件启动,而且即使用户切换到其他应用,服务仍将在后台继续运行。此外,组件可通过绑定到服务与之进行交互,甚至是执行进程间通信 (IPC)。例如,服务可在后台处理网络事务、播放音乐,执行文件 I/O 或与内容提供程序进行交互.
本篇文章,我们重点讲一讲绑定服务. 为后面写的理解进程间通信机制文章做个铺垫.
二. 服务类型
2.1 前台服务
前台服务执行一些用户能注意到的操作。例如,音频应用会使用前台服务来播放音频曲目。前台服务必须显示通知。即使用户停止与应用的交互,前台服务仍会继续运行。
2.2 后台服务
后台服务执行用户不会直接注意到的操作。例如,如果应用使用某个服务来进行数据搜集上报,则此服务通常是后台服务。
2.3 绑定服务
当应用组件通过调用 bindService() 绑定到服务时,服务即处于绑定状态。绑定服务会提供客户端-服务器接口,以便组件与服务进行交互、发送请求、接收结果,甚至是利用进程间通信 (IPC) 跨进程执行这些操作。仅当与另一个应用组件绑定时,绑定服务才会运行。多个组件可同时绑定到该服务,但全部取消绑定后,该服务即会被销毁。
三. 基础知识
如要创建服务,您必须创建 Service 的子类(或使用它的一个现有子类)。在实现中,您必须重写一些回调方法,从而处理服务生命周期的某些关键方面,并提供一种机制将组件绑定到服务(如适用)。以下是你应该重写的最重要的回调方法:
onStartCommand()
当另一个组件(如 Activity)请求启动服务时,系统会通过调用 startService() 来调用此方法。执行此方法时,服务即会启动并可在后台无限期运行。
如果您实现此方法,则在服务工作完成后,需负责通过调用 stopSelf() 或 stopService() 来停止服务。
onBind()
当另一个组件想要与服务绑定(例如执行 RPC)时,系统会通过调用 bindService() 来调用此方法。在此方法的实现中,您必须通过返回 IBinder 提供一个接口,以供客户端用来与服务进行通信。请务必实现此方法;但是,如果你并不希望允许绑定,则应返回 null。
如果组件通过调用 startService() 启动服务(这会引起对 onStartCommand() 的调用),则服务会一直运行,直到其使用 stopSelf() 自行停止运行,或由其他组件通过调用 stopService() 将其停止为止。
[注意]: 如果通过startService()已经启动了一个服务,再通过startService()方法启动的时候, 只会走onStartCommand()方法,不会重新走onCreate()方法.
四. 创建绑定服务
绑定服务允许应用组件通过调用 bindService() 与其绑定,从而创建长期连接.
如需与 Activity 和其他应用组件中的Service服务进行交互,或需要通过进程间通信 (IPC) 向其他应用公开某些应用功能,则应创建绑定服务。
[要点]:
如要创建绑定服务,您需通过实现 onBind() 回调方法返回 IBinder,从而定义与服务进行通信的接口;
1. 必须定义指定客户端如何与服务进行通信的接口。
2. 服务与客户端之间的这个接口必须是 IBinder 的实现,并且服务端必须从 onBind() 回调方法返回该接口。
3. 收到 IBinder 后,客户端便可开始通过该接口与服务端进行交互。
多个客户端可以同时绑定到服务。完成与服务的交互后,客户端会通过调用 unbindService() 来取消绑定。如果没有绑定到服务的客户端,则系统会销毁该服务。
等同于下面这句话的理解:
多个客户端可以绑定到相同服务,而且当所有绑定全部取消后,系统即会销毁该服务(服务不必自行停止运行).
五. 服务生命周期

六. 实践出真知
本篇文章重点只讲绑定本地服务, 在同一个进程间通信.
如果您的服务仅供本地应用使用,且无需跨进程工作,您可以实现自有 Binder 类,让客户端通过该类直接访问服务中的公共方法。
注意:只有当客户端和服务处于同一应用和进程内(最常见的情况)时,此方式才有效。例如,对于需要将 Activity 绑定到在后台播放音乐的自有服务的音乐应用,此方式非常有效。
实现步骤:
1. 在你的服务中,创建可执行以下某种操作的 Binder 实例:
包含客户端可调用的公共方法。
返回当前的 Service 实例,该实例中包含客户端可调用的公共方法。
返回由服务承载的其他类的实例,其中包含客户端可调用的公共方法。
2. 从 onBind() 回调方法返回此 Binder 实例。
3. 在客户端中,从 onServiceConnected() 回调方法接收 Binder,并使用提供的方法调用绑定服务。
客户端代码
public class LocalClient extends AppCompatActivity {private Intent intent;//同一进程, 本地服务对象LocalService mService;//是否绑定成功boolean mBound = false;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);intent = new Intent(this, LocalService.class);Button btn = (Button)findViewById(R.id.start_btn);btn.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {if(mBound) {int num = mService.getRandomNumber();Toast.makeText(LocalClient.this, "number: " + num, Toast.LENGTH_SHORT).show();}}});}private ServiceConnection connection = new ServiceConnection() {@Overridepublic void onServiceConnected(ComponentName componentName, IBinder service) {Log.e("test", "===客户端===onServiceConnected======");mBound = true;//已经绑定到LocalService,强制转换IBinder并获取LocalService实例LocalService.LocalBinder binder = (LocalService.LocalBinder) service;mService = binder.getService();}@Overridepublic void onServiceDisconnected(ComponentName componentName) {Log.e("test", "====onServiceDisconnected=====");mBound = false;}};//在onstart方法中 调用 bindservice 绑定服务@Overrideprotected void onStart() {super.onStart();bindService(intent, connection, Context.BIND_AUTO_CREATE);}//在onstop方法中, 调用unbindservice 解绑服务@Overrideprotected void onStop() {super.onStop();unbindService(connection);mBound = false;}@Overrideprotected void onDestroy() {super.onDestroy();}
本地服务端的代码:
public class LocalService extends Service {// Binder given to clientsprivate final IBinder binder = new LocalBinder();// Random number generatorprivate final Random mGenerator = new Random();public LocalService() {}/** method for clients */public int getRandomNumber() {return mGenerator.nextInt(100);}/*** Class used for the client Binder. Because we know this service always* runs in the same process as its clients, we don't need to deal with IPC.* 用于客户端的Binder类。因为我们知道该服务总是在与其客户端相同的进程中运行,所以我们不需要处理IPC。*/class LocalBinder extends Binder {LocalService getService() {// Return this instance of LocalService so clients can call public methodsreturn LocalService.this;}}@Overridepublic IBinder onBind(Intent intent) {Log.e("test", "====LocalService onBind====绑定服务回调===");return binder;}@Overridepublic boolean onUnbind(Intent intent) {Log.e("test", "====LocalService onUnbind===解绑服务回调==");return super.onUnbind(intent);}
打开app界面后,打印log:
03-06 15:16:16.612 19858 19858 E test : ====LocalService onBind====绑定服务回调=
03-06 15:16:16.623 19858 19858 E test : ===客户端===onServiceConnected======
客户端通过bindservice 绑定服务, 打印'===LocalService onBind===='然后服务端通过onBind()回调方法返回此Binder实例
在客户端中从 onServiceConnected() 回调方法接收 Binder对象,打印"客户端===onServiceConnected===="
退出app界面后, 解绑服务,打印log:
03-06 15:22:52.460 19858 19858 E test : ====LocalService onUnbind===解绑服务回调==
相关文章:
Android Service知识
一. 概览 Service 是一种可在后台执行长时间运行操作而不提供界面的应用组件。服务可由其他应用组件启动,而且即使用户切换到其他应用,服务仍将在后台继续运行。此外,组件可通过绑定到服务与之进行交互,甚至是执行进程间通信 (IPC…...
axios的get请求传入数组参数后端无法接收的问题
问题描述 在做项目时,需要把前端的数组通过axios的get请求发送到后端处理,于是像这样直接发送: axios.get(url,{params:{arr: update_arr}})这时在后端接收后报错说:没有 ‘arr’ 这个key: arr request.GET[arr] pr…...
奖金发放-课后程序(Python程序开发案例教程-黑马程序员编著-第3章-课后作业)
实例2:奖金发放 某企业发放的奖金是根据利润和提成计算的,其规则如表1所示。 表1 奖金发放规则 利润(万元) 奖金提成(%) I≤10 10% 10<I≤20 7.5% 20<I≤20 5% 10…...
第十四届蓝桥杯第三期模拟赛 【python】
第十四届蓝桥杯第三期模拟赛 【python】 文章目录第十四届蓝桥杯第三期模拟赛 【python】✨最小的十六进制(python的16进制)❓️问题描述答案提交🧠思路🖥︎参考答案✨Excel的列(进制转化)❓️问题描述答案…...
Python——函数(重点内容)
函数 函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段。 函数能提高应用的模块性,和代码的重复利用率。你已经知道Python提供了许多内建函数,比如print()。但你也可以自己创建函数,这被叫…...
2023年如何在Google做外贸
2023年如何在Google做外贸 答案是:利用谷歌SEO获取自然流量促进成交。 随着全球化和数字化的发展,外贸行业越来越重视互联网的渠道拓展。 在Google搜索引擎上做好SEO优化,是吸引国际客户和提高品牌知名度的关键。 本文将探讨2023年如何在…...
Linux操作系统学习(线程池)
文章目录线程池线程池原理代码示例单例模式饿汉模式懒汉模式饿汉懒汉对比其他的锁线程池 线程池原理 线程池是一种线程使用模式。在多线程应用中,若每有一个任务,线程就去调度相应的函数去创建,当任务过多时,每次都去调度且每…...
JVM运行时数据区—Java虚拟机栈
虚拟机栈的背景 由于跨平台性的设计,java的指令都是根据栈来设计的。不同平台CPU架构不同,所以不能设计为基于寄存器的。 根据栈设计的优点是跨平台,指令集小,编译器容易实现,缺点是性能下降,实现同样的功…...
gitlab中文社区
1、获取gitlab中文社区项目 中文社区版项目:https://gitlab.com/xhang/gitlab 2、克隆中文仓库 git clone https://gitlab.com/xhang/gitlab.git 3、查看gitlab版本 diff 获取对应版本的中文 head -1 /opt/gitlab/version-manifest.txt #安装的是gitlab-ce…...
深度学习-第T2周——彩色图片分类
深度学习-第T2周——彩色图片分类深度学习-第P1周——实现mnist手写数字识别一、前言二、我的环境三、前期工作1、导入依赖项并设置GPU2、导入数据集3、归一化4、可视化图片四、构建简单的CNN网络五、编译并训练模型1、设置超参数2、编写训练函数六、预测七、模型评估深度学习-…...
GNU C编译器扩展关键字:__attribute__
目录 一、section 二、aligned 三、packed 四、format 五、weak 六、alias 七、noinline和always_inline GNU C增加了一个__attribute__关键字用来声明一个函数、变量或类型的特殊属性,可以知道编译器在编译过程中进行特定方面的优化或代码检查。 目前&…...
C++基础 | 从C到C++快速过渡
一、开发环境 c使用的编译器是g。 vim或者vscodeclionVS 二、C版本的Hello World /*** brief c版本helloworld示例* author Mculover666* date 2023/2/26*/#include <iostream> using namespace std;int main() {int a 1;double b 3.14;char c[] "str…...
【C++】仿函数 -- priority_queue
文章目录一、priority_queue 的介绍和使用1、priority_queue 的介绍2、priority_queue 的使用3、priority_queue 相关 OJ 题二、仿函数1、什么是仿函数2、仿函数的作用三、priority_queue 的模拟实现一、priority_queue 的介绍和使用 1、priority_queue 的介绍 priority_queu…...
盘一盘C++的类型描述符(一)
前言 C的类型描述方式是从C语言继承来的,并且进行了扩充(例如引用、非静态成员函数、模板实参等)。但由于C语言中的类型描述方式就略微有点「反人类」,再经C扩展后就有点「反碳基生物」了~ 是的,当我第一次看到这种描…...
Peppol的发展史和基本框架
Peppol(Pan-European Public Procurement Online)是欧洲区域内的一个跨境公共采购电子商务平台试点项目,由欧盟委员会和Peppol联盟成员国共同资助建立,旨在通过制定标准化框架,推动欧盟成员国在公共采购相关的电子目录…...
Linux-GCC介绍+入门级Makefile使用
前言(1)我们都知道,在Linux中编译.c文件需要使用gcc -o .c文件的指令来将C文件变成可执行文件。但是我们有没有发现,如果我们需要编译大一点的工程,后面需要加上的.c文件是不是太多了?感觉非常的麻烦。&…...
iOS(一):Swift纯代码模式iOS开发入门教程
Swift纯代码模式iOS开发入门教程项目初始化(修改为纯代码项目)安装第三方库(以SnapKit库为例)桥接OC库(QMUIKit)封装视图并进行导航跳转示例:使用 TangramKit 第三方UI布局库应用国际化添加 R.s…...
IDEA+Python+Selenium+360浏览器自动化测试
环境配置前提,见文章https://mp.csdn.net/mp_blog/creation/editor/new?spm1001.2101.3001.4503下载360浏览器,并下载对应版本的chromedriver.exe,下载地址http://chromedriver.storage.googleapis.com/index.html下载好360浏览器࿰…...
运输层概述及web请求
运输层 运输层概述 运输层向高层用户屏蔽了下面网络核心的细节(如网络拓扑、所采用的路由选择协议等)它使应用进程看见的就好像是在两个运输层实体之间有一条端到端的逻辑通信信道; 根据需求不同,运输层提供两种运输协议 面向连…...
python与pycharm从零安装
python(解释器)下载地址:Welcome to Python.orgpycharm(编译器)下载地址:PyCharm: the Python IDE for Professional Developers by JetBrains一、python的下载与安装到官网后根据步骤下载安装包后…...
Mybatis逆向工程,动态创建实体类、条件扩展类、Mapper接口、Mapper.xml映射文件
今天呢,博主的学习进度也是步入了Java Mybatis 框架,目前正在逐步杨帆旗航。 那么接下来就给大家出一期有关 Mybatis 逆向工程的教学,希望能对大家有所帮助,也特别欢迎大家指点不足之处,小生很乐意接受正确的建议&…...
2024年赣州旅游投资集团社会招聘笔试真
2024年赣州旅游投资集团社会招聘笔试真 题 ( 满 分 1 0 0 分 时 间 1 2 0 分 钟 ) 一、单选题(每题只有一个正确答案,答错、不答或多答均不得分) 1.纪要的特点不包括()。 A.概括重点 B.指导传达 C. 客观纪实 D.有言必录 【答案】: D 2.1864年,()预言了电磁波的存在,并指出…...
基于Uniapp开发HarmonyOS 5.0旅游应用技术实践
一、技术选型背景 1.跨平台优势 Uniapp采用Vue.js框架,支持"一次开发,多端部署",可同步生成HarmonyOS、iOS、Android等多平台应用。 2.鸿蒙特性融合 HarmonyOS 5.0的分布式能力与原子化服务,为旅游应用带来…...
学习STC51单片机31(芯片为STC89C52RCRC)OLED显示屏1
每日一言 生活的美好,总是藏在那些你咬牙坚持的日子里。 硬件:OLED 以后要用到OLED的时候找到这个文件 OLED的设备地址 SSD1306"SSD" 是品牌缩写,"1306" 是产品编号。 驱动 OLED 屏幕的 IIC 总线数据传输格式 示意图 …...
TRS收益互换:跨境资本流动的金融创新工具与系统化解决方案
一、TRS收益互换的本质与业务逻辑 (一)概念解析 TRS(Total Return Swap)收益互换是一种金融衍生工具,指交易双方约定在未来一定期限内,基于特定资产或指数的表现进行现金流交换的协议。其核心特征包括&am…...
HarmonyOS运动开发:如何用mpchart绘制运动配速图表
##鸿蒙核心技术##运动开发##Sensor Service Kit(传感器服务)# 前言 在运动类应用中,运动数据的可视化是提升用户体验的重要环节。通过直观的图表展示运动过程中的关键数据,如配速、距离、卡路里消耗等,用户可以更清晰…...
【Redis】笔记|第8节|大厂高并发缓存架构实战与优化
缓存架构 代码结构 代码详情 功能点: 多级缓存,先查本地缓存,再查Redis,最后才查数据库热点数据重建逻辑使用分布式锁,二次查询更新缓存采用读写锁提升性能采用Redis的发布订阅机制通知所有实例更新本地缓存适用读多…...
GO协程(Goroutine)问题总结
在使用Go语言来编写代码时,遇到的一些问题总结一下 [参考文档]:https://www.topgoer.com/%E5%B9%B6%E5%8F%91%E7%BC%96%E7%A8%8B/goroutine.html 1. main()函数默认的Goroutine 场景再现: 今天在看到这个教程的时候,在自己的电…...
MinIO Docker 部署:仅开放一个端口
MinIO Docker 部署:仅开放一个端口 在实际的服务器部署中,出于安全和管理的考虑,我们可能只能开放一个端口。MinIO 是一个高性能的对象存储服务,支持 Docker 部署,但默认情况下它需要两个端口:一个是 API 端口(用于存储和访问数据),另一个是控制台端口(用于管理界面…...
【从零开始学习JVM | 第四篇】类加载器和双亲委派机制(高频面试题)
前言: 双亲委派机制对于面试这块来说非常重要,在实际开发中也是经常遇见需要打破双亲委派的需求,今天我们一起来探索一下什么是双亲委派机制,在此之前我们先介绍一下类的加载器。 目录 编辑 前言: 类加载器 1. …...
