31.HarmonyOS App(JAVA)鸿蒙系统app Service服务的用法

鸿蒙系统app Service服务的用法

后台任务调度和管控

  • HarmonyOS将应用的资源使用生命周期划分为前台、后台和挂起三个阶段。前台运行不受资源调度的约束,后台会根据应用业务的具体任务情况进行资源使用管理,在挂起状态时,会对应用的资源使用进行调度和控制约束,以保障其他体验类业务对资源的竞争使用。
  • 后台任务调度和管控主要对在后台状态下的资源使用进行控制,应用从前台退到后台,可能有各种业务诉求,为了达到系统资源使用能效最优的目的,HarmonyOS提供了后台任务能力。

后台任务类型

本文描述的后台任务特指应用或业务模块处于后台(无可见界面)时,有需要继续执行或者后续执行的业务。对这些应用不可见但要继续或者将要执行的业务动作,为避免后台任务调度和管控对业务执行的影响,HarmonyOS将后台任务分为三种类型:

  1. 无后台业务:退后台后,无任务需要处理。
  2. 短时任务:退后台后,如果有紧急不可推迟且短时间能完成的任务,如应用退后台要进行数据压缩,不可中断,则使用短时任务申请延迟进入挂起(Suspend)状态。
  3. 长驻任务:如果是用户发起的可感知业务需要长时间后台运行的,如后台播放音乐、导航、上传下载、设备连接、VoIP等,则使用长驻任务避免进入挂起(Suspend)状态。

短时任务

退到后台的应用有不可中断且短时间能完成的任务时,可以使用短时任务机制,该机制允许应用在后台短时间内完成任务,保障应用业务运行不受后台生命周期管理的影响。

  • 注意:短时任务仅针对应用的临时任务提供资源使用生命周期保障,限制单次最大使用时长为3分钟,全天使用配额默认为10分钟(具体时长系统根据应用场景和系统状态智能调整)。
  • 接口请参考:BackgroundTaskManager接口说明。

短时任务使用约束

短时任务的使用需要遵从如下约束和规则:

  • 申请时机:允许应用在前台时,或退后台在被挂起之前(应用退到后台默认有6~12秒的运行时长,具体时长由系统根据具体场景决定)申请延迟挂起,否则可能被挂起(Suspend),导致申请失败。
  • 超时:延迟挂起超时(Timeout),系统通过回调知会应用,应用需要取消对应的延迟挂起,或再次申请延迟挂起。超期不取消或不处理,该应用会被强制取消延迟挂起。
  • 取消时机:任务完成后申请方应用主动取消延时申请,不要等到超时后被系统取消,否则会影响该应用的后台允许运行时长配额。
  • 配额机制:为了防止应用滥用保活,或者申请后不取消,每个应用每天都会有一定配额(会根据用户的使用习惯动态调整),配额消耗完就不再允许申请短时任务,所以应用完成短时任务后立刻取消延时申请,避免消耗配额。(注,这个配额指的是申请的时长,系统默认应用在后台运行的时间不计算在内)。

长驻任务

长驻任务类型给用户能直观感知到的且需要一直在后台运行的业务提供后台运行生命周期的保障。比如,业务需要在后台播放声音,或者需要在后台持续导航定位等,此类用户可以感知到的后台业务行为,可以通过使用长驻任务对应的后台模式保障业务在后台的运行,支撑应用完成在后台的业务。

后台模式分类

HarmonyOS提供了十种后台模式,供需要在后台做长驻任务的业务使用,具体的后台模式类型如下:

长驻任务后台模式

英文名

描述

数据传输

data-transfer

通过网络/对端设备进行数据下载、备份、分享、传输等业务

播音

audio-playback

音频输出业务

录音

audio-recording

音频输入业务

画中画

picture-in-picture

画中画、小窗口播放视频业务

音视频通话

voip

音视频电话,VoIP业务

导航/位置更新

location

定位、导航业务

蓝牙设备连接及传输

bluetooth-interaction

蓝牙扫描、连接、传输业务

WLAN设备连接及传输

wifi-interaction

WLAN扫描、连接、传输业务

屏幕抓取

screen-fetch

录屏、截屏业务

多设备互联

multiDeviceConnection

多设备互联,分布式调度和迁移等业务

