安卓应用之服务
服务
服务也是四大组件之一,用于执行长时间运行操作的组件,它与用户界面(UI)是分开的,因此即使用户切换到其他应用,服务依然可以继续运行。主要用于处理一些不需要用户交互的任务。例如,播放音乐、下载文件、处理网络请求等。服务可以在整个应用生命周期中运行,直到被显式停止或应用进程被终止。
服务的3种类型
Service 可以分为三种类型:前台服务(Foreground Service)、后台启动式服务(Background Service)和绑定服务(Bound Service)。每种服务有其特定的使用场景和生命周期管理方式:
- 绑定式服务:允许Activity组件与服务进行交互,如果Service需要和Activity频繁交互数据,那可以使用这种。
- 前台服务:适用于需要用户可见且长时间运行的任务,必须显示通知。常见的后台采集步数信息、音乐播放就是前台服务+通知栏的形式。
- 启动式服务:适用于在后台运行的任务,用户不需要感知。但在8.0以上的系统,受到更严格的系统限制,内存不足的时候更有可能先被系统干掉。所以后台服务酌情使用。
startService——启动式服务
当应用组件(如 Activity)通过 startService() 方法启动一个服务时,就创建了一个启动服务。这种服务可以在后台无限期地运行,即使启动它的组件被销毁了,它仍然可以继续工作。但这不太符合系统高版本(安卓8.0以上)的策略,所以不建议优先考虑使用。
启动式服务的生命周期
- onCreate():服务第一次创建时调用,用于进行一些初始化操作。
- onStartCommand():每次通过 startService() 方法启动服务时调用。这个方法可以接收从启动组件传递过来的意图(Intent),根据意图中的信息来执行相应的操作。
- onDestroy():服务被停止时调用,用于释放资源。
启动式服务使用
- 创建服务类
public class MyService extends Service { private static final String TAG = "MyService"; private MediaPlayer mediaPlayer; @Override public void onCreate() { super.onCreate(); Log.i(TAG, "onCreate: 服务第一次创建"); mediaPlayer = MediaPlayer.create(this, R.raw.qlx); mediaPlayer.setLooping(true); } @Override public int onStartCommand(Intent intent, int flags, int startId) { //这里的intent指的是启动服务时的意图,可以用来传值 int cmd = intent.getIntExtra("key_data", 0); Log.i(TAG, "onStartCommand: 每次通过 startService() 方法启动服务时调用。"); if (!mediaPlayer.isPlaying()) { mediaPlayer.start(); } //这里的START_STICKY,指的是:执行完onStartCommand之后,如果被系统杀死,让系统在合适的时机,尝试重新创建服务并调用onStartCommand方法 //但在安卓8.0后,使用startService启动的服务,会受到严格的限制 return START_STICKY; } @Override public void onDestroy() { Log.i(TAG, "onDestroy: "); super.onDestroy(); if (mediaPlayer != null && mediaPlayer.isPlaying()) { mediaPlayer.stop(); mediaPlayer.release(); } } //onBind方法,一般不会在startService的时候被触发 @Override public IBinder onBind(Intent intent) { Log.i(TAG, "onBind: "); return null; } }
- 在清单文件中声明服务
<service android:name=".serv.MyService" android:enabled="true" android:exported="true"></service>
- 在其他组件启动服务、停止服务
findViewById(R.id.btn_start).setOnClickListener(view ->{ Intent intent = new Intent(this, MyService.class); intent.putExtra("key_data",101); startService(intent);//使用意图启动服务 }); findViewById(R.id.btn_stop).setOnClickListener(view ->{ Intent intent = new Intent(this, MyService.class); stopService(intent);//停止服务 });
前台服务
前台服务用于执行用户可察觉的操作。前台服务显示状态栏通知,让用户知道应用正在前台执行任务并消耗系统资源,比如常见的音视频播放、健身APP后台获取数据。
清单中声明服务
服务属于组件之一,需要在清单中声明组件,并且需要指定服务类型。
<service android:name=".MyMediaPlaybackService" android:foregroundServiceType="mediaPlayback" android:exported="false"> </service>
高版本的系统中不添加服务类型,会提示异常。另外,如果服务中有多个功能类型,可以使用 | 将其分隔开运算符。例如,使用摄像头和麦克风的服务 会进行如下声明:
android:foregroundServiceType="camera|microphone"
添加前台服务权限
如果在高版本的Android系统中不添加前台服务权限,会提示异常。
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/> <uses-permission android:name="android.permission.FOREGROUND_SERVICE_CAMERA"/>
除此之外,与前台服务搭配使用的功能,有可能也需要对权限做出声明,例如: 尝试启动 location 类型的前台服务,获取定位信息。系统会检查应用已有ACCESS_COARSE_LOCATION 或 ACCESS_FINE_LOCATION 权限,否则也会提示异常。
创建服务
public class MyForegroundService extends Service { //指的是某一条通知的id private static final int NOTIFICATION_ID = 1; //指的是通知的通道(一般会根据通知的类型划分不同的通道,比如日常消息、营销信息、系统通知等等) private static final String CHANNEL_ID = "MyServiceChannel"; @Override public void onCreate() { super.onCreate(); //这里可以初始化一些操作 比如音乐播放... // 创建通知通道 createNotificationChannel(); } @Override public int onStartCommand(Intent intent, int flags, int startId) { // 启动前台服务 startForeground(NOTIFICATION_ID, getNotification()); // 执行长时间运行的任务 new Thread(new Runnable() { @Override public void run() { // 在这里执行耗时操作,例如下载文件、播放音乐等 // ... } }).start(); return START_STICKY; } @Override public IBinder onBind(Intent intent) { return null; // 不需要绑定 } @Override public void onDestroy() { super.onDestroy(); // 清理资源 } private void createNotificationChannel() { //安卓8.0以上可以用这种形式创建通知通道 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { NotificationChannel serviceChannel = new NotificationChannel( CHANNEL_ID, "Foreground Service Channel", NotificationManager.IMPORTANCE_DEFAULT ); NotificationManager manager = getSystemService(NotificationManager.class); if (manager != null) { manager.createNotificationChannel(serviceChannel); } } } private Notification getNotification() { return new NotificationCompat.Builder(this, CHANNEL_ID) .setContentTitle("Service Running") .setContentText("Your service is running in the foreground") .setSmallIcon(R.drawable.ic_service) .build(); } }
启动前台服务
在需要使用服务的地方启动:
//启动服务 Intentservice Intent=newIntent(this, MyMediaPlaybackService.class); context.startForegroundService(intent);
停止服务
使用完毕的时候停止:
IntentserviceIntent=newIntent(this, MyForegroundService.class); stopService(serviceIntent);
前台服务的生命周期
- onCreate()
-
- 当服务首次创建时调用。此方法是服务生命周期的起点。
- 在这里,可以执行一次性的初始化操作,例如前台服务经常会和通知栏代码一起使用,所以可以在这里设置通知通道。
@Override public void onCreate() { super.onCreate(); // 创建通知通道等初始化操作 }
- onStartCommand(Intent intent, int flags, int startId)
-
- 当服务被启动时调用,可以多次调用。每次调用都会传入一个 Intent,可以用于处理启动服务的请求。
- 在这里,你需要调用 startForeground() 方法以将服务提升为前台服务并显示通知。
- 返回值指示系统该如何处理服务被杀死的情况。常用的返回值有:
- START_STICKY:服务在被杀死后会尝试重启,但不会重新传入原始的 Intent。
- START_NOT_STICKY:服务被杀死后不会重启。
- START_REDELIVER_INTENT:服务被杀死后会重启,并将最后传入的 Intent 重新传入。
@Override public int onStartCommand(Intent intent, int flags, int startId) { startForeground(NOTIFICATION_ID, getNotification()); // 执行长时间运行的任务 return START_STICKY; }
- onBind(Intent intent)
-
- 当组件(如 Activity)调用 bindService() 方法时调用。如果服务不提供绑定功能,可以返回 null。
@Override public IBinder onBind(Intent intent) { return null; // 这里返回null表示不支持绑定 }
- onRebind(Intent intent)
-
- 当已有的连接到服务的客户端调用 bindService() 时,系统会调用此方法。如果 onBind() 返回非 null 的 IBinder,则会调用此方法。
@Override public void onRebind(Intent intent) { super.onRebind(intent); // 处理重新绑定逻辑 }
- onUnbind(Intent intent)
-
- 当所有客户端都解除绑定时调用。返回值决定了是否会调用 onRebind() 方法。
@Override public boolean onUnbind(Intent intent) { // 处理解绑逻辑 return false; // 返回true将会调用onRebind }
- onDestroy()
-
- 当服务被停止时调用。此方法用于清理资源和释放服务占用的内存。
@Override public void onDestroy() { super.onDestroy(); // 清理一些资源 }
绑定服务
绑定服务是客户端-服务器接口中的服务器。比如将 activity 绑定到服务。所以,适用于需要与应用的其他组件(如 Activity 或 Fragment)进行交互的任务。另外,绑定服务不会无限期在后台运行,而是受到绑定组件的影响。
- 创建服务类
这里以音乐播放为案例。演示绑定服务和Activity的UI是如何密切交互的。首先,我们需要创建一个 Service 子类。
// MusicService.java public class MusicService extends Service { //音乐控制实例 private MediaPlayer mediaPlayer; //本地绑定对象 private final IBinder binder = new LocalBinder(); public class LocalBinder extends Binder { MusicService getService() { return MusicService.this; } } @Override public void onCreate() { super.onCreate(); mediaPlayer = MediaPlayer.create(this, R.raw.sample_music); // 假设有一段音乐在 res/raw 目录 } @Nullable @Override public IBinder onBind(Intent intent) { return binder; // 返回本地绑定对象 } public void playMusic() { if (!mediaPlayer.isPlaying()) { mediaPlayer.start(); } } public void pauseMusic() { if (mediaPlayer.isPlaying()) { mediaPlayer.pause(); } } public void stopMusic() { if (mediaPlayer.isPlaying()) { mediaPlayer.stop(); mediaPlayer.prepareAsync(); // 准备下一次播放 } } @Override public void onDestroy() { super.onDestroy(); if (mediaPlayer != null) { mediaPlayer.release(); mediaPlayer = null; } } }
- 在 AndroidManifest.xml 中注册服务
<service android:name=".MusicService" />
- 在 Activity 中绑定服务
接下来,在你的 Activity 中绑定 MusicService,以便可以通过它控制音乐的播放。
// MainActivity.java public class MainActivity extends AppCompatActivity { private MusicService musicService; private boolean isBound = false; //通过connection获取服务的实例,并且调用服务中的播放控制 private ServiceConnection connection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { MusicService.LocalBinder binder = (MusicService.LocalBinder) service; musicService = binder.getService(); // 获取服务实例 isBound = true; } @Override public void onServiceDisconnected(ComponentName name) { isBound = false; // 服务意外断开 } }; @Override protected void onStart() { super.onStart(); Intent intent = new Intent(this, MusicService.class); bindService(intent, connection, Context.BIND_AUTO_CREATE); // 绑定服务 } @Override protected void onStop() { super.onStop(); if (isBound) { unbindService(connection); // 解绑服务 isBound = false; } } public void onPlayButtonClick(View view) { if (isBound) { musicService.playMusic(); // 调用服务中的播放方法 } } public void onPauseButtonClick(View view) { if (isBound) { musicService.pauseMusic(); // 调用服务中的暂停方法 } } public void onStopButtonClick(View view) { if (isBound) { musicService.stopMusic(); // 调用服务中的停止方法 } } }
两种服务的区别
生命周期
- 绑定服务的生命周期:
- onCreate(): 当服务首次被创建时调用。
- onBind(): 客户端通过 bindService() 绑定服务时调用。
- onUnbind(): 当所有客户端都解除绑定时调用。
- onRebind(): 当新的客户端绑定到已经解绑的服务时调用。
- onDestroy(): 当服务被销毁时调用。
- 前台服务的生命周期:
- onCreate(): 服务被创建时调用。
- onStartCommand(): 服务被启动时调用,通常是通过 startService()。
- onBind(): 绑定服务的调用(可选)。
- onDestroy(): 服务被销毁时调用。
启动和绑定方式
- 前台服务:
-
- 通过 startService(Intent) 启动。
- 运行在前台,显示持续的通知,通常用于执行长时间运行的任务。
- 不依赖于其他组件的绑定,可以独立存在。
- 绑定服务:
- 通过 bindService(Intent, ServiceConnection, int) 绑定。
- 可以在多个组件间共享,并通过 IBinder 与绑定的组件进行通信。
- 其生命周期与绑定的组件密切相关,当没有绑定的组件时,服务可以被销毁。
3. 使用场景的区别
- 前台服务:
- 适用于需要用户注意的长时间运行任务,比如音乐播放、下载任务等。它必须在前台运行,并且具有持续的通知,以提高用户体验。
- 绑定服务:
- 适用于需要与应用的其他组件(如 Activity 或 Fragment)进行交互的任务,如数据共享或任务协调。它不一定需要在前台运行,服务的存在与否取决于是否有组件绑定。
服务与线程如何选择?
选择服务还是线程主要取决于任务的性质、需求和资源管理的考虑。对于需要长时间在后台执行的任务,推荐使用服务;而对于短期任务或与用户交互密切的操作,则使用线程更为合适。
相关文章:
安卓应用之服务
服务 服务也是四大组件之一,用于执行长时间运行操作的组件,它与用户界面(UI)是分开的,因此即使用户切换到其他应用,服务依然可以继续运行。主要用于处理一些不需要用户交互的任务。例如,播放音…...
【Vue CLI脚手架开发】——6.scoped样式
文章目录 一、scoped是什么二、应用案例1.使用代码2.原理3父组件App未添加scoped影响 一、scoped是什么 我们知道vue为了防止css样式污染,在每个组件中提供了 scoped属性进行限定css作用域;当<style>标签有 scoped 属性时,它的 CSS 只…...
JVM参数调整
一、内存相关参数 1. 堆内存控制 -Xmx:最大堆内存(如 -Xmx4g,默认物理内存1/4)。-Xms:初始堆内存(建议与-Xmx相等,避免动态扩容带来的性能波动)。-Xmn:新生代大小&…...
NodeJS学习笔记
NodeJS软件安装 node环境安装: https://nodejs.org 安装好后的node通常在C:\Program Files\nodejs验证安装是否成功 node -v npm -v 进入REPL模式命令行模式 nodeNodeJS在REPL模式和编辑器使用 windos在dos下常用命令 windos命令: 1、cmd dos系统2、…...
缺陷管理工具-禅道
目录 一、禅道的介绍 二、禅道的特点 三、禅道使用流程 1.管理缺陷 2.管理用例 黑马测试视频学习记录 一、禅道的介绍 二、禅道的特点 三、禅道使用流程 1.管理缺陷 2.管理用例...
C++ 单词识别_牛客题霸_牛客网
点击链接即可查看题目: 单词识别_牛客题霸_牛客网 一、题目 描述 输入一个英文句子,把句子中的单词(不区分大小写)按出现次数按从多到少把单词和次数在屏幕上输出来,次数一样的按照单词小写的字典序排序输出,要求能识别英文单词和句号。 输入…...
qt open3dAlpha重建
qt open3dAlpha重建 效果展示二、流程三、代码效果展示 二、流程 创建动作,链接到槽函数,并把动作放置菜单栏 参照前文 三、代码 1、槽函数实现 void on_actionAlpha_triggered();//alpha重建 void MainWindow::...
PS内发光、外发光
内外发光(图层样式–》内发光、外发光):(滤色 效果最好) 内发光–》结构:内发光的外形 内发光–》图素:渐变发光细节的调整 内发光–》品质:增加质感 内发光–》图素–》阻塞&#x…...
C++之thread_local变量
C之thread_local变量_c threadlocal-CSDN博客 thread_local简介 thread_local 是 C11 为线程安全引进的变量声明符。表示对象的生命周期属于线程存储期。 线程局部存储(Thread Local Storage,TLS)是一种存储期(storage duration),对象的存储是在…...
鸿蒙开发中,数据持久化之Transaction(事务)的概念及应用
SQLite 数据库具备事务处理能力。 事务本质上是一组操作的集合,它具有原子性,意味着这一系列操作要么全部成功执行,要么全部失败,不存在部分操作成功而部分失败的中间状态。 以常见的转账功能为例,A 账户向 B 账户转账…...
软考高项笔记 1.1.1 信息
1.1.1 信息 📚 信息(Information) 是物质、能量及其属性的标示的集合,是确定性的增加。它以物质介质为载体,传递和反映世界各种事物存在方式、运动状态等的表征。信息不是物质,也不是能力,它以一种普遍形式,…...
【TCP/IP协议栈】计算机网络知识补充
参考资料: 前言 【计算机网络知识】 总结 IP 在互联网中MAC 在局域网中 1. IP地址 IP地址有两个版本,IPv4和IPv6。IPv6现在并没有普及使用,所以现在使用的地址大部分依然是IPv4。 IP地址是在IP协议中,用来标识网络中不同主机的…...
【C++进阶学习】第一讲——继承(下)---深入挖掘继承的奥秘
目录 1.隐藏 1.1隐藏的概念 1.2隐藏的两种方式 2.继承与友元 3、继承与静态成员 4.单继承和多继承 4.1单继承 4.2多继承 5.菱形继承 问题1:冗余性 问题2:二义性 6.虚拟继承 7.总结 1.隐藏 1.1隐藏的概念 在 C 中,继承是一种机制…...
IDEA Generate POJOs.groovy 踩坑小计 | 生成实体 |groovy报错
一、无法生成注释或生成的注释是null 问题可能的原因: 1.没有从表里提取注释信息,修改def calcFields(table)方法即可 def calcFields(table) {DasUtil.getColumns(table).reduce([]) { fields, col ->def spec Case.LOWER.apply(col.getDataType().…...
数据结构与算法 计算机组成 八股
文章目录 数据结构与算法数组与链表的区别堆的操作红黑树定义及其原理 计算机组成int和uint的表示原码反码补码移码的定义?为什么用补码? 数据结构与算法 数组与链表的区别 堆的操作 红黑树定义及其原理 计算机组成 int和uint的表示 原码反码补码移…...
【奇点时刻】通义千问开源QwQ-32B技术洞察报告(扫盲帖)
以下报告将基于今天各大社区对 Qwen/QwQ-32B(下文简称「QwQ-32B」)模型的讨论、测评与实测体验进行综合性分析与洞察。本报告将从模型背景与定位、核心技术、性能表现与对比、部署与使用方式,以及未来潜力与可能的影响五个维度,帮…...
神经网络中梯度计算求和公式求导问题
以下是公式一推导出公式二的过程。 表达式一 ∂ E ∂ w j k − 2 ( t k − o k ) ⋅ sigmoid ( ∑ j w j k ⋅ o j ) ⋅ ( 1 − sigmoid ( ∑ j w j k ⋅ o j ) ) ⋅ ∂ ∂ w j k ( ∑ j w j k ⋅ o j ) \frac{\partial E}{\partial w_{jk}} -2(t_k - o_k) \cdot \text{sigm…...
IDEA 2024.1.7 Java EE 无框架配置servlet
1、创建一个目录(文件夹)lib来放置我们的库 2、将tomcat目录下的lib文件夹中的servlet-api.jar文件复制到刚创建的lib文件夹下。 3、把刚才复制到lib下的servlet-api.jar添加为库 4、在src下新建一个package:com.demo,然后创…...
Three.js 快速入门教程【十四】使用Stats.js监控渲染帧率和性能优化
系列文章目录 Three.js 快速入门教程【一】开启你的 3D Web 开发之旅 Three.js 快速入门教程【二】透视投影相机 Three.js 快速入门教程【三】渲染器 Three.js 快速入门教程【四】三维坐标系 Three.js 快速入门教程【五】动画渲染循环 Three.js 快速入门教程【六】相机控件 Or…...
基于RapidOCR与DeepSeek的智能表格转换技术实践
基于RapidOCR与DeepSeek的智能表格转换技术实践 一、技术背景与需求场景 在金融分析、数据报表处理等领域,存在大量图片格式的表格数据需要结构化处理。本文介绍基于开源RapidOCR表格识别与DeepSeek大模型的智能转换方案,实现以下典型场景: …...
简单多状态 dp 问题(典型算法思想)—— OJ例题算法解析思路
目录 一、面试题 17.16. 按摩师 - 力扣(LeetCode) 算法代码: 代码思路解析: 问题分析: 动态规划定义: 状态转移方程: 初始化: 填表: 返回值: 优化空…...
【电路笔记 TMS320C6***DSP】外部存储器接口 A EMIFA向FPGA(作为异步存储器)写入数据的示例
目录 DSP和FPGA的连接DSP端:传输数据给FPGAFPGA端:接收数据 EMIFA(External Memory Interface A)的“异步存储器”(Asynchronous Memory)指的是那些不与系统时钟同步进行读写操作的外部存储设备。这类存储器…...
pgsql 查看数据库、表、索引大小等
查询数据库大小 -- 查询单个数据库大小 select pg_size_pretty(pg_database_size(postgres)) as size;-- 查询所有数据库大小 select datname, pg_size_pretty (pg_database_size(datname)) AS size from pg_database; 查询表大小 -- 查询单个表大小 select pg_size_pretty(p…...
物联网感知层采集的数据 经过etl 后 ,输送给ai 训练模型 和模型本身调优
在物联网(IoT)系统中,感知层采集的数据经过 ETL(Extract, Transform, Load) 处理后,可以作为 AI 模型的训练数据,用于模型训练和调优。以下是实现这一过程的详细步骤和技术方案: 一、数据流程概述 数据采集:通过传感器和物联网设备采集原始数据。ETL 处理:对原始数据…...
C语言基础
一、基础 C语言文件 后缀 .c为源文件 .h为头文件 以 Visual studio 为例右键点击源文件点击添加,新建项 .c为C语言文件,.cpp为C文件 后缀不同编译器会按照不同的编译语法进行编译 .cpp以C语法 第一个程序 #include <stdio.h> //包含 st…...
pinginfoview网络诊断工具中文版
介绍 pinginfoview中文版本是一款实用的网络诊断工具,它专为中文用户设计,提供了方便易用的界面,使得在Windows环境下进行ping测试变得更加简单。该工具是由NirSoft开发的一款免费的桌面应用程序,尽管官方可能并未正式发布中文版…...
Anyting LLM LLM温度设置范围
在Anything LLM中,LLM(Language Model)的温度设置是一个关键参数,它影响着模型生成文本时的随机性和确定性。关于Anything LLM的LLM温度设置范围,虽然没有官方的明确数值范围说明,但通常温度参数的设置遵循…...
鸿蒙Android4个脚有脚线
效果 min:number122max:number150Row(){Stack(){// 底Text().border({width:2,color:$r(app.color.yellow)}).height(this.max).aspectRatio(1)// 长Text().backgroundColor($r(app.color.white)).height(this.max).width(this.min)// 宽Text().backgroundColor($r(app.color.w…...
RecyclerView与ListView的优化
RecyclerView与ListView的优化 一、基础概念对比 1.1 ListView与RecyclerView概述 ListView和RecyclerView都是Android中用于展示列表数据的重要控件,但RecyclerView是更现代化的解决方案,提供了更多的灵活性和性能优势。 ListView特点 Android早期…...
【人工智能】GPT-4 vs DeepSeek-R1:谁主导了2025年的AI技术竞争?
前言 2025年,人工智能技术将迎来更加激烈的竞争。随着OpenAI的GPT-4和中国初创公司DeepSeek的DeepSeek-R1在全球范围内崭露头角,AI技术的竞争格局开始发生变化。这篇文章将详细对比这两款AI模型,从技术背景、应用领域、性能、成本效益等多个方…...
2025年Cursor最新安装使用教程
Cursor安装教程 一、Cursor下载二、Cursor安装三、Cursor编辑器快捷键(1) 基础编辑快捷键(2) 导航快捷键(3) 其他常用快捷键 一、Cursor下载 Cursor官方网站(https://www.cursor.com/ ) 根据自己电脑操作系统选择对应安装包 二、Cursor安装 下载完成后…...
原码、反码和补码的介绍和区别
在计算机中,有符号整数的表示方法主要有 原码、反码和补码,它们解决了二进制数表示正负数及简化运算的问题。以下是分步说明: 1. 原码(Sign-Magnitude) 定义:最高位为符号位(0正1负)…...
STM32 进阶 定时器
在stm32中定时器大概分为4类 1、系统定时器:属于arm内核,内嵌在NVIC中 2、高级定时器:可以用来刹车和死区 3、通用定时器:可以用来输出pwm方波 4、基本定时器:只能记数 系统定时器注意: 1、系统定时器…...
山东大学:《DeepSeek应用与部署》
大家好,我是吾鳴。 今天吾鳴要给大家分享一份由山东大学出版的DeepSeek报告——《DeepSeek应用与部署》,这份报告讲述了AIGC的发展历程,DeepSeek应用场景和DeepSeek如何本地化部署。报告一共80页PPT,文末有完整版下载地址。 内容摘…...
【无标题】FrmImport
文章目录 前言一、问题描述二、解决方案三、软件开发(源码)四、项目展示五、资源链接 前言 我能抽象出整个世界,但是我不能抽象你。 想让你成为私有常量,这样外部函数就无法访问你。 又想让你成为全局常量,这样在我的…...
Android14 OTA升级
因Vendor Freeze的缘故,若开启Non-AB OTA, 则会遇到交叉编译vendor和system的增量升级包时需要检查fingerprint而导致编译失败,从而无法做到增量升级包升级。高版本一般都是打开AB模式。 AB 和 non AB 切换相关宏 /vendor_ap_s0/device/mediatek/system/mssi_64_cn/SystemCo…...
监听 RabbitMQ 延时交换机的消息数、OpenFeign 路径参数传入斜杠无法正确转义
背景 【MQ】一套为海量消息和高并发热点消息,提供高可用精准延时服务的解决方案 我现在有一个需求,就是监听 RabbitMQ 一个延时交换机的消息数,而 RabbitTemplate 是不存在对应的方法来获取的。 而我们在 RabbitMQ 的控制台却可以发现延时交…...
宇树科技嵌入式面试题及参考答案(春晚机器人的公司)
目录 设计一个带看门狗(Watchdog)的嵌入式系统,描述故障恢复流程 在资源受限的 MCU 上实现 OTA 升级功能,描述关键设计点 如何实现 OTA(空中升级)功能?描述固件校验和回滚机制的设计要点 推挽输出与开漏输出的区别?举例说明其在 GPIO 控制中的应用 UART、SPI、I2C …...
Linux内核自定义协议族开发指南:理解net_device_ops、proto_ops与net_proto_family
在Linux内核中开发自定义协议族需要深入理解网络协议栈的分层模型。net_device_ops、proto_ops和net_proto_family是三个关键结构体,分别作用于不同的层次。本文将详细解析它们的作用、交互关系及实现方法,并提供一个完整的开发框架。 一、核心结构体的作用与层级关系 struct…...
【Go语言快速上手】第一部分:数据类型(数组、切片、映射)与控制语句
文章目录 一、复合类型Ⅰ 数组1. 语法2. 示例3. 特点4. 数组的传递 Ⅱ 切片1. 定义2. 语法3. 示例4. 特点5. 切片的创建6. 切片的操作切片的扩展切片的拷贝 Ⅲ 映射1. 定义2. 语法3. 示例4. 特点5. 映射的创建6. 映射的操作示例:插入、访问和删除判断键是否存在示例…...
系统架构评估中的重要概念
(1)敏感点(Sensitivity Point) 和权衡点 (Tradeoff Point)。敏感点和权衡点是关键的架构 决策。敏感点是一个或多个构件(和/或构件之间的关系)的特性。研究敏感点可使设计人员 或分析员明确在搞清楚如何实现质量目标时应注意什么。权衡点是影响多个质量属性的特性, …...
shell逐行读取文件 远程操作服务器
代码示例 while read ip; doecho "uninstalling test programs in $line" ssh root$ip bash -s < remote_remove_tool.shdone < installed_ips总结 ✅ 作用: 逐行读取 installed_ips 文件中的 IP 地址通过 SSH 连接到远程服务器ÿ…...
盛铂科技SCP4000射频微波功率计与SPP5000系列脉冲峰值 USB功率计 区别
在射频(RF)和微波测试领域,快速、精准的功率测量是确保通信系统、雷达、卫星设备等高性能运行的核心需求。无论是连续波(CW)信号的稳定性测试,还是脉冲信号的瞬态功率分析,工程师都需要轻量化、…...
【每日八股】计算机网络篇(三):IP
目录 DNS 查询服务器的基本流程DNS 采用 TCP 还是 UDP,为什么?默认使用 UDP 的原因需要使用 TCP 的场景?总结 DNS 劫持是什么?解决办法?浏览器输入一个 URL 到显示器显示的过程?URL 解析TCP 连接HTTP 请求页…...
vtk 3D坐标标尺应用 3D 刻度尺
2d刻度尺 : vtk 2D 刻度尺 2D 比例尺-CSDN博客 简介: 3D 刻度尺,也是常用功能,功能强大 3D 刻度尺 CubeAxesActor vtkCubeAxes调整坐标轴的刻度、原点和显示效果,包括关闭小标尺、固定坐标轴原点,以及设置FlyMode模…...
探秘基带算法:从原理到5G时代的通信变革【十】基带算法应用与对比
文章目录 三、算法在现代通信系统中的应用3.1 5G 通信中的应用3.1.1 信道编码与调制解调3.1.2 大规模 MIMO 技术3.1.3 案例分析:5G 基站与终端实现 3.2 卫星通信中的应用3.2.1 抗干扰与纠错编码3.2.2 信号处理与调制解调3.2.3 案例分析:卫星通信系统实例…...
消费级、工业级、汽车级、军工级、航天级芯片区别对比
汽车电子行业,经常会由于降本原因,听到“消规、工规、车规”方面的讨论。常见的芯片等级一般是按照使用温度、辐射、抗干扰等来分级。等级分为以下5类: 民用级(消费级)、工业级、汽车级(车规级)、军工级、航…...
迷你世界脚本背包接口:Backpack
背包接口:Backpack 彼得兔 更新时间: 2023-10-25 10:29:21 具体函数名及描述如下: 序号 函数名 函数描述 1 getBackpackBarIDRange(...) 获取道具背包栏ID范围(起始ID~结束ID) 2 getBackpackBarSize(...) 获取道具背包栏大小 3 setGridItem(.…...
javaSE基础
java跨平台性: Java 语言编写的程序,一次编译后,可以在多个操作系统上运行。是由于其增加了一个中间件 JVM,JVM 负责将 Java 字节码转换为特定平台的机器码,并执行。 Java 程序从源代码到运行需要经过三步:…...
电脑的系统版本是windows7的,下载pycharm的哪个版本比较好呢?
李升伟 整理 在Windows 7系统上选择PyCharm版本时,需综合考虑系统兼容性、Python版本适配性以及开发需求。以下是具体建议和操作指南: 1. 选择PyCharm的兼容版本 推荐版本:PyCharm 2020.3.5及之前的旧版本。 原因:自2021年起&a…...