一文了解 Android Auto 车载开发~

news2024/11/29 12:35:09

作者:牛蛙点点申请出战

背景

我的的产品作为一个海外音乐播放器,在车载场景听歌是一个很普遍的需求。在用户反馈中,也有很多用户提到希望能在车上播放音乐。同时车载音乐也可以作为提升用户消费时长一个抓手。

出海产品,主要服务于海外用户。不同于国内的 Android 车载系统,往往是定制的 ROM,国外的 Android 车载也是 Google 一家独大,主要可以分为 Android Auto、Automotive OS。Android Auto 可以理解为是一套将手机应用「投屏」在车载屏幕上的方案,和 iOS 的 CarPlay 类似。而 Automotive OS 则类似于国内的定制 ROM。如果要支持 Automotive OS,那我们可能要重头开发一个适配大屏的 mini 版 app,那样工作量很大。所以我们第一步先从支持 Android Auto 开始

准备知识

Android Auto 支持多种类型的应用,包括导航、媒体、消息应用等。音乐播放器属于媒体应用,因此下面给出的参考仅限于媒体应用。

Android Auto 的适配需要做提前了解做一些准备知识,具体如下:

  • 官方文档

    • 构建车载媒体应用
      教你明白 Android Auto 开发媒体应用的各种概念以及如何开发。这个网址的中文翻译可读性很差,建议直接看英文。另外,如果要开发的是导航类应用而不是媒体应用,那可以直接使用 androidX 的 Car Library
    • 测试 Android Automotive OS 应用
      教你如何使用车机模拟器(DHU)配合手机上的 Android Auto app 来测试 Auto 应用。但是文档里有个坑点,文档里默认你的手机是 Pxiel 系列,Pxiel 系列是自带 Android Auto app 的,但是国产手机基本都没有这个 app,需要自己去下载然后安装在手机上。可以去 这里下载。另外 Android Auto app 第一次启动的时候会安装好几个谷歌服务,华为手机因为 ban 掉了google,这一步在华为手机上会失败。所以华为手机没法用来测试 Android Auto。推荐尽量使用 Pixel 系列手机来测试,避免测试过程中遇到奇奇怪怪的问题。
  • 车载设备

    • 业务功能的测试,一般使用模拟器 DHU 就可以。但是在应用发布之前,我们肯定要在真实设备上充分测试。如果你有带 Android Auto 的真车的话,直接用真车测试就行。但是国内带 Android Auto 的车比较少,大概率是没有真车可供测试的。可以去闲鱼上单独购买一个车载主机(闲鱼搜索「187b主机」即可)。
    • 还有一个坑点,应用没有经过 google play store 分发的话,在真实车机设备上是不会显示的。这个问题官方文档没有明确提到,导致当时我们 debug 的时候莫名其妙的花了很久的时间。
    • 这里顺带提一下,谷歌分发渠道有四个,internal、closed testing、open testing、production,分别对应内部、内测、公测、产品。当然,我们不可能为了测试直接提 play store 的 production 渠道,用 internal 分发渠道用作真机测试就可以了。closed testing 和 open testing 渠道也可以。
  • 质量规范

    • developer.android.google.cn/docs/qualit…
      因为车载场景事关驾驶员生命安全,所以 google 对 Android Auto 应用审核很严格。所有支持 Android Auto 的应用,必须满足上面链接中的质量规范才可能通过 Play Store 的审核。这个规范要求的点很多,坑也不少,后面还会说到。这里面很重要的一点是必须支持语音搜索歌曲起播,这是审核强卡的一个点。
  • 官方 demo

    • 因为文档讲得很晦涩,照着文档大概率是依然很难上手开发的。可以参考 google 官方的音乐播放器 uamp,虽然这个 demo 很简单,但是它也支持 Android Auto,有不懂的开发细节都可以参考这个 demo。
  • Android Auto app(包名为 com.google.android.projection.gearhead

    • 想要把 android auto 连上车机跑起来,必须要在手机上安装 Android Auto app,在 这里 下载。大部分国内的 rom 是不带这个 app 的,要自己手动安装。pixel 系列手机是自带的,可以在设置中搜索到这个应用。

如何开发

基本概念

首先,Android Auto 是不支持自定义 UI 的,你的应用投屏到车机上,UI 展示已经在车机内部写死了,你能做的只是把数据传到车机上。所以支持 Auto 的应用在车机上看起来都差不多。Auto 只允许你在播控界面的自定义操作里添加自定义图标。

其次,整个车机的播放流程涉及到三个部分,播放器应用、android auto app、车机。

另外还有几个概念我们要了解

  • MediaBrowserService
    • 指的就是音乐播放器的 Service。在 Service 里通过覆写 onGetRootonLoadChildren 等方法对外提供车机所需要展示的数据。相当于「媒体生产者」,该生产者由你的 app 的提供。
  • MediaBrowser
    • 展示、消费你从上面的 MediaBrowserService 拿到的数据。手机上的 Android Auto app 内部包含了这个类。这个类会来主动 binds 上面提到的的 MediaBrowserService。相当于「媒体消费者」,就是 Android Auto app。
  • MediaSession
    • MediaSession 就是 app 和车机之间进行交互的桥梁。实际上 app 和车机不是直接连接进行通信。app 是和 Android Auto app 进行 IPC 通信,Android Auto 再和车机进行通信。MediaSession 本质上就是一个对 IPC 的封装。这个封装不仅能和车机通信,还可以和耳机线控等外部设备进行通信。这些外部设备共用一个 MediaSession。

  • MediaItem、MediaMetadata、MediaDescription
    • MediaItem 代表了车机屏幕上的一个媒体元素,比如某一个页面,一首歌,一张专辑等等,在这个类中对应的属性设置成什么,车机上屏幕上就显示什么。
    • MediaMetadata 代表 MediaItem 中各个属性对应的值,用来构造 MediaDescription。MediaItem 持有 MediaDescription 用以描述该媒体元素该如何在车机上展示。
  • BROWSABLE 和 PLAYABLE
    • 这个一个枚举标记,车机上每一个 MediaItem 要么是 BROWSABLE 的,要么是 PLAYABLE 的。
    • PLAYABLE 意味着该 MediaItem 可播,这样当你在车机屏幕上点击该 MediaItem 时,会直接进行播放。这种 MediaItem 一般是歌曲,可直接起播。
    • BROWSABLE 意味着该 MediaItem 是可浏览的,也就是说点击该 MediaItem 时,会加载一个新的媒体集合用于展示。比如专辑、歌单等,点击的时候会进入一个新的页面展示歌曲列表。

上面就是做 Android Auto 开发需要理解的基本的概念,可以理解为一套车机的框架,把手机和车机交互中的各个角色都定义好了。我们的工作就是在这套框架上开发我们的业务。

车机连接手机

  • 真车上和模拟器上都可以参考官方文档 developer.android.com/training/ca…
  • 或者可以下载这个压缩包,运行 main.py 即可。该脚本把上述文档里的操作步骤都集成进去了。
  • 连上以后,音乐自动会从车机上播放,像耳机连上手机之后音频自动从耳机播放一样。不需要额外在代码中设置。

检测连接

  • 这是 auto 开发中的一个坑点。以往有一个方法可以检测手机是否处在车载模式,但是该方法只对 android 12 以下的系统生效,android 12 上无效:
public static boolean isCarUiMode(Context c) {
UiModeManager uiModeManager = (UiModeManager) c.getSystemService(Context.UI_MODE_SERVICE);
    if (uiModeManager.getCurrentModeType() == Configuration.UI_MODE_TYPE_CAR) {
        LogHelper.d(TAG, "Running in Car mode");
        return true;
    } else {
        LogHelper.d(TAG, "Running on a non-Car mode");
        return false;
    }
}
  • 官方有一个新的 CarLibrary 「androidx.car.app:app」,这个库中使用 CarConnection 类来检测车机和手机的连接。
CarConnection(carContext).type.observe(this, ::onConnectionStateUpdated)

但是该方法只适合于 android 6-12 的系统,并且我们只想使用连接检测,导入整个库的话未免显得太笨重。

  • 基于上述 CarLibrary 「androidx.car.app:app」的方法,我们把核心代码抽出来即可。具体代码我在 stackoverflow 上贴出来作为一个回答,也被采纳了。对于 android 5 的系统,使用前述的 isCarUiMode 方法即可。

工作原理

如前面 MediaSession 的介绍所述,这个工作过程涉及到车机、android auto app、应用三方。为了叙述方便,后面提到的「车机回调客户端方法」实际上均是中介作用的 Android Auto App 通过 IPC 完成的。

下文中的 PlayerService 指的是应用中用于播放音乐的 Service。

整体的工作流程如下面的时序图所示,后面会逐一解释。

bindService
  • 当我们的车机和手机连接上之后,Android Auto app 就会主动地 bind 我们的 PlayerService。因此 Service 必须声明 android:exported="true" ,这样才可以被外部拉起。同时整个 app 进程也被拉起了。

页面树
  • 整个车机屏幕的 UI 可以看做一个页面树,客户端应用负责把定义各个页面树的节点 ID 和传输节点数据对应的 MediaItem。而车机在拿到这些数据以后就可以渲染屏幕 UI。
  • 车机通过 IPC 回调到客户端代码中的 onGetRoot() 方法和 onLoadChildren() 方法来获取页面 ID 和数据。接下来详细说下这两个方法。
  • 页面树的节点 ID 可以自己定义,只要保证每个节点对应唯一的 ID 即可。
  • 一般来说,叶子节点是 PLAYABLE 类型的 MediaItem,而非叶子节点对应 BROWSABLE 类型的 MediaItem。
onGetRoot()
override fun onGetRoot(
    clientPackageName: String,
    clientUid: Int,
    rootHints: Bundle?
): MediaBrowserServiceCompat.BrowserRoot
  • onGetRoot 是车机和手机交互的入口方法,只要车机和手机连接上了,就会回调这个方法。在这个方法中,需要构造一个 BrowserRoot 返回,作为车机页面树的根节点。整个页面树构造 BrowserRoot 需要传入 rootId。
  • clientPackageName – 是唤起客户端是包名,一般来说是 Android Auto App,包名是 com.google.android.projection.gearhead。但是有时候通过语音搜索播歌唤起客户端,包名就是 com.google.android.googlequicksearchbox,是 google 语音助手。通过这个参数可以过滤你认为有效的包名。
  • 其他两个参数一般用不上。
onLoadChildren()
override fun onLoadChildren(
    parentMediaId: String,
    result: Result<List<MediaItem>>
)
  • onLoadChildren 方法一旦被回调,说明在车机上真正开始加载手机客户端对应的车机页面树了。所以这个方法可以认为是车机端的 launch 点,可以用这个方法统计车机 DAU。
  • parentMediaId – 之前我们会在 onGetRoot 中返回了 rootId,接下来车机会回调 onLoadChildren, rootId 就会作为该方法的 parentMediaId 传入,代表在此次 onLoadChildren 方法回调中我们需要加载 parentMediaId 对应的页面树节点对应的 List,也就是页面树中该节点的子节点。
  • 加载好了子节点后,以 List 的形式,通过 result.sendResult(List) 方法将结果返回给车机。

整体的页面树如上所示。当在车机上点击蓝色子节点时,会回调 onLoadChildren 加载下一级子节点。当点击绿色叶子节点时,会回调 onPlayFromMediaId 方法进行起播。下面详细介绍。

MediaSession.Callback
  • MediaSession.Callback 是用户在车机上进行起播、播控以及语音搜索等操作的回调。该抽象类中包含了一系列的回调方法。下面介绍一些重要的回调方法。
  • 通过 mediaSession.setCallback 方法设置回调。
public abstract static class Callback { 
    public boolean onMediaButtonEvent(Intent mediaButtonEvent) {}// 线控耳机回调
    public void onPlay() {} // 播放
    public void onPause() {} // 暂停
    public void onPlayFromMediaId(String mediaId, Bundle extras) {} // 起播
    public void onPlayFromSearch(String query, Bundle extras) {} // 语音搜索
    public void onSkipToQueueItem(long id) {} // 切到播放队列中的某一首歌
    public void onSkipToNext() {} // 切到下一首
    public void onSkipToPrevious() {} // 切到上一首
    public void onCustomAction(String action, Bundle extras) {} // 自定义操作
    ....
}
MediaSession.setPlaybackState
  • 当我们执行了上述回调后,如何通知车机进行播放页的 UI 更新呢?这时候就需要调用 MediaSession.setPlaybackState 方法来通知车机更新 playback 的状态和 UI。PlaybackState,顾名思义,就是车机播放状态,所以改变这个状态意味着车机播控页 UI 也会更新。
  • 该方法具体如何使用可以参考 UMAP demo 和官方文档,这里不展开了。
onPlayFromMediaId
  • 上面我们说到,当用户在车机屏幕上点击歌曲起播时,就会回调该方法,并将构建页面树时赋予的 id 作为 mediaId 参数传入。因此,在该方法中我们需要调用客户端的起播歌曲的方法来起播。
onPlay 和 onPause
  • 这两个方法对应车机上的播放和暂停操作。
onSkipToNext 和 onSkipToPrevious
  • 这两个方法对应车机上的切下一首和切上一首操作。
onSkipToQueueItem
  • 在车机上切换到当前队列里的某一首歌,会回调该方法。传入对应的歌曲 id。
  • 在队列切歌之前,需要先给车机构造队列。调用 mediaSessionCompat.setQueue(List) 即可。
onPlayFromSearch(String query, Bundle extras)
  • 当我们在车内使用语音助手起播歌曲时,比如说 「播放周杰伦的夜曲」,会回调该方法。并且将语音内容识别成文字,分词后将 「周杰伦 夜曲」 通过入参 query 传入。这样我们拿到 query 字符串后,调用客户端的搜索服务就可以获得搜索的歌曲结果,并将该结果起播即可。
onCustomAction(String action, Bundle extras)
  • 当你想在车机播控界面添加其他自定义的操作,比如收藏歌曲、单曲循环等,就会用到这个方法。
  • 首先需要在构造 PlaybackState 的时候传入你定义的自定义操作,通过 PlaybackStateBuilder.addCustomAction(CustomAction action) 方法完成。构造 aciton 时需要传入唯一的标识字符串。在刷新了 PlaybackState 之后,在车机的播控界面就会出现自定义的操作按钮。
  • 当在车机屏幕点击了自定义操作按钮后,会回调 onCustomAction 方法,入参 action 就是唯一标识字符串,根据该字符串来区分不同的自定义操作。

开发中的坑

Android Auto 在国内渗透率不高,所以大部分开发者对这个东西很陌生,我也是。并且很多国产 ROM 系统层就不支持 Android Auto。作为国内业界少数 Android Auto 的应用,在开发过程中经历了资料匮乏、机型兼容、审核被拒等很多坑。这里把之前开发踩坑的经历分享出来。

图标缓存

车机界面每个 tab 的 icon 在设置完之后是会有在车机里缓存的。如果修改了 icon 样式,一定要改掉对应的 drawable 的 id,不然车机会从缓存中取图片,icon 修改不生效。

机型不兼容

很多国产的 rom 对 Android Auto 的支持有问题。具体表现有:

  • 无法安装 GMS 导致无法使用 Android Auto App,以华为系手机为代表。
  • 可以安装并且运行 Android Auto App,但是一旦连上 DHU 测试的时候,DHU 就一直黑屏,无法正常运行。亲测小米 11 、vivo S15 机型有该问题。
  • 可以连接 DHU,可以正常运行,但是使用 debug 包在测试的时候,DHU 上不会显示应用。只有使用 GP 商店分发的包才能显示出来。 部分 vivo 手机有这个问题。

所以,最好使用 pixel 这样的原生系统进行测试。

GP 分发

当我们在 DHU 上测完,想使用真实车机进行测试的时候,却发现真车上不显示我们的应用。正如之前所述,在真车上测试,需要经过 GP 分发的包才行,没有经过 GP 分发过的包,即使是 release 包也不行。这个坑当时困扰了我们很久,最后我们也是靠猜测才猜出原因。后来我们和 google 官方进行沟通,也确认了这一点。但是坑爹的是,google 文档里完全没有提及这一点。

语音搜索

语音搜索这个功能,在 DHU 上经常莫名其妙地不好用。具体有

  • 识别不出语音,语音助手回复 「对不起,我没有听懂」
  • 识别成别的应用,比如无论你怎么说 「使用 xxx 播放音乐」,它都回复 「好的,我来让 youtube music 播放音乐」,然后打开 youtube music 播放音乐
  • 语音说完没有任何反应。比如你说 「播放音乐」,在语音助手的对话框消失后就没有任何反应了,也没有回复,也不会打开应用播放。
  • 识别率差。我们的应用名,经常会识别错。但是像 Spotify、微信等应用名,识别率很高。怀疑是 google 语音助手对特定应用名识别做了优化。 上面这些坑是在做语音搜索功能时经常遇到的。QA 在测的过程中也会经常遇到并且反馈 bug 给我。但大部分时候都是语音助手抽风。

如何判断到底是 bug 还是语音助手抽风呢,可以用同样的语音去试下其他应用,比如 spotify 和 YT music。如果也有同样的问题,那么可以认为是语音助手又抽风了。

审核

Google 商店对车载应用的审核标准很高。详见 质量规范,其中对车载应用需要满足什么样的条件做了严格的要求。对于音乐类应用,有几点容易忽视的需要格外关注:

  • 必须支持语音搜索播歌功能。google 认为,用户在开车时不能分散注意力,所以必须提供语音搜索播歌的功能,让用户可以开车的同时按下方向盘上的麦克风按钮,直接语音控制歌曲的播放。如果这个功能没满足,应用不能过审。

  • 歌曲播放时,如果手机上碰到阻塞,比如出需要手动关闭的广告、出弹窗、请求权限,必须让用户转到手机上处理时,这时候必须要在车机屏幕上提示用户。这时可以使用错误提示的 API 来做提示。

  • 添加特定的 Intent Filter
<activity ...>
   <intent-filter>
       <action android:name="android.media.action.MEDIA_PLAY_FROM_SEARCH" />
       <category android:name="android.intent.category.DEFAULT" />
   </intent-filter>
</activity>

一定要在启动 Acitivity 里面添加这个 intent-filter,用来兼容古老版本的 android 手机语音播歌。可以参考

这个点其实在 google 官方文档里有提,但是没有明确说必须要有,只是建议添加。但是如果不加的话,应用审核会被拒绝。所以这里也是个坑点。

总之,成为一名Android车载开发工程师需要深厚的技术功力,同时他们需要不断学习并更新专业知识和技能,以应对未来Android车载应用市场的不断变化,并更好地实现车载应用的创新和发展。

针对车载Android 开发所需要学习的内容,整理了以下的知识路线

路线有了,那自然参考的学习文档笔录也不会少,大家可以参考:https://qr18.cn/F05ZCM

Android 车载学习手册:

  • 第一章——Android Auto概述
  • 第二章——开发汽车媒体应用
  • 第三章——构建 Android Auto即时通信应用
  • 第四章——构建车载导航和地图的注点应用
  • 第五章——构建 Android Automotive OS 视频应用

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

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

相关文章

[国产MCU]-BL602开发实例-定时器

定时器 文章目录 定时器1、BL602定时器介绍2、定时器驱动API介绍3、定时器使用实例3.1 单次计时3.2 持续计时通用定时器,用于定时,当时间到达我们所设置的定时时间会产生定时中断,可以用来完成定时任务。本文将详细介绍如何使用BL602的定时器功能。 1、BL602定时器介绍 BL6…

vscode自动添加注释说明

1. 安装vscode 双击安装程序,默认安装即可(如:VSCodeSetup-x64-1.70.2.exe) 2. 安装doxygen文档生成插件 1> 打开vscode软件,点击左侧插件管理菜单 2> 点击右上角’…‘按钮,选择’Install from VSIX’(联网状态可以直接搜索doxygen下载安装) 3> 选择doxygen离线安装…

torchvision.datasets数据加载失败

torchvision.datasets数据加载失败 如何使用torchvision.datasets进行自动下载数据失败&#xff0c;可以使用手动下载数据 Ctrl点击可以进入相关包文件&#xff0c;查找下载地址&#xff1a;https://www.cs.toronto.edu/~kriz/cifar-10-python.tar.gz 手动下载之后解压&#x…

【Spring】(四)Bean 的作用域和生命周期

文章目录 前言一、Bean 的作用域1.1 被修改的 Bean 案例1.2 作用域的定义1.3 Bean 的六种作用域1.4 Bean 作用域的设置 二、Spring 的执行流程 和 Bean 的生命周期2.1 Spring 的执行流程2.2 Bean 的生命周期2.3 Bean 生命周期的演示 前言 Bean 是 Spring 框架中的一个核心概念…

Benchmarking Augmentation Methods for Learning Robust Navigation Agents 论文阅读

论文信息 题目&#xff1a;Benchmarking Augmentation Methods for Learning Robust Navigation Agents: the Winning Entry of the 2021 iGibson Challenge 作者&#xff1a;Naoki Yokoyama, Qian Luo 来源&#xff1a;arXiv 时间&#xff1a;2022 Abstract 深度强化学习和…

AssetBundleBrowser导入报错解决方案

第一次导入AssetBundleBrowser遇到报错有 Assets\Scenes\AssetBundles-Browser-master\AssetBundles-Browser-master\Tests\Editor\ABModelTests.cs(13,7): error CS0246: The type or namespace name Boo could not be found (are you missing a using directive or an assem…

24届近5年杭州电子科技大学自动化考研院校分析

今天给大家带来的是杭州电子科技大学控制考研分析 满满干货&#xff5e;还不快快点赞收藏 一、杭州电子科技大学 学校简介 杭州电子科技大学&#xff08;Hangzhou Dianzi University&#xff09;&#xff0c;简称“杭电”&#xff0c;位于杭州市&#xff0c;是浙江省人民政…

Containerd容器镜像管理

1. 轻量级容器管理工具 Containerd 2. Containerd的两种安装方式 3. Containerd容器镜像管理 4. Containerd数据持久化和网络管理 1、Containerd镜像管理 1.1 Containerd容器镜像管理命令 docker使用docker images命令管理镜像单机containerd使用ctr images命令管理镜像,con…

消息队列 -封装数据库的操作

前言 上一篇博客我们写了, 关于交换机, 队列,绑定, 写入数据库的一些建库建表的操作 这一篇博客中,我们将建库建表操作,封装一下实现层一个类来供上层服务的调用 , 并在写完该类之后, 测试代码是否完整 实现封装 在写完上述的接口类 与 xml 后, 我们想要 创建一个类 ,来调用…

Neety与IO模型简介

Netty与IO模型简介 1、Netty 是由 JBOSS 提供的一个 Java 开源框架&#xff0c;现为 Github 上的独立项目。 2、Netty 是一个异步的、基于事件驱动的网络应用框架&#xff0c;用以快速开发高性能、高可靠性的网络 IO 程序。 3、Netty 主要针对在 TCP 协议下&#xff0c;面向…

2023牛客暑期多校训练营7-c-Beautiful Sequence

思路&#xff1a; &#xff0c;则有&#xff0c;也就是说只要知道A1就可以求任意A。由于A是升序排列&#xff0c;所以对于任意&#xff0c;二进制所包含1的最高位第k位来说&#xff0c;表明与第k位相反&#xff0c;要大一些&#xff0c;所以它的第k位为1&#xff0c;的第k位为…

echarts 柱状图 实例

实例效果&#xff1a; 代码&#xff1a; draw(data1, data2,data3) {var option {// backgroundColor: rgb(10,36,68),tooltip: {trigger: axis,axisPointer: {type: shadow,},formatter: function (params: any, ticket: any, callback: any) {const item params[0];var str…

关于“为爱发电”的一些说明~~

对不起&#xff0c;兄弟们&#xff0c;收费了。。 1. 为什么设置收费 emm...混口饭吃。 也是大龄程序员积在极探索挣钱之路。 2. 都有哪些服务 本专栏的手把手教学资料工程文件&#xff0c;但是近期忙于CMN&#xff0c;可能没时间答疑和讨论&#xff0c;见谅。 另外&#xff0…

知识图谱实战应用23-【知识图谱的高级用法】Neo4j图算法的Cypher查询语句实例

大家好,我是微学AI,今天给大家介绍一下知识图谱实战应用23-【知识图谱的高级用法】Neo4j图算法的Cypher查询语句实例,Neo4j图算法是一套在Neo4j图数据库上运行的算法集合。这些算法专门针对图数据结构进行设计,用于分析、查询和处理图数据。图算法可以帮助我们发现图中的模…

class version 61 java version 17.0.4

class version (javap -verbose xxxx.class)_spencer_tseng的博客-CSDN博客

概念解析 | 合成孔径雷达中运动补偿与自聚焦的关系

注1:本文系“概念解析”系列之一,致力于简洁清晰地解释、辨析复杂而专业的概念。本次辨析的概念是:合成孔径雷达中运动补偿和自聚焦的联系与差别 概念解析 | 合成孔径雷达运动补偿与自聚焦的关系研究 基于二维空变运动补偿的机动平台大斜视SAR稀疏自聚焦方法 一、背景介绍 合成…

qt源码---事件系统之QCoreApplication

上一节分析了qt和windows系统之间的消息的传递&#xff0c;本节着重看一下&#xff0c;qt内部的事件是如何传递的&#xff1f; 1.sendEvent函数 在使用的自定义事件时&#xff0c;有时需要手动抛出一个事件&#xff0c;常用的方式有2种&#xff0c;其一时阻塞式的sendEvent函…

优化手机性能,解决卡顿问题:关闭这3个微信开关,释放内存空间

在日常使用手机的过程中&#xff0c;微信无疑是受欢迎和广泛使用的社交应用之一。然而&#xff0c;由于微信的一些默认设置可能会占用大量内存空间&#xff0c;导致手机性能下降并出现卡顿问题。为了提高手机的运行效果&#xff0c;我们需要注意并关闭这3个微信开关&#xff0c…

面试热题(环形链表II)

给定一个链表&#xff0c;返回链表开始入环的第一个节点。 从链表的头节点开始沿着 next 指针进入环的第一个节点为环的入口节点。如果链表无环&#xff0c;则返回 null。 为了表示给定链表中的环&#xff0c;我们使用整数 pos 来表示链表尾连接到链表中的位置&#xff08;索引…

最后一次模拟考试题解

哦我想这不用看都知道是为了水任务 T1 黑白染色 其实这题有原 什么手写体 md (指 markdown) 分析 首先这题如果你题目没看错的话 ,会发现其实他是 n m n \times m nm 让你求 n n n \times n nn 的区域内的点&#xff08;不会只有我一个人题目看错了罢 然后我们会发现…