Android Service知识

news2024/9/20 16:38:02

一. 概览

        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;

    @Override
    protected 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() {
            @Override
            public 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() {
        @Override
        public void onServiceConnected(ComponentName componentName, IBinder service) {
            Log.e("test", "===客户端===onServiceConnected======");
            mBound = true;
            //已经绑定到LocalService,强制转换IBinder并获取LocalService实例
            LocalService.LocalBinder binder = (LocalService.LocalBinder) service;
            mService = binder.getService();
        }

        @Override
        public void onServiceDisconnected(ComponentName componentName) {
            Log.e("test", "====onServiceDisconnected=====");
            mBound = false;
        }
    };

    //在onstart方法中 调用 bindservice 绑定服务
    @Override
    protected void onStart() {
        super.onStart();
        bindService(intent, connection, Context.BIND_AUTO_CREATE);
    }

    //在onstop方法中, 调用unbindservice 解绑服务
    @Override
    protected void onStop() {
        super.onStop();
        unbindService(connection);
        mBound = false;
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
    }

本地服务端的代码:

public class LocalService extends Service {

    // Binder given to clients
    private final IBinder binder = new LocalBinder();
    // Random number generator
    private 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 methods
            return LocalService.this;
        }
    }


    @Override
    public IBinder onBind(Intent intent) {
        Log.e("test", "====LocalService  onBind====绑定服务回调===");
        return binder;
    }

    @Override
    public 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===解绑服务回调==


 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/391781.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

你是真的“C”——为冒泡排序升级赋能!

你是真的“C”——为冒泡排序升级赋能!😎前言🙌冒泡排序升级赋能之境界一!冒泡排序升级赋能之境界二!qsort库函数的运用和认识总结撒花💞😎博客昵称:博客小梦 😊最喜欢的…

【CDP】更改solr 存储路径导致ranger-audit 大量报错问题解决

前言 我们生产上公司是使用的CDP集群,一次管理员通知,Solr 组件的数据存放路径磁盘空间不够。 我们的solr 组件时为 Ranger 服务提供日志审计功能, 在我们更改了磁盘路径,并重启了Solr 组件,然后发现相关组件&#…

基于Python的selenium

一、安装 1.1安装Python,安装Python时需要勾选增加环境变量 如果之前已经安装过Python,需要将Python相关文件以及环境变量删除 1.2安装成功:在命令行界面下输入Python,最终展示>>>即可成功 2.1安装pycharm,直接自定义安装…

论文阅读-(GLIP)Grounded Language-Image Pre-training (目标检测+定位)

Paper:Grounded Language-Image Pre-training Code:https://github.com/microsoft/GLIP 简介: 定位任务与图像检测任务非常类似,都是去图中找目标物体的位置,目标检测为给出一张图片找出bounding box,定位…

07react+echart,大屏代码开发

react框架引入第三方插件原链接gitHub:GitHub - hustcc/echarts-for-react: ⛳ Apache ECharts components for React wrapper. 一个简单的 Apache echarts 的 React 封装。import ReactECharts from echarts-for-react;import * as echarts from echarts;一、软件简介echarts-…

微机原理和计算机组成原理复习

1:冯诺依曼机器的主要特点? 1)计算机由运算器、存储器、控制器、输入设备和输出设备五大部分组成; 2)指令和数据存储在存储器中,并可以按地址访问; 3)指令和数据均以二进制表示&…

2023年软考中级信息安全工程师考什么?

信息安全工程师是属于软考中级科目,含金量很高的,信息安全工程师在社会上的需求是蛮大的。 信息安全工程师主要涉及计算机信息安全方面,在计算机软硬件、网络、应用相关领域从事安全系统设计、安全产品开发、产品集成、信息系统安全检测与审计…

小程序容器作为软件中间件技术不可忽视的价值

随着移动互联网的不断发展,越来越多的应用程序被广泛应用于各种行业和领域中。然而,不同的平台和设备之间的差异性和复杂性,给应用程序的开发和部署带来了很大的挑战。这时,小程序容器作为软件中间件技术的其中一环,成…

格密码学习笔记(三):闵可夫斯基第一定理