使用长驻任务

  1. HarmonyOS应用开发工具DevEco Studio在业务的ServiceAbility创建的时候提供了后台模式的选择,针对当前创建的ServiceAbility可以赋予对应的后台模式类型设置,如下图所示:

    业务根据需要选择对应的后台模式以后,会在应用的config.json文件中新创建的ServiceAbility组件下生成对应选择的后台模式配置,如下图所示:

    说明

    只有ServiceAbility才有对应的后台模式类型选择和配置。

  2. 在Service创建的方法里面调用keepBackgroundRunning(),将Service与通知绑定。

    调用keepBackgroundRunning()方法前需要在配置文件中声明ohos.permission.KEEP_BACKGROUND_RUNNING权限。

    完成对应的后台业务以后,在销毁服务的方法中调用cancelBackgroundRunning()方法,即可停止使用长驻任务。

    请参考:前台Service。

长驻任务使用约束

  1. 如果用户选择可感知业务(如播音、导航、上传下载等),触发对应后台模式,在任务启动时或退入后台时,需要提醒用户。
  2. 如果任务结束,应用应主动退出后台模式。若在后台运行期间,系统监测到应用并未使用对应后台模式的资源,则会被挂起(Suspend)。
  3. 避免不合理地申请后台长驻任务,长驻任务类型要与应用的类型匹配,如任务类型与应用类型匹配表所示,如果执行的任务和申请的类型不匹配,也会被系统检测到并被挂起(Suspend)。
  4. 长驻任务是为了真正在后台长时间执行某任务,如果一个应用申请了长驻任务,但在实际运行过程中,并未真正运行或执行此类任务时,也会被系统检测到并被挂起(Suspend)。

托管任务

托管任务是系统提供的一种后台代理机制。通过系统提供的代理API接口,用户可以把任务(如后台下载、定时提醒、后台非持续定位)交由系统托管。

托管任务类型

  1. 托管任务-后台非持续定位(non-sustained Location):如果应用未申请location常驻模式,且在后台依然尝试获取位置信息,此时应用行为被视为使用非持续定位能力,后台非持续定位限制每30分钟提供一次位置信息。应用不需要高频次定位时,建议优先使用非持续定位。
  2. 托管任务-后台提醒代理(Reminder):后台提醒代理主要提供了一种机制,使开发者在应用开发时,可以调用这些接口去创建定时提醒,包括倒计时、日历、闹钟三种提醒类型。使用后台代理提醒能力后,应用可以被冻结或退出,计时和弹出提醒的功能将被后台系统服务代理。请参考:Reminder接口使用说明。
  3. 托管任务-后台下载代理:系统提供DownloadSession接口实现下载任务代理功能,应用提交下载任务后,应用被退出,下载任务仍然可以继续执行,且支持下载任务断点续传。请参考:DownloadSession接口使用说明。

托管任务使用约束

  1. 后台下载代理,系统会根据用户场景和设备状态,对不同的下载任务进行相应的管控,避免影响功耗和性能。
  2. 后台非持续定位和后台提醒代理需要申请对应的权限。后台提醒需要申请ohos.permission.PUBLISH_AGENT_REMINDER权限,后台非持续定位需要申请ohos.permission.LOCATION和ohos.permission.LOCATION_IN_BACKGROUND权限。
  3. 资源滥用会影响系统性能和功耗,托管任务类型要与应用类型匹配
