Android14新特性 开启前台service服务

news2025/7/8 18:44:19

1. Android14新特性

1.1. 场景

  在Android14(targetSDK=34)系统手机开启前台service服务崩溃

ATAL EXCEPTION: main
                 Process: com.inspur.lbrd, PID: 15634
                 java.lang.RuntimeException: Unable to create service com.inspur.lbrd.service.KeepAliveService: android.app.MissingForegroundServiceTypeException: Starting FGS without a type  callerApp=ProcessRecord{957facf 15634:com.inspur.lbrd/u0a352} targetSDK=34
                 	at android.app.ActivityThread.handleCreateService(ActivityThread.java:5182)
                 	at android.app.ActivityThread.-$$Nest$mhandleCreateService(Unknown Source:0)
                 	at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2638)
                 	at android.os.Handler.dispatchMessage(Handler.java:108)
                 	at android.os.Looper.loopOnce(Looper.java:226)
                 	at android.os.Looper.loop(Looper.java:328)
                 	at android.app.ActivityThread.main(ActivityThread.java:9128)
                 	at java.lang.reflect.Method.invoke(Native Method)
                 	at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:586)
                 	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1099)
                 Caused by: android.app.MissingForegroundServiceTypeException: Starting FGS without a type  callerApp=ProcessRecord{957facf 15634:com.inspur.lbrd/u0a352} targetSDK=34
                 	at android.app.MissingForegroundServiceTypeException$1.createFromParcel(MissingForegroundServiceTypeException.java:53)
                 	at android.app.MissingForegroundServiceTypeException$1.createFromParcel(MissingForegroundServiceTypeException.java:49)
                 	at android.os.Parcel.readParcelableInternal(Parcel.java:4884)
                 	at android.os.Parcel.readParcelable(Parcel.java:4866)
                 	at android.os.Parcel.createExceptionOrNull(Parcel.java:3066)
                 	at android.os.Parcel.createException(Parcel.java:3055)
                 	at android.os.Parcel.readException(Parcel.java:3038)
                 	at android.os.Parcel.readException(Parcel.java:2980)
                 	at android.app.IActivityManager$Stub$Proxy.setServiceForeground(IActivityManager.java:7415)
                 	at android.app.Service.startForeground(Service.java:775)
                 	at com.inspur.lbrd.service.KeepAliveService.setForeground(SourceFile:118)
                 	at com.inspur.lbrd.service.KeepAliveService.onCreate(SourceFile:32)
                 	at android.app.ActivityThread.handleCreateService(ActivityThread.java:5169)
                 	at android.app.ActivityThread.-$$Nest$mhandleCreateService(Unknown Source:0) 
                 	at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2638) 
                 	at android.os.Handler.dispatchMessage(Handler.java:108) 
                 	at android.os.Looper.loopOnce(Looper.java:226) 
                 	at android.os.Looper.loop(Looper.java:328) 
                 	at android.app.ActivityThread.main(ActivityThread.java:9128) 
                 	at java.lang.reflect.Method.invoke(Native Method) 
                 	at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:586) 
                 	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1099) 

在这里插入图片描述

1.2. 解决方案

1.2.1. 在清单文件AndroidManifest.xml添加权限和配置

 <!-- android14前台常住服务权限-->
    <uses-permission android:name="android.permission.FOREGROUND_SERVICE_LOCATION" />
  <service
      android:name=".service.KeepAliveService"
      android:foregroundServiceType="location" />

1.2.2. 授权

      if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
            // 定位权限
            requestPermissionLauncher
                    .launch(Manifest.permission.ACCESS_COARSE_LOCATION);
            requestPermissionLauncher
                    .launch(Manifest.permission.ACCESS_FINE_LOCATION);
            requestPermissionLauncher
                    .launch(Manifest.permission.ACCESS_BACKGROUND_LOCATION);
        }
    ActivityResultLauncher<String> requestPermissionLauncher
            = registerForActivityResult(
            new ActivityResultContracts.RequestPermission(),
            result -> {
                if (result.equals(true)) {
                    //权限获取到之后的动作
                } else {
                    //权限没有获取到的动作
                }
            });

1.2.3. service服务

