Android - Service

2023-05-16

前台20s后台200s不执行玩就报ANR异常。

一、概念

没有界面在后台长期运行在主线程中的一个组件。

ServiceThread
可以配置执行在不同的进程中。CPU调度的最小单位。
任何有Context的地方都可以控制Service当Activity销毁后不再持有该Thread的引用,不管该子线程是一次任务还是循环任务都无法再控制。

二、生命周期

 所有和界面相关生命周期都没有。

2.1  onStartCommand()中的返回值

系统会因为内存不足而销毁Service,是可以等到内存充足后再重建Service,并执行onStartCommand()。

返回值类型说明

return super.onStartCommand(intent, flags, startId)

return Service.START_NOT_STICKY

默认情况,被销毁后不会重建。
return Service.START_STICKY被销毁后会重建。但是不再保存onStartCommand()中的形参intent。
return Service.START_REDELIVER_INTENT被销毁后会重建。会将销毁钱最后一次传入onStartCommand()中的Intent保留。

三、常见属性

<service
    android:name=".MyService"    //Service的类名	
    android:label    //Service的名字,若不设置,默认为Service类名
    android:icon    //Service的图标	
    android:permission    //申明此Service的权限,有提供了该权限的应用才能控制或连接此服务
    android:process    //表示该服务是否在另一个进程中运行(远程服务),不设置默认为本地服务;remote则设置成远程服务
    android:foregroundServiceType="location|camera|microphone"    //在前台Service中获取定位/摄像头/麦克风权限需要配置(Android10引入定位,11引入摄像头麦克风)
    android:enabled="true"    //是否默认启动,默认为 true
    android:exported="true"    //该服务是否能够被其他应用程序所控制或连接	不设置默认此项为 true
    >
    <intent-filter android:priority="1000" />    //配置优先级,最大1000
</service>

四、开启关闭

4.1 start 方式

  • 长期后台运行(不会因为APP或者Activity销毁而停止,但服务进程在内存不足时会被回收),外部不能调用Service里的方法。
  • 每调用一次startService(),onStartCommand()就会执行一次,但实际上每个 Service 只会存在一个实例。所以不管调用了多少次 startService(),只需调用一次 stopService() 或 stopSelf() ,Service就会停止。stopSelf() 是 Service 内部自己调用的。
class MyService : Service() {
    //第一次创建的时候才调用
    override fun onCreate() { super.onCreate() }
    //每次启动的时候都会调用
    override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int {
        return super.onStartCommand(intent, flags, startId)
    }
    //销毁的时候调用
    override fun onDestroy() { super.onDestroy() }
}

Activity {
    //开启和关闭不要用同一个intent,当退出Activity后开启的intent就是null,关闭调用报错。
    //实际开发开启和注销服务都写在Activity的onStart()、onDestroy()里面就没有这个问题
    btn1.setOnClickListener {
        val intent = Intent(this, MyService::class.java)
        startService(intent)    //启动服务
    }
    btn2.setOnClickListener {
        val intent = Intent(this, MyService::class.java)
        stopService(intent)    停止服务
    }
}

4.2 bind 方式

  • 生命周期和Activity同生共死,外部可以调用Service中的方法,可以和多个Activity绑定共享。
  • 如果Service或者Activity是new出来的就是普通类不是组件了,这样调用里面的方法没意义。隐形的服务系统设置里面查不到,Activity死的时候Service也死了,不能长期在后台运行。bindService()绑定服务会调用onCreate() => onBind(),unbundService()解绑服务会调用onUnbind() => onDestroy()。绑定和解绑只能调用一次,因此写到Activity的onCreate()和onDestroy()中。
//抽取用于暴露Service中供外部调用的功能
interface IFunction {
    fun callEat()
    fun callJump()
}

class MyService : Service() {
    //绑定时调用
    override fun onBind(intent: Intent): IBinder {
        return MyBinder()   //返回代理人实例
    }
    //解绑时调用
    override fun onUnbind(intent: Intent?): Boolean {
        return super.onUnbind(intent)
    }
    //Service中自定义的函数
    fun eat() {}
    fun jump() {}
    //定义代理人,//在代理人中调用Service的对应方法
    inner class MyBinder : Binder(), IFunction {
        override fun callEat() { eat() }
        override fun callJump() { jump() }
    }
}