<?xml version="1.0" encoding="utf-8"?>
<DirectionalLayoutxmlns:ohos="http://schemas.huawei.com/res/ohos"ohos:height="match_parent"ohos:width="match_parent"ohos:alignment="center"ohos:orientation="vertical"><Buttonohos:id="$+id:btn_start"ohos:height="match_content"ohos:width="match_content"ohos:background_element="#A306F52E"ohos:layout_alignment="horizontal_center"ohos:text="启动服务"ohos:text_size="40vp"/><Buttonohos:id="$+id:btn_stop"ohos:height="match_content"ohos:width="match_content"ohos:background_element="#A3235DEE"ohos:layout_alignment="horizontal_center"ohos:text="停止服务"ohos:text_size="40vp"/><Buttonohos:id="$+id:btn_connect"ohos:height="match_content"ohos:width="match_content"ohos:background_element="#A306F52E"ohos:layout_alignment="horizontal_center"ohos:text="连接服务"ohos:text_size="40vp"/><Buttonohos:id="$+id:btn_disconnect"ohos:height="match_content"ohos:width="match_content"ohos:background_element="#A3235DEE"ohos:layout_alignment="horizontal_center"ohos:text="断开连接服务"ohos:text_size="40vp"/><Buttonohos:id="$+id:btn_foreground"ohos:height="match_content"ohos:width="match_content"ohos:background_element="#A306F52E"ohos:layout_alignment="horizontal_center"ohos:text="启动前台service"ohos:text_size="40vp"/><Buttonohos:id="$+id:btn_foreground_stop"ohos:height="match_content"ohos:width="match_content"ohos:background_element="#A3235DEE"ohos:layout_alignment="horizontal_center"ohos:text="停止后台服务"ohos:text_size="40vp"/><TextFieldohos:id="$+id:text_filed_info"ohos:height="300vp"ohos:background_element="#FC0A84EF"ohos:text="信息显示区域"ohos:width="350vp"ohos:hint=""ohos:margin="2vp"ohos:text_size="20vp"/><Clockohos:id="$+id:clock"ohos:height="match_content"ohos:width="match_content"ohos:background_element="#FF80EF66"ohos:layout_alignment="left"ohos:text_size="20vp"/></DirectionalLayout>

创建服务类 

 

package com.example.serviceability;import ohos.aafwk.ability.Ability;
import ohos.aafwk.content.Intent;
import ohos.event.notification.NotificationRequest;
import ohos.rpc.IRemoteObject;
import ohos.hiviewdfx.HiLog;
import ohos.hiviewdfx.HiLogLabel;public class ForegroundServiceAbility extends Ability {private static final HiLogLabel LABEL_LOG = new HiLogLabel(3, 0xD001100, "Demo");@Overridepublic void onStart(Intent intent) {HiLog.error(LABEL_LOG, "ForegroundServiceAbility::onStart");NotificationRequest.NotificationNormalContent content3 = new NotificationRequest.NotificationNormalContent().setTitle("测试hap应用").setText("该service将会常留后台");NotificationRequest.NotificationContent notificationContent = new NotificationRequest.NotificationContent(content3);NotificationRequest request3 = new NotificationRequest(1001).setContent(notificationContent);keepBackgroundRunning(1001,request3);super.onStart(intent);}@Overridepublic void onBackground() {super.onBackground();HiLog.info(LABEL_LOG, "ForegroundServiceAbility::onBackground");}@Overridepublic void onStop() {super.onStop();HiLog.info(LABEL_LOG, "ForegroundServiceAbility::onStop");}@Overridepublic void onCommand(Intent intent, boolean restart, int startId) {}@Overridepublic IRemoteObject onConnect(Intent intent) {return null;}@Overridepublic void onDisconnect(Intent intent) {}
}

 

 

