Skip to content

feat(android): add Android 5.0+ (API 21) compatibility via multi-level Gradle property - #319

Merged
LanRhyme merged 3 commits into
MicYou-Dev:masterfrom
luminset:compat/v2.0.1
Aug 31, 2026
Merged

LanRhyme merged 3 commits into
MicYou-Dev:masterfrom
luminset:compat/v2.0.1

Conversation

@luminset

@luminset luminset commented Aug 26, 2026 •

Copy link
Copy Markdown
Contributor

概述

为 Android 端添加 Android 5.0+ (API 21) 和 32 位设备的兼容性支持,通过多级别 Gradle 属性开关控制,完全非破坏性——默认不加参数时编译结果与上游完全一致。

本 PR 基于最新 master (commit 90aaf76) 重新构建,已解决此前 rebase 不及时导致的兼容性问题。

实现方式

通过多级别 Gradle 属性 -Pmicyou.androidCompat=<level> 切换兼容模式:

  • 不传参数 → 正常模式(与上游完全一致)
  • api21 → Android 5.0+ 兼容模式
  • 预留扩展:api19 等更低级别

构建命令

原版(与上游一致):

./gradlew :composeApp:assembleDebug

兼容版(Android 5.0+):

./gradlew :composeApp:assembleDebug -Pmicyou.androidCompat=api21

PowerShell 中必须用引号:"-Pmicyou.androidCompat=api21"

构建系统改动

  • settings.gradle.kts:通过 versionCatalogs.version() 覆盖版本号,兼容模式下自动降级 AGP (9.3.1→8.9.1)、Kotlin (2.4.10→2.3.10)、Compose BOM (2026.05.00→2024.09.00) 等依赖
  • gradle/libs.versions.toml:新增 compat-* 系列版本条目,原版本值不动
  • composeApp/build.gradle.kts:条件控制 minSdk (24→21)、targetSdk (36→29)、MultiDex、核心库脱糖、JVM target (11→1.8)、32 位 ABI 支持、resolutionStrategy 强制降级

Source Set 桥接层

对 API 差异较大的库(haze、ExpressiveColorScheme)采用 source set 桥接方案:

  • src/normal/ — 正常模式:委托给原版库
  • src/compat/ — 兼容模式:降级实现(半透明背景替代 haze 模糊等)
  • src/main/ 仅从桥接包导入,无需修改

运行时兼容(始终生效,SDK_INT 守卫)

兼容点 高版本行为 低版本降级
AudioRecord 浮点读取 read(float[], READ_NON_BLOCKING) API 23+ read(ByteBuffer) + asFloatBuffer() 间接读取
AudioRecord 非阻塞模式 READ_NON_BLOCKING API 23+ 3 参数阻塞版本
前台服务启动 startForegroundService() API 26+ startService() + 内部 startForeground()
通知渠道 NotificationChannel API 26+ 跳过渠道创建,直接发通知
PendingIntent 标志 FLAG_IMMUTABLE API 23+ 仅 FLAG_UPDATE_CURRENT
闹钟精确唤醒 setExactAndAllowWhileIdle() API 23+ setExact()
startForeground 类型 3 参数版本 API 29+ 2 参数版本
POST_NOTIFICATIONS 权限 运行时请求 API 33+ 跳过,安装时自动授予
PCM_FLOAT 格式 默认使用 API 23+ 按 API 级别默认选择和过滤
Material3 颜色角色 动态颜色角色 API 31+ 降级为近似色值
MultiDex ART 原生支持 反射调用,无依赖时静默跳过

非破坏性保证

  1. 默认构建与上游完全一致(不加参数 = 无改动)
  2. 只新增 compat-* 条目,不修改原版本值
  3. 所有高版本 API 调用均有 SDK_INT 守卫
  4. Source Set 桥接层隔离,main 代码不直接引用差异库

验证

  • ✅ 兼容模式构建成功(-Pmicyou.androidCompat=api21)
  • ✅ 基于最新 upstream/master (commit 90aaf76)
  • ✅ 华为 P7(Android 5.1 / API 22)实机音频流正常传输
  • ✅ PCM_FLOAT 在 API<23 时自动降级为 PCM_16BIT

详细说明见 Android_兼容性编译说明.md。

@micyou-automation micyou-automation Bot added reviewing 正在复核 size/xl 500-999 行 labels Aug 26, 2026
@luminset luminset changed the title Android 5.0+ / 32-bit compatibility for v2.0.1 (non-breaking) feat(android): add Android 5.0+ / 32-bit compatibility (non-breaking, v2.0.1) Aug 26, 2026
@ChouChiu