Activity {
    private lateinit var function: IFunction
    private val connection = object : ServiceConnection {
        //绑定时调用
        override fun onServiceConnected(name: ComponentName, binder: IBinder) {
            //抽取成属性供别处调用
            function = binder as IFunction    //转为抽取的接口对象来调用Service暴露的功能
        }
        //解绑时调用
        override fun onServiceDisconnected(name: ComponentName) {...}
    }
    btn1.setOnClickListener{
        val intent = Intent(this, MyService::class.java)
        bindService(intent, connection, Context.BIND_AUTO_CREATE)    //绑定Service
    }
    btn2.setOnClickListener{
        val intent = Intent(this, MyService::class.java)
        unbindService(connection)    //解绑Service
    }
    btn3.setOnClickListener{
        function.callJump()    //就可以调用Service里的方法了
        function.callEat()
    }
}

4.3 混合方式

  • 既长期在后台运行,又能调用 Service 里面的方法。
  • 在 Activity 的 onCreate() 中 startService() 并 bindService(),顺序无所谓。
  • 在 Activity 的 onDestroy()  中 unbindService(),根据情况在需要的地方stopService(),顺序无所谓两者都调用才会销毁服务。

五、进程间通信

Aidl接口描述语言,专门用来解决调用远程服务的方式。

调用第三方支付中APP中的付款功能,要将支付信息传递过去:

①用隐式意图开启到对方Service
    Intent intent = new Intent();
    intent.setAction("cn.hugmua.demo.remote");
    bindService(intent,conn,BIND_AUTO_CREATE);    
②远程应用中,把暴露出来的接口Iservice.java改成Iservice.aidl,删除public权限修饰(public是包和包之间,而现在用于多个工程之间)
③远程应用中,自定义的MyBinder只继承Stub。在gen目录里生成了新的Iservice.java,里面的Stub帮我们继承了Binder和实现了Iservice
④本地应用中,创建和远程服务中相同包名,并把Iservice.aidl复制过来,gen目录下会自动生成相应报名文件夹,里面有Iservice.java
⑤本地应用中,在连接器ServiceConnection的onServiceConnected()中,调用Stub静态方法anInterface()将IBinder转换为Iservice
    public void onServiceConnected(ComponentName name, IBinder service) {
        iservice = Stub.anInterface(service);
    }
⑥现在就可以用iservice对象调用远程服务里的方法了,要处理异常。

六、前台Service(保活)

从Android 8.0开始,只有APP保持在前台可见状态的情况下 Service 才能保证稳定运行,一旦进入后台 Service 随时都有可能被系统回收,防止恶意APP长期在后台占用手机资源。因此需要 Service 能一直保持运行状态就可以使用前台Service。

  • 前台Service在状态栏里会显示图标,下拉通知栏有显示通知。(这样APP就以另一种形式保持前台可见让用户清楚得知道什么APP占用着资源)
  • 前台Service优先级较高,不会由于系统内存不足而被回收;后台Service优先级较低,当系统出现内存不足情况时,很有可能会被回收。

<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />

从Android 9.0系统开始,必须在 Manifest 中进行权限声明。

override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
    //构建"点击通知后打开MainActivity"的Intent对象
    val myIntent = Intent(this, MainActivity::class.java)
    val pendingIntent = PendingIntent.getActivity(this, 0, myIntent, 0)
    //构建通知
    val notification = Notification.Builder(this, "")    //获取构建器
        .setContentTitle("标题")  //设置通知的标题
        .setContentText("内容")   //设置通知的内容
        .setSmallIcon(R.mipmap.ic_launcher) //设置状态栏小图标
        .setLargeIcon(R.mipmap.ic_launcher) //设置通知栏大图标
        .setContentIntent(pendingIntent)    //设置点击通知后的操作
        .build()    //构建一个通知
    //让Service变成前台Service,并在系统的状态栏显示出来
    startForeground(1, notification) //参数一唯一标识停止的时候还要用,参数二通知
    return super.onStartCommand(intent, flags, startId)
}

override fun onDestroy() {
    super.onDestroy()
    stopForeground(1)    //开启时设置的唯一标识
}

七、耗时任务 IntentService

