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

如何在Android应用中加载自定义编译的SQLite .so插件?

Android加载SQLite插件libsimple.so失败的解决方案

问题背景

开发Android应用时,使用sqlite-android加载自行编译的libsimple.so插件,将so文件放置在jniLibs对应ABI目录下,APK打包后确实包含该文件,但通过applicationInfo.nativeLibraryDir获取路径后,调用File.canRead()返回false,插件加载失败;但将so文件复制到应用cache目录后可正常加载。

解决方案

1. 跳过File.canRead()判断,直接尝试加载

Android 11(API 30)及以上版本中,应用nativeLibraryDir目录下的so文件受系统权限限制,File API无法直接读取,但系统动态链接器(dlopen)可正常加载这些库。无需用canRead()做前置判断,直接执行加载逻辑即可。

修改后的加载代码:

import io.requery.android.database.sqlite.SQLiteDatabase
import io.requery.android.database.sqlite.SQLiteDatabaseConfiguration
import io.requery.android.database.sqlite.SQLiteCustomExtension

private val libsimplePath = "${context.applicationInfo.nativeLibraryDir}/libsimple.so"
private val cfg = SQLiteDatabaseConfiguration(":memory:", SQLiteDatabase.OPEN_READWRITE)
val ext = SQLiteCustomExtension(libsimplePath, null)
cfg.customExtensions.add(ext)
try {
    val db = SQLiteDatabase.openDatabase(cfg, null, null)
    // 加载成功,执行后续业务逻辑
} catch (e: Exception) {
    // 捕获异常并排查具体原因
    e.printStackTrace()
}

2. 将jniLibs中的so复制到Cache目录后加载

若直接加载nativeLibraryDir下的so仍有问题,可将APK中打包的so复制到应用cache目录,再加载该路径的so(已验证此方法可行)。

实现代码示例:

private fun getLibsimplePath(context: Context): String {
    val cacheDir = context.cacheDir
    val targetFile = File(cacheDir, "libsimple.so")
    
    if (!targetFile.exists()) {
        // 从APK的native库目录复制文件到cache
        val sourcePath = "${context.applicationInfo.nativeLibraryDir}/libsimple.so"
        val sourceFile = File(sourcePath)
        sourceFile.copyTo(targetFile, overwrite = true)
    }
    
    return targetFile.absolutePath
}

// 使用处理后的路径加载插件
private val libsimplePath = getLibsimplePath(context)
private val cfg = SQLiteDatabaseConfiguration(":memory:", SQLiteDatabase.OPEN_READWRITE)
val ext = SQLiteCustomExtension(libsimplePath, null)
cfg.customExtensions.add(ext)
val db = SQLiteDatabase.openDatabase(cfg, null, null)

3. 验证so文件的ABI兼容性

确保编译的libsimple.so的ABI与sqlite-android支持的ABI完全匹配:

  • 确认sqlite-android支持的ABI列表(通常包含armeabi-v7a、arm64-v8a、x86、x86_64)
  • 检查libsimple.so是针对对应ABI编译的,避免跨ABI加载导致失败

4. 更新sqlite-android到最新版本

使用最新版本的sqlite-android库,新版本通常会修复高API版本下的兼容性问题。

原因说明

Android 11及以上版本强化了应用私有目录权限,nativeLibraryDir下的so文件属于系统管理的应用库文件,普通File API无法直接读取,但系统动态链接器有权限加载这些库;而cache目录属于应用可完全控制的私有目录,File API和动态链接器都能正常访问。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 11:03:24