文章目录NNN维超球体体积结论闵可夫斯基凸体定理闵可夫斯基第一定理闵可夫斯基第二定理致谢NNN维超球体体积结论 在nnn维空间中,对半径为rrr的超球体(Ball),有vol(B(0,r))≥(2rn)n\mathrm{vol}(\mathcal{B}(0, r)) \geq \left( \…

java基础:浅聊实例化和初始化

其实如果了解python的化,其在生成一个实例对象的时候会调用两个系统方法__new__ 和__init__。 这个可以通过看生成的class文件看到,比如创建一个test.java,然后通过jclasslib这个软件查看class文件,当然ide也可以安装这个软件的插…

ggplot2的组图拓展包(1):patchwork(上篇)

专注系列化、高质量的R语言教程推文索引 | 联系小编 | 付费合集patchwork是ggplot绘图系统的拓展包,主要功能是将多个ggplot格式的图形组合成一幅大图,即组图。patchwork工具包十分好用,它主要利用几个类似四则运算符号的操作符进行组图&…

Python——函数(重点内容)

函数 函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段。 函数能提高应用的模块性,和代码的重复利用率。你已经知道Python提供了许多内建函数,比如print()。但你也可以自己创建函数,这被叫…

Linux 常用软件安装(jdk,redis,mysql,minio,kkFileView)

1.jdk安装 查询所有跟Java相关的安装的rpm包 rpm -qa | grep java卸载所有跟openjdk相关的包: 执行命令。删除以上除了noarch 结尾的所有文件 rpm -e --nodeps java-1.8.0-openjdk-1.8.0.252.b09-2.el8_1.x86_64 rpm -e --nodeps java-1.8.0-openjdk-headless-1.8.0…

钉钉端H5开发调试怎么搞

H5开发本地调试教程 作为一名前端开发,大家平时工作中或多或少都有接触或需要开发H5页面的场景,在开发过程中,如何像PC端页面一样有有丝滑的体验呢? 不同的情况需要在不同的端调试更方便有效: 1. 在画UI的时候,更适合在PC端调试,更改代码或者直接在浏览器调试,都是实…

LeetCode链表(单链表,双链表,反转链表)

文章目录前言1.链表定义2.链表操作3.技巧链表常见操作1.lc203 移除链表元素2.lc2 两数相加3.lc328 奇偶链表反转链表1.lc206 反转链表2.lc92 反转链表II链表双指针1.lc19 删除链表的倒数第 N 个结点2.lc21 合并两个有序链表3.lc24 两两交换链表中的节点4.lc234 回文链表前言 本…

Vue3倒计时组件(Countdown)

可自定义设置以下属性: 倒计时数值(countdown),单位s,必传倒计时标题(title),默认Countdown,string | v-slot格式化倒计时展示(format)&#xff…

“操作无法完成,因为其中的文件或文件夹一再另一程序打开”解决方法

windows系统中,有时时候我们想要修改某个文件,就出现出现如下提示:操作无法完成,因为其中的文件或文件夹已在另一程序打开请关闭该文件或文件夹,然后重试出现这个上面提示的原因是,我们要修改的文件或文件夹…

网络基础(1)

目录1. 网络1.1 网络是什么1.2 网络在哪里2. 协议3. TCP/IP五层(或四层)模型3.1 分层细节3.2 报头3.2.1 封装与解包4. 数据传输4.1 局域网4.2 IP地址与Mac地址1. 网络 1.1 网络是什么 网络本质是一个软件,软件是可以进行分层的。例如STL库,实际上分为了…

文件包含漏洞1 | iwebsec

文章目录00-文件包含漏洞原理环境01-本地文件包含读取敏感文件信息配合文件上传getshell配合日志文件getshell配合SSH日志配合运行环境00-文件包含漏洞原理 为什么要文件包含? 为什么会有文件包含漏洞? 因为将被包含的文件设置为变量,用来进行动态调用…

169_技巧_Power BI 依据促销日历计算销售金额

169_技巧_Power BI 依据促销日历计算销售金额 一、背景 在各位表格表姐们计算销售金额的时候,有一个绕不开的问题:商品有促销的问题,需要使用对应的促销价来计算销售额。 按照惯例还是先来看看结果 Power BI 公共 web 效果:htt…