public class KeepAliveService extends Service {
    private final String TAG = "szyj_GridTraceS-";

    public KeepAliveService() {
    }
    @Override
    public void onCreate() {
        super.onCreate();
        // 添加常驻通知栏
        setForeground();
       // startXcService();
    }
    private void startXcService() {
        try {
            String patrolStatus = SpUtil.getInstance(this).getString(
                    GridTraceConstant.SP_PATROL_STATUS,
                    GridTraceConstant.SP_PATROL_STATUS_FALSE);
            //巡查服务已开启
            if (TextUtils.equals(patrolStatus, GridTraceConstant.SP_PATROL_STATUS_TRUE)) {
                if (!ServiceUtil.isServiceRunning(this, GridTraceService.class.getName())) {
                    startService(new Intent(this, GridTraceService.class));
                }
            } else {//未开启巡查服务
                if (ServiceUtil.isServiceRunning(this, GridTraceService.class.getName())) {
                    stopService(new Intent(this, GridTraceService.class));
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        //可将onStartCommand() 方法的返回值设为 START_STICKY或START_REDELIVER_INTENT ,
        //该值表示服务在内存资源紧张时被杀死后,在内存资源足够时再恢复。
        //也可将Service设置为前台服务,这样就有比较高的优先级,在内存资源紧张时也不会被杀掉。
        return START_STICKY;
        //return super.onStartCommand(intent, flags, startId);
    }
    @Override
    public void onDestroy() {
        super.onDestroy();
        // 删除图标
        stopForeground(true);
    }

    @Override
    public IBinder onBind(Intent intent) {
        throw new UnsupportedOperationException("Not yet implemented");
    }
    /**
     * 添加常驻通知栏
     */
    private void setForeground() {
        NotificationManager notificationManager = (NotificationManager) getSystemService
                (Context.NOTIFICATION_SERVICE);
        String notificationId = "serviceid";
        String notificationName = "servicename";
        int noticeId = 2;
        Notification.Builder builder = new Notification.Builder(this);
        //创建NotificationChannel
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            NotificationChannel channel = new NotificationChannel(notificationId,
                    notificationName, NotificationManager.IMPORTANCE_HIGH);
            channel.enableLights(true);//设置高亮(选填)
            channel.setShowBadge(true);//设置角标(选填)
            //设置锁屏可见(选填)
            channel.setLockscreenVisibility(Notification.VISIBILITY_PUBLIC);
            notificationManager.createNotificationChannel(channel);
            builder.setChannelId(notificationId);
        }
        Intent intent = new Intent(KeepAliveService.this, MainActivity.class);
        PendingIntent pendingIntent;
        //Android12
        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.S) {
            pendingIntent = PendingIntent.getActivity(this,
                    123, intent, PendingIntent.FLAG_IMMUTABLE);
        } else {
            pendingIntent = PendingIntent.getActivity(this,
                    123, intent, PendingIntent.FLAG_ONE_SHOT
                            | PendingIntent.FLAG_MUTABLE);
        }
        builder.setSmallIcon(R.mipmap.icon_app)
                .setLargeIcon(BitmapFactory.decodeResource(getResources(),
                        R.mipmap.icon_app))
                .setContentTitle(getString(R.string.app_name))//选填
                .setContentText(getString(R.string.app_name))//选填
                .setWhen(System.currentTimeMillis())
                .setContentIntent(pendingIntent);
        Notification notification = builder.build();
        startForeground(noticeId, notification);
    }
}

1.2.4. 启动service服务