Service默认运行在主线程,耗时操作需要开启子线程。Service一旦启动就会一直运行,直到调用 stopService()、stopSelf() 或被系统回收,我们可能会忘记调用。为了简单创建一个异步会自动停止的Service,可以使用IntentService。

class MyService : Service() {
    override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int {
        thread {
            //耗时任务
            stopSelf()    //停止Service
        }
    return super.onStartCommand(intent, flags, startId)
    }
}

class MyIntentService : IntentService("MyIntentService") {    //传入的字符串随意,只在调试的时候有用
    override fun onHandleIntent(intent: Intent?) {
        //耗时任务
    }
    override fun onDestroy() {
        super.onDestroy()
        Log.d("MyIntentService", "有自动停止")
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Android - Service 的相关文章

  • APK META-INF/library_release.kotlin_module 中复制的重复文件

    我最近通过 JitPack 添加了两个 Android 库 但出现以下错误 Duplicate files copied in APK META INF library release kotlin module 我已经清除了缓存 并尝试使
  • 如何检测android中的颠倒方向?

    在我的 Android 应用程序中 我有全景图像 并且我使用 TYPE ORIENTATION 传感器根据手机运动旋转该图像 它对于横向和纵向都工作良好 这是旋转逻辑的代码 Override public void onSensorChan
  • Android,让文本切换器成为中心?

    如何集中我的文本切换器 我尝试过设置重力 但似乎不起作用 ts setFactory new ViewFactory public View makeView TextView t new TextView this t setTypefa
  • Android Studio磁盘空间不足如何解决?

    我随机收到此错误 并且不确定为什么 Android Studio 的磁盘空间变低 Android Studio 系统目录分区磁盘空间不足 Update 此应用程序安装在运行 10 10 1 的 Mac 上 具有 251GB 内部存储和占用
  • 不使用 CookieManager 的 Android 会话 cookie

    我的应用程序进行多次网络调用以获得身份验证 我需要将此会话存储在 cookie 中 我想使用 Cookie Manager 但经过一些研究后 我发现它仅适用于 API 9 及更高版本 并且我的应用程序需要向后兼容 我使用 HTTPURLCo
  • PhoneGap 是应用程序开发的好选择吗? [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • 注销时Firebase facebook按钮android身份验证

    我在我的 Android 应用程序中使用 firebase 并在 facebook SDK 中使用登录 我面临的唯一问题是 当我使用 facebook 登录然后注销时 facebook 登录按钮处于 注销 状态 当我单击它时 它会询问我是否
  • Android 在创建时出现 SQLiteException

    首先我想说我是android新手 所以如果这个问题太愚蠢我很抱歉 我正在为带有两个表的 SQLite 数据库编写一个内容提供程序 表格上是在导航抽屉活动中显示列表 第二个表格是在 ListFragment 中显示 每次启动应用程序时 我都会
  • Android接收通知打开和取消事件

    我从 webService 接收数据以生成自定义通知 我想追踪Intent要知道open 点击 或cancel 滑动 通知上的事件 以报告服务器进行分析 有没有听众onIntentStart or onIntentCanceled 也许是通
  • 如何在不改变的情况下将字符串转换为字节?

    我需要一个解决方案将字符串转换为字节数组而不需要像这样进行更改 Input String s Test Output String s Test byte b Test 当我使用 s getBytes 那么回复是 B 428b76b8 但我
  • 使用 Web 服务时如何将 java.sql.Date 序列化为 Long?

    我有一个简单的 Web 服务方法 它返回一个简单的 java 类作为返回值 WebMethod public SimpleClass myMethod XmlRootElement public class SimpleClass XmlE
  • Android - 内容值覆盖现有行

    我正在尝试使用插入值ContentValues 我已将 5 个值插入到 5 列中 运行应用程序后 我只有最后一组值的行ContentValues 前四组未插入 ContentValues cv new ContentValues cv pu
  • 在Android的activity中调用onResume

    在活动的过程中通过调用 this OnResume 强制 onResume 事件可以吗 或者我应该实现另一个由 OnResume 和第一个成员调用的过程 实现在您的重写中调用的另一个过程onResume 后者不打算由您调用 它是一种方便的方
  • Android apk 调试模式工作正常,但发布模式给出太多警告

    我正在尝试从 eclipse 获取签名的 APK 我有一个可调试的 apk 版本 运行良好 现在发布时 当我尝试使用 Eclipse ADT 进行编译和签名时 我收到很多警告 其中大部分是can t find superclass or i
  • 找不到资源矢量绘图的异常

    我将在某些设备上运行我的应用程序 其崩溃日志如下 01 04 16 54 02 206 7466 7466 com lawnmowers E AndroidRuntime FATAL EXCEPTION main Process com l
  • 如何使用asynctask显示倒计时的进度条?

    在我的应用程序中 我希望用户按下按钮 然后等待 5 分钟 我知道这听起来很糟糕 但就这样吧 5 分钟等待期间的剩余时间应显示在进度条中 我使用带有文本视图的 CountDownTimer 来倒计时 但我的老板想要看起来更好的东西 这就是进度
  • 在 TextView onTextChanged 上设置文本

    我有一个定义为类属性的文本视图 以便我可以在整个类中访问它 在 onCreate 方法中我执行以下操作 chars TextView findViewById R id chars chars setText 300 之后 public v
  • 如何用 XML 制作双渐变(类似 iphone)

    如何使用 XML 制作这种可绘制渐变 我可以做一个从颜色 A 到颜色 B 的简单渐变 但我不知道如何在同一个可绘制对象中组合两个渐变 我终于找到了一个带有图层列表的解决方案 这对我来说已经足够好了
  • RecyclerView元素更新+异步网络调用

    我有一个按预期工作的回收视图 我的布局中有一个按钮可以填充列表 该按钮应该进行异步调用 根据结果 我更改按钮的外观 这一切都发生得很好 但是 当我单击按钮并快速向下滚动列表时 异步调用的结果会更新新视图的按钮 代替旧视图的视图 我该如何处理
  • Android 中带有无尽列表视图滚动的 AsyncTask

    我正在创建一个应用程序 其中我需要有无限的滚动列表视图 我不想在我的应用程序中使用任何库 我在网上看到了一些有助于实现此类列表视图的示例 但我的疑问是 当我的数据来自服务器并在异步任务中进行解析时 如何才能拥有无尽的列表视图 如何从滚动异步

随机推荐

  • 看这篇就够了——opencv与libopencv与cv_bridge的安装与使用

    一 基本关系 opencv OpenCV的全称是Open Source Computer Vision Library xff0c 是一个跨平台的计算机视觉处理开源软件库 xff0c 是由Intel公司俄罗斯团队发起并参与和维护 xff0c
  • Linux下更改oracle客户端字符集和服务端字符集

    from http blog csdn net chid article details 6166506 Linux 下更改 oracle 客户端字符集和服务端字符集 1 Linux 下更改 oracle 客户端字符集 xff0c 即设置环
  • C语言书籍推荐

    C 语言书籍推荐 宗旨 xff1a 技术的学习是有限的 xff0c 分享的精神是无限的 一 基础 1 C语言入门很简单 零起点学通C语言 xff08 多媒体范例教学 xff09 C语言从入门到精通 2 C程序设计语言 第2版 新版 C程序设
  • Jetson配置realsense D435i SDK以及realsense-ros

    一 命令安装 SDK sudo apt install librealsense2 realsense viewer 测试 realsense ros sudo apt get install ros ROS DISTRO realsens
  • 工程(十一)——NUC11+D435i+VINS-FUSION+ESDF建图(github代码)

    博主的合并代码 git 64 github com huashu996 VINS FUSION ESDFmap git 一 D435i深度相机配置 1 1 SDK 43 ROS 参考我之前的博客 xff0c 步骤和所遇见的问题已经写的很详细
  • 从零入门激光SLAM(八)——ROS常用消息

    大家好呀 xff0c 我是一个SLAM方向的在读博士 xff0c 深知SLAM学习过程一路走来的坎坷 xff0c 也十分感谢各位大佬的优质文章和源码 随着知识的越来越多 xff0c 越来越细 xff0c 我准备整理一个自己的激光SLAM学习
  • 嵌入式软件开发,快五年,没有成就感,快迷失自己了

    嵌入式软件开发 xff0c 快五年 xff0c 没有成就感 xff0c 快迷失自己了 看到了这个的问题 xff0c 其实这个问题何尝不是很多软件开发人员的困惑呢 至少我自己如此 在任何公司 xff0c 个人永远就是一枚螺丝钉的角色 当公司的
  • 从高校中走出的 Apache 顶级项目 —— IoTDB 核心成员黄向东

    本期访谈嘉宾 xff1a 黄向东 Apache 顶级开放源代码项目 IoTDB xff08 物联网数据库 xff09 核心成员 2021 年开源先锋 清华大学软件学院助理研究员 Q xff1a 简单介绍一下 Apache IoTDB IoT
  • pixhawk入门 -- 编译环境问题解决过程

    pixhawk 编译的基本操作步骤 xff1a 1 xff09 下载固件仓 git clone https github com PX4 Firmware git 2 xff09 更新固件代码 cd Firmware git submodu
  • 树莓派的供电问题

    树莓派99 的故障来自于5V电源 树莓派出现任何故障 xff08 死机 键盘和鼠标不工作 显示器变暗或失真 终端程序出现乱码 xff0c 无法开机 xff0c 运行的程序死机 xff0c usb设备无法识别或不工作 网络故障等 xff09
  • 树莓派的操作系统介绍

    1 Raspbian 单纯的Arm版的Linux系统 xff0c 基于Debian 是当前实用最广泛的操作系统 2 Pidora 单纯的Arm版的Linux系统 xff0c 基于Fedora 是拥有另一种风格的树莓派操作系统 3 Arch
  • gd32e103加入freertos的步骤

    gd32E103的芯片比较强大 xff0c m4的内核 xff0c 120mhz主频 xff0c 跑freertos是没有问题的 作为一个轻量级的操作系统 xff0c FreeRTOS提供的功能包括 xff1a 任务管理 时间管理 信号量
  • oracle数据库开启的时候 是先开监听还是先开主服务,关数据库的时候呢???...

    启动的时候无所谓先后 xff0c 关闭的话 1 首先是关闭监听 xff08 让远程客户端无法再连进来 xff09 xff1b 2 发出一个系统检查点 xff0c 让数据文件和控制文件的系统修改号统一 xff1b xff08 alter sy
  • Docker本地images删除问题

    背景 测试环境和生产环境 部署了不同的registry服务 xff0c 通过cli 操作过生产环境或测试环境push xff0f pull image功能 本地虚拟机 xff0c docker image 残留了很多image xff0c
  • Aruco的使用+opencv+opencv_contrib+cmake

    Aruco的使用 By GuangyeHu 1 下载 xff1a https sourceforge net projects aruco files 解压到相应的文件夹 2 安装Cmake 本次实现使用的是cmake 3 15 1 win
  • Nginx 配置多个Vue项目

    背景 xff1a 公司要求将之前用不同端口号区分的三个独立的系统统一配置到统一域名下 VUE项目配置 示例 xff1a 有两个项目 第一个 xff1a 打包到 96 test1 96 目录中 xff1b 第二个 xff1a 打包到 96 t
  • AD随堂笔记

    算起来 xff0c 这次算是第四次打板子了 xff0c 还是出现了不可饶恕的错误 串口三的TXD RXD接反了 xff0c 还有一根线是短路的 造成的原因 xff0c 就是没有进行规则检查 因为这个板子是在原来基础上面改的 xff0c 大意
  • 学习Linux必备书籍推荐

    xfeff xfeff 鸟哥的私房菜 xff08 第3版 xff09 xff0c 鸟哥著 xff1a 这本书内容丰富全面 xff0c 基本概念的讲解非常细致 xff0c 深入浅出 xff0c 各种功能和命令的介绍都配以大量的实例操作和详尽的
  • 无人机目标检测 Darknet-ROS 学习(一)

    无人机目标检测 Darknet ROS 学习 xff08 一 xff09 简介 在无人机上实现目标检测 xff0c 使用的设备是阿木实验室P200 xff0c 飞控是PX4 xff0c 板载计算机是TX2 xff0c 目的是在无人机有限的计
  • Android - Service

    前台20s后台200s不执行玩就报ANR异常 一 概念 没有界面在后台长期运行在主线程中的一个组件 ServiceThread可以配置执行在不同的进程中 CPU调度的最小单位 任何有Context的地方都可以控制Service当Activi