You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

自定义Android系统中设为默认短信App时Realm权限拒绝报错

Realm权限拒绝错误:设为系统默认短信应用时触发Permission denied

开发类短信的系统级默认应用,所有数据通过Realm数据库同步。在自定义Android系统中将该应用设为默认应用后,每次都会抛出如下权限拒绝错误:

RealmError: Permission denied in /Users/jasonflax/Development/realm-java/realm/realm-library/src/main/cpp/io_realm_internal_OsSharedRealm.cpp line 101

应用初始化代码

class App : Application() {
    override fun onCreate() {
        super.onCreate()
        Realm.init(this)
        val realmConfig = RealmConfiguration.Builder()
            .compactOnLaunch()
            .name("sms.realm")
            .deleteRealmIfMigrationNeeded()
            .migration(realmMigration)
            .schemaVersion(QkRealmMigration.SchemaVersion)
            .build()
        Realm.setDefaultConfiguration(realmConfig)
        try {
            Realm.getDefaultInstance()
        } catch (e: RealmError){
            rebuildRealm(realmConfig)
        } catch (e: RealmFileException){
            rebuildRealm(realmConfig)
        }
    }

    private fun rebuildRealm(realmConfig: RealmConfiguration) {
        Realm.deleteRealm(realmConfig)
        Realm.setDefaultConfiguration(realmConfig)
    }
}

崩溃日志

FATAL EXCEPTION: main
Process: com.app.sms, PID: 10913
io.realm.exceptions.RealmError: Unrecoverable error. Permission denied in /Users/jasonflax/Development/realm-java/realm/realm-library/src/main/cpp/io_realm_internal_OsSharedRealm.cpp line 101
at io.realm.internal.OsSharedRealm.nativeGetSharedRealm(Native Method)
at io.realm.internal.OsSharedRealm.<init>(OsSharedRealm.java:171)
at io.realm.internal.OsSharedRealm.getInstance(OsSharedRealm.java:241)
at io.realm.BaseRealm.<init>(BaseRealm.java:136)
at io.realm.BaseRealm.<init>(BaseRealm.java:103)
at io.realm.Realm.<init>(Realm.java:163)
at io.realm.Realm.createInstance(Realm.java:499)
at io.realm.RealmCache.doCreateRealmOrGetFromCache(RealmCache.java:355)
at io.realm.RealmCache.createRealmOrGetFromCache(RealmCache.java:285)
at io.realm.Realm.getDefaultInstance(Realm.java:407)
at com.app.sms.repository.ConversationRepositoryImpl.getConversations(ConversationRepositoryImpl.kt:58)
at com.app.sms.repository.ConversationRepository$DefaultImpls.getConversations$default(ConversationRepository.kt:29)
at com.app.sms.feature.main.MainViewModel.<init>(MainViewModel.kt:73)
at com.app.sms.feature.main.MainViewModel_Factory.provideInstance(MainViewModel_Factory.java:189)
at com.app.sms.feature.main.MainViewModel_Factory.get(MainViewModel_Factory.java:122)
at com.app.sms.feature.main.MainViewModel_Factory.get(MainViewModel_Factory.java:28)
at com.app.sms.feature.main.MainActivityModule_ProvideMainViewModelFactory.provideInstance(MainActivityModule_ProvideMainViewModelFactory.java:31)
at com.app.sms.feature.main.MainActivityModule_ProvideMainViewModelFactory.get(MainActivityModule_ProvideMainViewModelFactory.java:26)
at com.app.sms.feature.main.MainActivityModule_ProvideMainViewModelFactory.get(MainActivityModule_ProvideMainViewModelFactory.java:9)
at com.app.sms.common.ViewModelFactory.create(ViewModelFactory.kt:28)
at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.java:164)
at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.java:130)
at com.app.sms.feature.main.MainActivity$viewModel$2.invoke(MainActivity.kt:152)
at com.app.sms.feature.main.MainActivity$viewModel$2.invoke(MainActivity.kt:82)
at kotlin.SynchronizedLazyImpl.getValue(LazyJVM.kt:74)
at com.app.sms.feature.main.MainActivity.getViewModel(Unknown Source:2)
at com.app.sms.feature.main.MainActivity.onCreate(MainActivity.kt:177)

问题分析与解决方案

1. 调整Realm存储目录权限

系统默认短信应用的进程上下文可能对默认的getFilesDir()目录存在访问限制,可将Realm文件存储到系统允许的安全目录:

val realmConfig = RealmConfiguration.Builder()
    .directory(getNoBackupFilesDir()) // 使用系统推荐的无备份目录
    .name("sms.realm")
    .compactOnLaunch()
    .deleteRealmIfMigrationNeeded()
    .migration(realmMigration)
    .schemaVersion(QkRealmMigration.SchemaVersion)
    .build()

2. 限制Realm仅在主进程初始化

系统默认应用可能被多进程调用(如系统服务触发的进程),导致Realm文件访问冲突。仅在主进程初始化Realm:

override fun onCreate() {
    super.onCreate()
    if (packageName == applicationInfo.processName) { // 判断当前是否为主进程
        Realm.init(this)
        val realmConfig = RealmConfiguration.Builder()
            .name("sms.realm")
            .compactOnLaunch()
            .deleteRealmIfMigrationNeeded()
            .migration(realmMigration)
            .schemaVersion(QkRealmMigration.SchemaVersion)
            .build()
        Realm.setDefaultConfiguration(realmConfig)
        try {
            Realm.getDefaultInstance().close() // 初始化后立即关闭实例,避免持有锁
        } catch (e: RealmError){
            rebuildRealm(realmConfig)
        } catch (e: RealmFileException){
            rebuildRealm(realmConfig)
        }
    }
}

3. 检查自定义系统的SELinux策略

自定义Android系统的SELinux规则可能严格限制了默认应用的文件访问权限:

  • 临时关闭SELinux测试(仅用于排查):
    adb shell setenforce 0
    
  • 若问题解决,需联系系统开发者添加SELinux规则,允许应用读写私有目录下的Realm文件。

4. 确保Realm实例正确关闭

所有Realm实例使用后必须关闭,避免资源泄漏导致的文件锁或权限问题。推荐使用use函数自动管理实例生命周期:

fun getConversations(): Flow<List<Conversation>> {
    return Realm.getDefaultInstance().use { realm ->
        realm.where(Conversation::class.java)
            .findAllAsync()
            .asFlow()
            .map { it.list }
    }
}

内容的提问来源于stack exchange,提问作者Abdul Hanan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 04:12:02