  if (!ServiceUtil.isServiceRunning(this, KeepAliveService.class.getName())) {
            startService(new Intent(this, KeepAliveService.class));
        }

&emsp;&emsp;判断服务是否开启

public class ServiceUtil {
    /**
     * @param context
     * @param className service后台服务名称
     * @return
     * @desc 查询service是否在运行
     */
    public static boolean isServiceRunning(Context context, String className) {
        ActivityManager activityManager = (ActivityManager) context
                .getSystemService(Context.ACTIVITY_SERVICE);
        List<ActivityManager.RunningServiceInfo> serviceList = activityManager
                .getRunningServices(Integer.MAX_VALUE);

        if (!(serviceList.size() > 0)) {
            return false;
        }

        for (int i = 0; i < serviceList.size(); i++) {
            ActivityManager.RunningServiceInfo serviceInfo = serviceList.get(i);
            ComponentName serviceName = serviceInfo.service;

            if (serviceName.getClassName().equals(className)) {
                return true;
            }
        }
        return false;
    }
}

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

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

相关文章

[GDOUCTF 2023]泄露的伪装

[GDOUCTF 2023]泄露的伪装 wp 进入页面&#xff0c;会发现什么也没有&#xff1a; 目录扫描&#xff1a; dirsearch -u “http://node4.anna.nssctf.cn:28588/” 扫出了两个文件&#xff0c;都去访问一下&#xff0c;test.txt 是源码的副本&#xff0c;由于是文本文件&…

STL——集合算法

算法简介&#xff1a; set_intersection // 求两个容器的交集set_union // 求两个容器的并集set_difference // 求两个容器的差集 1.set_intersection 函数原型&#xff1a; set_intersection(iterator beg1, iterator end1, iterator beg2, iterator end2, iterator dest);…

NFS的基本使用

#江南的江 #每日鸡汤&#xff1a;岁月匆匆&#xff0c;时光荏苒&#xff0c;感悟人生路漫漫&#xff0c;不忘初心方得始终。 #初心和目标&#xff1a;和从前的自己博弈。 NFS(存储共享服务) 本文要点摘要&#xff1a; 下面将讨论什么是NFS&#xff0c;如何配置NFS&#xff0c;…

AI产品经理-借力

AI产品经理-借力&#xff1a;学会善用供应商改造自有产品 1.整个项目的工作方法 2.项目启动-行业调研 3.项目启动-供应商选型

【数据结构——二叉树】二叉树及其应用2023(头歌习题)【合集】

目录 第1关&#xff1a;括号表示法创建二叉树任务描述相关知识编程要求测试说明完整代码 第2关&#xff1a;先序序列创建二叉树任务描述相关知识二叉树的前序遍历如何创建一颗二叉树伪代码如下&#xff1a; 二叉树的中序遍历 编程要求测试说明完整代码 第3关&#xff1a;计算二…

蓝桥杯C/C++程序设计——单词分析

题目描述 小蓝正在学习一门神奇的语言&#xff0c;这门语言中的单词都是由小写英文字母组 成&#xff0c;有些单词很长&#xff0c;远远超过正常英文单词的长度。小蓝学了很长时间也记不住一些单词&#xff0c;他准备不再完全记忆这些单词&#xff0c;而是根据单词中哪个字母出…

Python魔法方法之__getattr__和getattribute

在Python中有这两个魔法方法容易让人混淆&#xff1a;__getattr__和getattribute。通常我们会定义__getattr__而从来不会定义getattribute&#xff0c;下面我们来看看这两个的区别。 __getattr__魔法方法 class MyClass:def __init__(self, x):self.x xdef __getattr__(self, …

HTML标签基础入门

HTML 基本语法概述标签关系HTML基础结构HTML常用标签标题标签示例 段落和换行标签示例 文本格式化标签示例 div和span标签示例 图像标签和路径示例 超链接标签示例 注释 ctrl/特殊字符示例 表格标签 表头单元格标签表格属性示例 合并单元格示例 列表标签无序列表有序列表自定义…

SpringBoot集成支付宝,看这一篇就够了。

前 言 在开始集成支付宝支付之前&#xff0c;我们需要准备一个支付宝商家账户&#xff0c;如果是个人开发者&#xff0c;可以通过注册公司或者让有公司资质的单位进行授权&#xff0c;后续在集成相关API的时候需要提供这些信息。 下面我以电脑网页端在线支付为例&#xff0c;介…

Linux系统使用yum安装MySQL

部署MySQL数据库有多种部署方式&#xff0c;常用的部署方式就有三种&#xff1a;yum安装、rpm安装以及编译安装。每一种安装方式都有自己的优势&#xff0c;那么企业当中通常情况下采用的是rpm和二进制安装的方式。 MySQL官网下载地址 Mysql 5.7的主要特性 更好的性能&#xf…

费曼学习法应用:谈自私和教育的引导

今天这个还是来源于我和九迁的对话&#xff0c;起因是中午吃饭的时候&#xff0c;九迁在学校与班主任老师和数学老师对话中带来的思考。 先听音频&#xff1a; 对话内容&#xff08;以下内容可以边听边看&#xff0c;属于语音转换过来的文字&#xff0c;最后有个总结&#xff0…

中文字符占用字节即相关原理(实现中文(中英混合)字符串的反转)

如有不对欢迎指正。 目录 一.ASCLL字符和中文字符 1.使用无符号数表示的原因(对于中文字符)&#xff1a; 2.但是并不是所有情况都是用无符号数(以下目前只是猜测,如有问题欢迎指正) &#xff1a; 1. 什么时候使用无符号数表示: 2. 不需要使用的情况&#xff1a; …

46、激活函数 - Relu 激活

本节介绍一个在神经网络中非常常见的激活函数 - Relu 激活函数。 什么是ReLU激活函数 ReLU 英文名为 Rectified Linear Unit,又称修正线性单元,是一种简单但很有效的激活函数,它的定义如下: 即当输入 x 大于零时,输出等于他自己;当输入小于等于零时,输出为零,下面是re…

2023年成都市中等职业学校学生技能大赛“网络搭建及应用”赛项竞赛样卷

2023年成都市中等职业学校学生技能大赛 “网络搭建及应用”赛项竞赛样卷 &#xff08;总分1000分&#xff09; 目录 2023年成都市中等职业学校学生技能大赛 “网络搭建及应用”赛项竞赛样卷 网络建设与调试项目&#xff08;500分&#xff09; 服务器搭建与运维项目&#xff08;…

2023年度业务风险报告:四个新风险趋势

目录 倒票的黄牛愈加疯狂 暴增的恶意网络爬虫 愈加猖獗的羊毛党 层出不穷的新风险 业务风险呈现四个趋势 防御云业务安全情报中心“2023年业务风险数据”统计显示&#xff0c;恶意爬虫风险最多&#xff0c;占总数的37.8%&#xff1b;其次是虚假账号注册&#xff0c;占18.79%&am…

负载均衡之LVS

LVS LVS 原理 IPVS LVS 的 IP 负载均衡技术是通过 IPVS 模块来实现的&#xff0c;IPVS 是 LVS 集群系统的核心软件&#xff0c;它的主要作用是&#xff1a;安装在 Director Server 上&#xff0c;同时在 Director Server 上虚拟出一个 IP 地址&#xff0c;用户必须通过这个虚…

【web安全】短信等各类验证码的绕过思路整理

前言 本文是对一些验证码可能出现的问题的总结。 验证码的种类分析 首先验证码有两种&#xff1a; 1.短信验证码&#xff0c;这种通常出现在一些登录&#xff0c;修改绑定信息等位置处。 2.人机验证码&#xff0c;这种一般是用来防止机器操作和密码爆破的&#xff0c;通常…

每日一练(编程题-C/C++)

目录 CSDN每日一练1. 2023/2/27- 一维数组的最大子数组和(类型&#xff1a;数组 难度&#xff1a;中等)2. 2023/4/7 - 小艺照镜子(类型&#xff1a;字符串 难度&#xff1a;困难)3. 2023/4/14 - 最近的回文数(难度&#xff1a;中等)4. 2023/2/1-蛇形矩阵(难度&#xff1a;困难)…

数据采集来源有哪些?怎么做?

数据采集 数据采集&#xff0c;又称数据获取&#xff0c;是指从传感器和其他待测设备等模拟和数字被测单元中自动采集非电量或者电量信号&#xff0c;送到上机中进行分析、处理。 ✦ 一、电商数据采集主要来源 1、互联网公开数据 互联网是数据采集的主要来源之一&#xff0c…

kivy开发一个登陆界面

Kivy Kivy是一个用于开发跨平台移动应用&#xff08;如Android和iOS&#xff09;以及桌面应用&#xff08;如Windows、Linux和macOS&#xff09;的Python框架。它采用开源许可证&#xff08;MIT许可证&#xff09;&#xff0c;提供了丰富的图形界面组件和工具&#xff0c;以便…