时光地下铁

Software is a great combination of art and engineering.

有时候过多的分支的提交记录会导致整个git历史杂乱而难以进行版本回溯,这里介绍一种基于 rebase 的 Git 工作流,核心目标是维护一条线性、洁净的提交历史,避免产生多余的 merge commit,让代码审查和版本回溯更加清晰。

核心原则

  • 每条 feature 分支只包含该功能的必要提交
  • 合入主干前通过 rebase 将分支提交平移到主干顶端
  • 不使用 merge --no-ff,禁止产生环状历史
  • 主干(dev)始终是一条直线

步骤详解

1. 同步本地主干

1
2
git checkout dev
git pull

确保本地 dev 分支与远程保持一致。git pull 相当于 git fetch origin dev:dev + 快进合并,在未偏离远程的前提下不会产生额外提交。

阅读全文 »

你在手机上打开开发者选项,点下“启用蓝牙 HCI 信息收集日志”,然后复现那个偶现的连接闪断。十几秒后,你拿到一份日志(Android 是 btsnoop_hci.log,iOS 是 PacketLogger 捕获的 .pklg)。用 Wireshark 打开,迎面而来的是满屏的时间戳、十六进制和缩写:CMDEVTACLLE Meta

多数移动端开发者到这里就放弃了。

但真相是:HCI 日志是蓝牙协议栈唯一不会说谎的部分。上层 API 的异常、系统回调的延迟、固件的怪异行为,在 HCI 层都会留下精确到微秒的痕迹。无论你开发的是 Android 还是 iOS 应用,一旦学会阅读它,你就拥有了一双透视协议栈的“显微眼”。

本文将兼顾广度与深度,从协议栈分层讲起,到二进制位级拆解,再到真实案例实战,并通过 Android 与 iOS 的双端对比,让你彻底掌握用 HCI 日志跨平台排查问题的能力。


一、HCI 是什么?为什么它至关重要?

1.1 蓝牙的“大脑”与“身体”:Host 与 Controller

要搞懂 HCI,必须先理清蓝牙系统的两个核心角色:Host(主机)Controller(控制器)

打一个经典的比方:你用手机 App 连接一个蓝牙体温计。

  • Host (主机):手机上的软件部分。包括你的 App、操作系统里的蓝牙协议栈(Android 的 Bluedroid/Fluoride,iOS 的 CoreBluetooth)。它负责高层逻辑,如“连接哪个设备”“把体温数据解析显示到屏幕上”“弹出配对对话框”。
  • Controller (控制器):手机里的蓝牙射频芯片及其固件。它只负责最底层的硬件操作,如“在物理信道 37 上发一个广播包”“以 30 微妙精度在约定时刻回复数据”。

那么,在你的手机和体温计之间,角色具体怎样分布?

阅读全文 »

笔者最近遇到BLE传输性能问题,研究了一下BLE(低功耗蓝牙)传输效率的系统性瓶颈,涵盖链路层协议、系统调度、硬件共存、平台差异等核心维度,适用于 iOS/Android/HarmonyOS 三端,供大家优化参考。


1. 核心链路参数:BLE 传输的”天花板”

BLE 的理论速度首先受制于链路层(Link Layer)参数的协商,这些参数决定了 BLE 物理信道的利用效率上限。

1.1 Connection Interval(连接间隔)

BLE 是跳频通信,每隔一个 Connection Interval,双方才进行一次数据交换(Connection Event)。间隔越短,单位时间内可用的传输次数越多,吞吐量越高。

根据 Bluetooth Core Specification,Connection Interval 的规范范围为 7.5 ms ~ 4.0 s,以 1.25 ms 为步进 [1]。各平台的实际限制如下:

平台 最小值 推荐值 备注
iOS 15ms(CoreBluetooth) 15~20ms HID 设备可达 11.25ms;普通设备若请求 15ms,部分机型可能平衡至 30ms [2]
Android 7.5ms 15~20ms 后台/Doze 模式下系统可能拒绝低功耗模式外的激进参数请求 [3]
HarmonyOS 7.5ms 15~20ms 受限于系统电源策略,高功耗场景自动延长

关键机制:每个 Connection Event 内可以包含多个 PDU(Protocol Data Unit)。若设备支持 DLE(Data Length Extension,见 1.3),单个 Connection Event 可承载更多数据。

阅读全文 »

在真实的业务场景中,绝大多数Flutter项目都已完成iOS和Android双平台的开发与落地,承载着核心业务逻辑、用户交互及多端一致性体验的需求。随着鸿蒙(HarmonyOS)生态的快速崛起,覆盖手机、平板、穿戴设备等全场景的终端布局,将已有的Flutter 3.x工程适配到鸿蒙平台,成为许多企业拓展生态覆盖、触达更多用户的必然选择。本文提供将已有的 Flutter 3.x (iOS/Android 双平台) 工程适配到鸿蒙(HarmonyOS)的详细技术方案。


一、环境准备

1.1 安装鸿蒙 flutter_flutter

Flutter鸿蒙需要使用社区版本维护的适配鸿蒙的 Flutter分支flutter_flutter:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 方式一:从 Gitcode 克隆
git clone https://gitcode.com/openharmony-tpc/flutter_flutter.git

# 编辑 ~/.zshrc 或 ~/.bashrc
export PATH="$PATH:/path/to/flutter_flutter/bin"
export FLUTTER_ROOT=/path/to/flutter_flutter

# 使配置生效
source ~/.zshrc

# 方式二:使用开源脚本flutter_env_switch,自动添加环境变量
# 1. 复制脚本到本地
git clone https://github.com/lengain/flutter_env_switch.git
cd flutter_env_switch
cp flutter_env_switch.sh ~/
# 2. 添加执行权限
chmod +x ~/flutter_env_switch.sh

# 3. 执行环境检查(首次运行会自动初始化)
sh ~/flutter_env_switch.sh harmony
阅读全文 »

项目背景

Flutter Flavorizr 是什么

Flutter Flavorizr 是 Flutter 生态中广泛使用的多环境构建工具,通过一份 YAML 配置自动生成 Android、iOS、macOS 三端的 flavor 工程结构。开发者只需声明各 flavor 的包名、图标、签名等差异化配置,工具即可自动完成 Gradle productFlavors 注入、Xcode scheme/build configuration 创建、资源文件分发等繁琐工作。

该项目在 pub.dev 上拥有较高使用量,是 Flutter 多环境管理的事实标准方案之一。

为什么要做鸿蒙适配

随着 HarmonyOS 生态的持续推进,越来越多的 Flutter 应用需要同时支持 Android、iOS 和鸿蒙三端。Flutter 社区已提供鸿蒙版 SDK(如 Flutter 3.35.8-ohos),但在构建工具层面,flavorizr 尚未支持鸿蒙平台的多产品(multi-product)构建。

鸿蒙平台的构建体系与 Android/iOS 有本质差异:

维度 Android iOS/macOS HarmonyOS
构建系统 Gradle Xcode hvigor
多环境机制 productFlavors scheme + build configuration product + target
配置格式 Groovy/Kotlin DSL .xcodeproj + .xcconfig JSON5 (build-profile.json5)
签名管理 signingConfigs Provisioning Profile signingConfigs in JSON5

这意味着不能简单复用已有的 Android 或 iOS 处理器逻辑,需要为鸿蒙平台设计全新的配置模型和处理器链路。

阅读全文 »

背景与动机

在鸿蒙(OpenHarmony / HarmonyOS NEXT)生态持续扩张的背景下,越来越多的开发者需要将现有的 C/C++ 开源库移植到鸿蒙平台。然而鸿蒙的 NDK 工具链与传统 Linux / Android 存在若干关键差异,其中最容易踩坑的就是 共享库 SONAME 格式

本文基于 Opus 音频编解码库 的鸿蒙适配实践,参考官方文档,系统梳理从工具链配置、CMake 工程改造到最终产物验证的完整流程,帮助开发者少走弯路。

阅读全文 »

每次切环境都像拆盲盒:flutter 到底指向哪个 SDK?

pub get 为什么又超时了?


这篇文章分享一个可落地的工程化解法:用一个 Shell 脚本,把鸿蒙与 iOS 的 Flutter 环境切换做成“可重复、可追溯、可持久化、可自愈”的标准流程。

先说痛点

如果你和我一样,一台 Mac 同时做两类 Flutter 开发:

  • 鸿蒙开发:常用定制 SDK / 镜像源;

  • iOS 开发:常用官方 Flutter / 官方源。

那你大概率踩过这些坑:

  1. PATH 被来回覆盖,which flutter 指向不稳定;

  2. PUB_HOSTED_URLFLUTTER_STORAGE_BASE_URL 没成套切换,pub get 时灵时不灵;

  3. 终端重启后环境丢失,要再手动配置一遍;

阅读全文 »

引言

在音频应用开发过程中,单纯的Opus编解码往往不足以满足复杂的生产需求。标准的Ogg Opus容器格式能够为音频数据提供完整的元数据、时间戳、以及与主流播放器的兼容性。HarmonyOS平台在这方面同样存在空白,现有的音频编解码方案缺乏标准容器支持。OggOhos库应运而生,通过结合OpusOhos编码能力和libogg容器支持,为HarmonyOS开发者提供生产级别的Ogg Opus编解码解决方案。本文详细阐述OggOhos库的架构设计、实现原理及技术细节。

本库发布到OpenHarmony三方库中心仓

开发背景

技术需求分析

音频应用的完整开发需要解决以下核心问题:

  1. 标准文件格式支持:应用需要生成和读取符合RFC 7845标准的Ogg Opus文件,确保与其他平台和播放器的兼容性
  2. 元数据管理:需要在音频文件中持久化存储采样率、声道数、时间戳等关键信息
  3. 流式处理能力:支持大文件的流式编解码,而非一次性加载到内存
  4. 跨生态协作:生成的音频文件可被各平台(Web、iOS、Android等)正确识别和播放

传统的单纯Opus编码只能生成裸音频帧,缺乏完整的文件格式封装,这在实际应用中很难被主流播放器直接识别。

为什么选择Ogg容器

Ogg Vorbis容器能够为音频编解码器提供以下支持:

  • 标准规范:RFC 7845明确定义了Ogg Opus的封装方式,确保跨平台兼容
  • 灵活扩展:通过OpusHead和OpusTags包提供参数携带和标签管理
  • 流式音频:支持流式编码和解码,适合实时应用和大文件处理
  • 时间精度:Granulepos机制提供精确的样本级时间戳
  • 广泛支持:几乎所有主流音频播放器都原生支持Ogg Opus格式
阅读全文 »

摘要

在 iOS 26.3(Xcode 相应版本)上,使用 CocoaPods 的 use_frameworks! 动态链接方式部署 Flutter 应用时,会导致整个网络栈(包括 DNS 解析和 TCP 连接)完全失效。本文通过系统的诊断实验,揭示了这一问题的根本原因,并提供了可靠的修复方案。


一、问题现象

症状描述

在 iOS 26.3 设备上运行 Flutter 应用,出现全面的网络连接失败:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
❌ DNS 解析失败

Error: Failed host lookup (OS Error: nodename nor servname provided,

or not known, errno = 8)



❌ IP 直连失败

Error: Connection failed (OS Error: No route to host)



❌ HTTP/HTTPS 请求失败

所有基于 DNS 或 IP 连接的网络操作无法进行



❌ 影响范围

同一设备上的 Safari 浏览器、其他应用网络正常

➜ 非设备/网络环境问题,特定于该 Flutter 应用
阅读全文 »

引言

随着 HarmonyOS 生态的快速发展,移动应用对高质量音频处理的需求日益增长。无论是实时语音通话、音频录制还是流媒体传输,都需要一个高效、可靠的音频编解码解决方案。Opus 作为一种开放、免版税的音频编解码标准,以其卓越的音质和灵活性在业界广受认可。然而,HarmonyOS 平台缺乏成熟的 Opus 编解码库支持。本文将详细介绍 OpusOhos 库的设计与实现过程,探讨如何将 C/C++ 原生库高效集成到 HarmonyOS 应用开发生态中。

目前该库已发布到OpenHarmony三方库中心仓,点击前往

阅读全文 »
0%