package com.example.serviceability;import ohos.aafwk.ability.Ability;
import ohos.aafwk.ability.LocalRemoteObject;
import ohos.aafwk.content.Intent;
import ohos.rpc.IRemoteObject;
import ohos.hiviewdfx.HiLog;
import ohos.hiviewdfx.HiLogLabel;public class ServiceAbility extends Ability {private static final HiLogLabel LABEL_LOG = new HiLogLabel(3, 0xD001100, "Demo");@Overridepublic void onStart(Intent intent) {HiLog.error(LABEL_LOG, "ServiceAbility::onStart");super.onStart(intent);}@Overridepublic void onBackground() {super.onBackground();HiLog.info(LABEL_LOG, "ServiceAbility::onBackground");}@Overridepublic void onStop() {super.onStop();HiLog.info(LABEL_LOG, "ServiceAbility::onStop");}@Overridepublic void onCommand(Intent intent, boolean restart, int startId) {}@Overridepublic IRemoteObject onConnect(Intent intent) {HiLog.info(LABEL_LOG,"OnConnect");return new MyRemoteObject();}@Overridepublic void onDisconnect(Intent intent) {HiLog.info(LABEL_LOG,"断开服务");}public class MyRemoteObject extends LocalRemoteObject{public MyRemoteObject(){HiLog.info(LABEL_LOG,"my remoteobject被创建");}//自定义方法,控制service的public String manipulateService(){HiLog.info(LABEL_LOG,"自定义方法,控制service的");return "exec_value666";}}}

package com.example.serviceability.slice;import com.example.serviceability.ForegroundServiceAbility;
import com.example.serviceability.ResourceTable;
import com.example.serviceability.ServiceAbility;
import ohos.aafwk.ability.AbilitySlice;
import ohos.aafwk.ability.IAbilityConnection;
import ohos.aafwk.content.Intent;
import ohos.aafwk.content.Operation;
import ohos.agp.components.Button;
import ohos.agp.components.Clock;
import ohos.agp.components.Component;
import ohos.agp.components.TextField;
import ohos.bundle.ElementName;
import ohos.rpc.IRemoteObject;public class MainAbilitySlice extends AbilitySlice {TextField textField;Clock clock2;@Overridepublic void onStart(Intent intent) {super.onStart(intent);super.setUIContent(ResourceTable.Layout_ability_main);textField  = (TextField) findComponentById(ResourceTable.Id_text_filed_info);clock2 = (Clock) findComponentById(ResourceTable.Id_clock);clock2.setFormatIn24HourMode("yyyy-MM-dd HH:mm:ss");Button btn_start =(Button) findComponentById(ResourceTable.Id_btn_start);Button btn_stop =(Button) findComponentById(ResourceTable.Id_btn_stop);Button btn_con =(Button) findComponentById(ResourceTable.Id_btn_connect);Button btn_discon =(Button) findComponentById(ResourceTable.Id_btn_disconnect);Button btn_foreground = (Button) findComponentById(ResourceTable.Id_btn_foreground);Button btn_foreground_stop = (Button) findComponentById(ResourceTable.Id_btn_foreground_stop);btn_foreground_stop.setClickedListener(new Component.ClickedListener() {@Overridepublic void onClick(Component component) {StopForegoundService();textField.append(clock2.getText()+"已停止后台服务\n");}});btn_foreground.setClickedListener(new Component.ClickedListener() {@Overridepublic void onClick(Component component) {StartForegoundService();textField.append(clock2.getText()+"启动后台服务\n");}});btn_start.setClickedListener(new Component.ClickedListener() {@Overridepublic void onClick(Component component) {StartService();}});btn_stop.setClickedListener(new Component.ClickedListener() {@Overridepublic void onClick(Component component) {StopService();}});btn_con.setClickedListener(new Component.ClickedListener() {@Overridepublic void onClick(Component component) {ConnectService();}});btn_discon.setClickedListener(new Component.ClickedListener() {@Overridepublic void onClick(Component component) {disconnectAbility(connection3);textField.append(clock2.getText()+"已断开服务\n");}});}public void StartService(){Intent intent1 = new Intent();Operation operation = new Intent.OperationBuilder().withDeviceId("").withBundleName("com.example.serviceability").withAbilityName("com.example.serviceability.serviceability").build();intent1.setOperation(operation);startAbility(intent1);}public void StopService(){Intent intent1 = new Intent();Operation operation = new Intent.OperationBuilder().withDeviceId("").withBundleName("com.example.serviceability").withAbilityName("com.example.serviceability.serviceability").build();intent1.setOperation(operation);stopAbility(intent1);}//连接服务public void ConnectService(){Intent intent1 = new Intent();Operation operation = new Intent.OperationBuilder().withDeviceId("").withBundleName("com.example.serviceability").withAbilityName("com.example.serviceability.ServiceAbility").build();intent1.setOperation(operation);connectAbility(intent1,connection3);}@Overridepublic void onActive() {super.onActive();}@Overridepublic void onForeground(Intent intent) {super.onForeground(intent);}//连接远程的Service的IAbilityConnection对象private IAbilityConnection connection3 = new IAbilityConnection() {//通过远程对象操纵Service@Overridepublic void onAbilityConnectDone(ElementName elementName, IRemoteObject iRemoteObject, int i) {ServiceAbility.MyRemoteObject object3 = (ServiceAbility.MyRemoteObject) iRemoteObject;String aa = object3.manipulateService();textField.append(clock2.getText()+" 服务信息:"+aa);}@Overridepublic void onAbilityDisconnectDone(ElementName elementName, int i) {}};public void StartForegoundService(){Intent intent1 = new Intent();Operation operation = new Intent.OperationBuilder().withDeviceId("").withBundleName("com.example.serviceability").withAbilityName(ForegroundServiceAbility.class.getName()).build();intent1.setOperation(operation);startAbility(intent1);}public void StopForegoundService(){Intent intent1 = new Intent();Operation operation = new Intent.OperationBuilder().withDeviceId("").withBundleName("com.example.serviceability").withAbilityName(ForegroundServiceAbility.class.getName()).build();intent1.setOperation(operation);stopAbility(intent1);}
}

 

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【研发日记】,Matlab/Simulink开箱报告(十)——Requirements Toolbox

前言 见《开箱报告&#xff0c;Simulink Toolbox库模块使用指南&#xff08;五&#xff09;——S-Fuction模块(C MEX S-Function)》 见《开箱报告&#xff0c;Simulink Toolbox库模块使用指南&#xff08;六&#xff09;——S-Fuction模块&#xff08;TLC&#xff09;》 见《开…

Python学习:注释和运算符

python 注释 在Python中&#xff0c;注释用于在代码中添加解释、说明或者提醒&#xff0c;但并不会被解释器执行。Python中的注释以#开头&#xff0c;直到行末为止。下面是关于Python注释的详细解释和举例&#xff1a; 单行注释&#xff1a;使用#符号在行的开头添加注释&…

Vue3:标签的ref属性用法

一、情景说明 我们在写前端页面的时候&#xff0c;肯定会遇到获取DOM内容的情况。 以往&#xff0c;我们是用原生的js方法去获取&#xff0c;如document.getXxxx 但是&#xff0c;这中方法会有个问题&#xff0c;如果父组件和子组件的id相同&#xff0c;则会出错。 在Vue3中&…

酷开科技聚焦大屏端数据研究,构建酷开系统深度挖掘大屏商业价值

中国所有的彩色大屏中&#xff0c;智能电视规模已经过半&#xff0c;OTT平台的数据价值越发引起人们关注。作为OTT行业的头部代表&#xff0c;酷开科技一直聚焦大屏端数据研究&#xff0c;目前已经形成一套基于大屏指数的智慧营销体系&#xff0c;让OTT大屏的数字营销化水平实现…

安装MySQL5.7.19 + 解决数据库乱码

文章目录 1.删除mysql服务 sc delete mysql2.解压到D:\mysql5.7下3.配置管理员环境变量4.D:\mysql5.7\mysql-5.7.19-winx64下创建my.ini1.创建文件2.文件内容 5.管理员打开cmd&#xff0c;切换到 D:\mysql5.7\mysql-5.7.19-winx64\bin6.输入 mysqld -install 安装mysql服务7.初…

2 使用GPU理解并行计算

2.1 简介 本章旨在对并行程序设计的基本概念及其与GPU技术的联系做一个宽泛的介绍。本章主要面向具有串行程序设计经验&#xff0c;但对并行处理概念缺乏了解的读者。我们将用GPU的基本知识来讲解并行程序设计的基本概念。 2.2 传统的串行代码 绝大多数程序员是在串行程序占据…

数学建模-邢台学院

文章目录 1、随机抽取的号码在总体的排序2、两端间隔对称模型 1、随机抽取的号码在总体的排序 10个号码从小到大重新排列 [ x 0 , x ] [x_0, x] [x0​,x] 区间内全部整数值 ~ 总体 x 1 , x 2 , … , x 10 总体的一个样本 x_1, x_2, … , x_{10} ~ 总体的一个样本 x1​,x2​,……

《圣斗士星矢》AI制作CG大电影欣赏

《圣斗士星矢》AI制作CG大电影欣赏 In the darkest corners of the universe, legends are born. 宇宙最幽暗的角落&#xff0c;传奇应运而生。 The gods of Olympus descend, bringing chaos and terror. 奥林匹斯众神降临&#xff0c;带来混乱与恐怖。 The armor of the Sain…

Java基础学习笔记二

Java的加载与执行 Java既是编译型语言又是解释型语言 question&#xff1a;为什么JVM可以跨平台执行 answer &#xff1a; Java虚拟机&#xff08;JVM&#xff09;之所以能够跨平台执行&#xff0c;是因为它在不同操作系统上提供了一个统一的运行环境&#xff0c;实现了Java程…

Spring Boot+Vue前后端分离项目如何部署到服务器

&#x1f31f; 前言 欢迎来到我的技术小宇宙&#xff01;&#x1f30c; 这里不仅是我记录技术点滴的后花园&#xff0c;也是我分享学习心得和项目经验的乐园。&#x1f4da; 无论你是技术小白还是资深大牛&#xff0c;这里总有一些内容能触动你的好奇心。&#x1f50d; &#x…

19.WEB渗透测试--抓包技术(下)

免责声明&#xff1a;内容仅供学习参考&#xff0c;请合法利用知识&#xff0c;禁止进行违法犯罪活动&#xff01; 内容参考于&#xff1a; 易锦网校会员专享课 上一个内容&#xff1a;18.WEB渗透测试--抓包技术&#xff08;上&#xff09;-CSDN博客 Burp含义和内容参考&…

《算法王晓东》多处最优服务次序问题

多处最优服务次序问题 题目描述 设有n个顾客同时等待一项服务。顾客i需要的服务时间为ti, 1≤i≤n。共有s处可以提供此项服务。应如何安排n个顾客的服务次序才能使平均等待时间达到最小? 平均等待时间是n个顾客等待服务时间的总和除以n。 算法设计&#xff1a;对于给定的n个顾…

jvm的垃圾回收器以及触发full gc的场景

JVM&#xff08;Java虚拟机&#xff09;的垃圾回收器有很多种&#xff0c;主要包括以下几种&#xff1a; Serial收集器&#xff1a;串行收集器是最古老、最稳定的收集器。它使用单个线程进行垃圾收集工作&#xff0c;在进行垃圾回收时会暂停所有用户线程。 ParNew收集器&#…

使用STM32 再实现电动车防盗

项目需求 点击遥控器 A 按键&#xff0c;系统进入警戒模式&#xff0c;一旦检测到震动&#xff08;小偷偷车&#xff09;&#xff0c;则喇叭发出声响报警&#xff0c; 吓退小偷。 点击遥控器 B 按键&#xff0c;系统退出警戒模式&#xff0c;再怎么摇晃系统都不会报警&…

SQLiteC/C++接口详细介绍之sqlite3类(十二)

返回目录&#xff1a;SQLite—免费开源数据库系列文章目录 上一篇&#xff1a;SQLiteC/C接口详细介绍之sqlite3类&#xff08;十一&#xff09; 下一篇&#xff1a;SQLiteC/C接口详细介绍之sqlite3类&#xff08;十三&#xff09; ​37.sqlite3_load_extension 用于在SQLit…

MyBatis核心配置文件:解锁数据之美的密码

MyBatis&#xff0c;这位编程的诗人&#xff0c;通过其独特的核心配置文件&#xff0c;为我们描绘出一幅数据之美的画卷。本篇博客将带你深入探讨MyBatis核心配置文件的奥秘&#xff0c;让你能够更好地理解和运用这个优雅的数据持久化框架。 最近想搞私域&#xff0c;欢迎各位…

Docker与containerd:容器技术的双璧

&#x1f407;明明跟你说过&#xff1a;个人主页 &#x1f3c5;个人专栏&#xff1a;《Docker幻想曲&#xff1a;从零开始&#xff0c;征服容器宇宙》 &#x1f3c5; &#x1f516;行路有良友&#xff0c;便是天堂&#x1f516; 目录 一、前言 1、Docker和containerd的背景…

PyTorch 深度学习(GPT 重译)(五)

十二、通过指标和增强改进训练 本章涵盖 定义和计算精确率、召回率以及真/假阳性/阴性 使用 F1 分数与其他质量指标 平衡和增强数据以减少过拟合 使用 TensorBoard 绘制质量指标图 上一章的结束让我们陷入了困境。虽然我们能够将深度学习项目的机制放置好&#xff0c;但实…

Hive SQL必刷练习题:日期交叉问题(两种思路)

思路一&#xff1a; ​ 首先想到的是借助炸裂函数&#xff0c;一行变成多行&#xff0c;就可以进行去重操作&#xff0c;然后再统计日期。 用到炸裂函数&#xff0c;就首先需要可以拿到起始和终止日期差大小的数组&#xff0c;然后再炸裂​ 那这个指定长度数组怎么获取呢&…

sentry-cli - error: Failed to load .sentryclirc file from project path

Xcode 15.2 warning sentry-cli - error: Failed to load .sentryclirc file from project path (/Users/zhuhongwei/Desktop/pandabill/.sentryclirc)推荐一下刚上线的 App 熊猫小账本&#xff0c;里面有用到这篇博客讲的内容 熊猫小账本 一个简洁的记账 App&#xff0c;用于…