Copy link
Copy Markdown
Member

冲突

…perty

Add non-breaking support for Android 5.0+ devices and 32-bit architectures
through a multi-level Gradle property switch (-Pmicyou.androidCompat=api21).

## Build System

- **Multi-level compatibility parameter**: Changed from boolean to numeric/string
  level design (api21, extensible to api19, etc.). Default (no flag) = upstream
  behavior unchanged.
- **Version catalog overrides**: settings.gradle.kts overrides AGP (9.3.1→8.9.1),
  Kotlin (2.4.10→2.3.10), Compose BOM (2026.05.00→2024.09.00), and other dependency
  versions via versionCatalogs.version() when compat mode is enabled.
- **lib.versions.toml**: Added compat-* version entries without modifying originals.
- **composeApp/build.gradle.kts**: Conditional configuration for minSdk (24→21),
  targetSdk (36→29), MultiDex, core library desugaring, JVM target (11→1.8),
  32-bit ABIs (armeabi-v7a, x86), and resolutionStrategy force downgrades.

## Source Set Bridge Layer

For libraries with large API differences (haze, materialKolor/ExpressiveColorScheme):
- src/normal/ — normal mode: delegates to original libraries (haze 1.7.2, etc.)
- src/compat/ — compat mode: downgraded implementations (semi-transparent fallback)
- src/main/ imports from bridge package, no direct library references

## Runtime Compatibility (always active, guarded by SDK_INT)

- AudioRecord: float PCM read and READ_NON_BLOCKING fallback for API < 23
- AudioService: NotificationChannel, PendingIntent.FLAG_IMMUTABLE,
  setExactAndAllowWhileIdle, startForeground(3-arg) all guarded by version checks
- MainActivity: startForegroundService() fallback for API < 26
- PermissionDialog: POST_NOTIFICATIONS runtime request only for API 33+
- AudioSettings: availableAudioFormats() filters PCM_FLOAT below API 23
- AudioStreamViewModel: default audio format based on device API level
- Material3: ColorSchemeCompat for dynamic color roles below API 31

## Application & Manifest

- MicYouApplication: Reflective MultiDex.install() + global crash log handler
- AndroidManifest: android:name, tools:ignore for high-version permissions,
  tools:overrideLibrary for minSdk conflicts

## Documentation

- Android_兼容性编译说明.md: Complete build guide, version comparison table,
  runtime compatibility list, source set bridge explanation, and verification steps

## Non-destructive Guarantee

- Default build identical to upstream (no flag = no change)
- Only adds entries, never modifies original version values
- All runtime checks use Build.VERSION.SDK_INT guards
- Reflective MultiDex call silently skips when dependency absent
@micyou-automation micyou-automation Bot added size/xxl 1000+ 行 and removed size/xl 500-999 行 labels Aug 26, 2026
@luminset luminset changed the title feat(android): add Android 5.0+ / 32-bit compatibility (non-breaking, v2.0.1) feat(android): add Android 5.0+ (API 21) compatibility via multi-level Gradle property Aug 26, 2026
@luminset

Copy link
Copy Markdown
Contributor Author

冲突

我刚提交了基于最新代码的更新,看看是否能够解决冲突?

@luminset

Copy link
Copy Markdown
Contributor Author

你好~注意到 opencode 这个 CI check 在本 PR 上失败了,想分享一下我的观察,供参考:

错误信息是 Could not fetch an OIDC token,但我看到 .github/workflows/opencode.yml 里已经配置了 id-token: write 权限。进一步观察发现:

这意味着 opencode 在所有 fork 提交的 PR 上可能都会失败,属于预期行为,与本 PR 的代码改动无关。本 PR 的其他构建 check(Android + 三个 Tauri 平台)均已全部通过。

如果后续希望 opencode 也能在 fork PR 上运行,可能需要考虑:

  1. 将 opencode 的触发条件调整为仅在本仓库内部分支的 PR 上运行(通过 github.event.pull_request.head.repo.full_name == github.repository 判断)
  2. 或者改用不需要 OIDC 的鉴权方式

以上仅供维护者参考,如有不对的地方欢迎指正~

@LanRhyme
LanRhyme merged commit 98e5b93 into MicYou-Dev:master Aug 31, 2026
@micyou-automation micyou-automation Bot added done 完成 and removed reviewing 正在复核 labels Aug 31, 2026
@luminset
luminset deleted the compat/v2.0.1 branch October 18, 2026 17:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

done 完成 size/xxl 1000+ 行

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants