KMM Android端ConnectivityObserver权限缺失致CI构建失败
问题背景
使用KMM实现平台专属的ConnectivityObserver监听网络状态,Android端代码调用ConnectivityManager.registerDefaultNetworkCallback,已在androidApp模块的Manifest中声明ACCESS_NETWORK_STATE和INTERNET权限,但CI构建时触发MissingPermission错误,即使在shared/androidMain添加Manifest文件也无法解决。
解决方案
1. 强制Manifest权限合并
在androidApp模块的Manifest中给权限标签添加tools:node="merge"属性,避免权限被其他模块的Manifest配置覆盖:
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools"> <uses-permission android:name="android.permission.INTERNET" tools:node="merge"/> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" tools:node="merge"/> <application ... </application> </manifest>
注意:必须在Manifest根标签中添加
tools命名空间。
2. 针对Shared模块的Lint规则调整
CI构建可能对shared模块单独执行Lint检查,而Lint无法识别app模块Manifest中的权限声明。可以在shared/androidMain目录下创建lint.xml文件,忽略该文件的权限检查:
<?xml version="1.0" encoding="UTF-8"?> <lint> <issue id="MissingPermission"> <ignore path="**/ConnectivityObserver.kt"/> </issue> </lint>
或者在app模块的build.gradle.kts中配置Lint,放宽跨模块权限检查:
android { lint { // 可选:针对Release构建关闭严格检查 checkReleaseBuilds = false // 或者直接禁用MissingPermission规则 disable += "MissingPermission" } }
3. 验证合并后的Manifest
检查CI构建过程中生成的合并Manifest文件(路径通常为app/build/intermediates/merged_manifests/<构建变体>/AndroidManifest.xml),确认ACCESS_NETWORK_STATE权限是否存在。如果不存在,排查是否有其他依赖模块的Manifest移除了该权限。
4. 补充权限检查逻辑(可选)
虽然ACCESS_NETWORK_STATE属于正常权限(无需运行时申请),但可以在代码中添加权限检查,确保万无一失:
import android.content.pm.PackageManager import androidx.core.content.ContextCompat // 在connectionFlow中添加检查 private val connectionFlow = callbackFlow { val hasPermission = ContextCompat.checkSelfPermission( context, android.Manifest.permission.ACCESS_NETWORK_STATE ) == PackageManager.PERMISSION_GRANTED if (hasPermission) { val callback = object : ConnectivityManager.NetworkCallback() { override fun onAvailable(network: Network) { super.onAvailable(network) trySend(true) } override fun onLost(network: Network) { super.onLost(network) trySend(false) } } connectivityManager.registerDefaultNetworkCallback(callback) awaitClose { connectivityManager.unregisterNetworkCallback(callback) } } else { trySend(false) } }
原因分析
KMM项目中,shared模块的Android代码在Lint检查时,默认只会检查自身模块内的Manifest配置,无法识别app模块Manifest中的权限声明。CI构建通常会对每个模块单独执行Lint,因此触发了权限缺失的错误。另外,Manifest合并过程中如果存在冲突配置,也可能导致权限被意外移除。
内容的提问来源于stack exchange,提问作者Andre Thiele

