如何将sqlite插件文件(.so)添加到Android应用程序?

问题描述 投票:0回答:1

我正在开发一个Android应用程序,需要加载一个自编译的sqlite插件(libsimple)。编译后的插件是一个.so文件。

sqlite-android可以加载此类文件作为插件。但我是 Android 开发新手,不知道如何正确加载文件。

目前,我将编译好的插件放入 jniLibs 中。

app/
├─ src/
│  ├─ main/
│  │  ├─ jniLibs/
│  │  │  ├─ x86_64/
│  │  │  │  ├─libsimple.so
│  │  │  ├─ arm64_v8a/
│  │  │  │  ├─libsimple.so

构建的 apk 确实包含这些文件。

apk-debug.apk/
├─ lib/
│  ├─ x86_64/
│  │  ├─libsimple.so
│  ├─ arm64_v8a/
│  │  ├─libsimple.so

代码中定义的路径如下:

private val libsimplePath = "${context.applicationInfo.nativeLibraryDir}/libsimple.so"

但是,当使用 API 35 在 Android studio 中运行应用程序时,返回的路径如下

data/app/~~W0ZleGXEDPvGfIKN22O5Ow==/com.hal9000com.picfinder-eadN36R50XdAo86g8fxllN==/lib/x86_64/libsimple.so

下面的测试代码将返回 false。插件加载也会失败。

fun isPathReadable(path: String): Boolean {
    val file = File(path)
    return file.canRead()
}

但是当我上传 .so 文件并使用文件选择器选择它时,它将获得如下路径

/data/user/0/com.hal9000com.picfinder/cache/libsimple.so

并且插件将会工作。

质疑 ChatGPT 没有返回任何好处,我尝试添加

    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

更改为 AndroidManifest.xml,但没有任何更改。

扩展加载部分代码如下。

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)
private val db = SQLiteDatabase.openDatabase(cfg, null, null)

需要 .so 文件的路径,如 sqlite-android 源代码中所定义。

public final class SQLiteCustomExtension {

    public final String path;
    public final String entryPoint;

    /**
     * Creates a SQLite extension description.
     *
     * @param path       path to the loadable extension shared library
     *                   e.g. "/data/data/(package)/lib/libSqliteICU.so"
     * @param entryPoint extension entry point (optional)
     *                   e.g. "sqlite3_icu_init"
     */
    public SQLiteCustomExtension(String path, String entryPoint) {
        if (path == null) {
            throw new IllegalArgumentException("null path");
        }
        this.path = path;
        this.entryPoint = entryPoint;
    }
}
android
1个回答
0
投票

找到了解决方案,.so文件应该放在assets文件夹中,并在应用程序启动时复制。

fun copyAssetToInternalStorage(context: Context, assetFileName: String,saveName:String): String? {
    val file = File(context.filesDir, saveName)
    try {
        context.assets.open(assetFileName).use { inputStream ->
            FileOutputStream(file).use { outputStream ->
                inputStream.copyTo(outputStream)
            }
        }
    } catch (e: IOException) {
        e.printStackTrace()
        return null
    }
    return file.absolutePath
}

然后就可以访问该路径了。

© www.soinside.com 2019 - 2024. All rights reserved.