Android资产、C语言、JNI

8

如何通过JNI从C访问Android资源,例如.txt文件?

我尝试使用"file:///android_asset/myFile.txt"和本地的"myFile.txt",并在jni文件夹中复制了一个myFile.txt的副本与C实现文件。


请查看此答案: https://dev59.com/RWkv5IYBdhLWcg3wtS8N - Derzu
2个回答

12

关于资源文件的问题在于你不能像访问普通文件一样直接获取它们,这是因为资源文件直接从 APK 中读取,安装后不会解压到指定文件夹。

从 Android 2.3 开始,提供了 C API 来访问资源。可以查看 <android/asset_manager.h><android/native_activity.h> 中的 assetManager 字段。尽管我从未使用过这个功能,但我不确定如果不使用原生活动是否可以使用此资源管理器 API。总之,在 Android 2.2 及以下版本中无法使用该 API。

所以我有三个选项:

  • 将资源文件提取到某个目录中,但这将占用额外的空间。
  • 使用类似 libzip 的库(打包和)在纯 C 中从 APK 中读取资源文件。
  • 或者,为避免捆绑额外的库,我的个人偏好是使用 JNI 从 Java 的 InputStream 对象中读取数据。虽然需要些代码,但效果非常好。

2
@olivierg,你有没有使用JNI从AssetManager中使用Inputstream的示例? - markov00

3
如果您无法使用AssetManager C API,因为需要调用需要文件名的C/C++库,则可以使用原始资源代替。
唯一的缺点是需要在运行时将其复制到应用程序的数据(临时)目录中。
将要从本地代码读取的文件放置在res/raw目录中。
在运行时,将文件从res/raw/myfile.xml复制到data目录中:
File dstDir = getDir("data", Context.MODE_PRIVATE);
File myFile = new File(dstDir, "tmp_myfile.xml");
FileMgr.copyResource(getResources(), R.raw.my_file, myFile);

现在要传递给本地代码的文件名是myFile.getAbsolutePath()

copyResource (rsrcId, dstFile)

复制资源(rsrcId)到目标文件(dstFile)

public static File copyResource (Resources r, int rsrcId, File dstFile) throws IOException
{
    // load cascade file from application resources
    InputStream is =  r.openRawResource(rsrcId);
    FileOutputStream os = new FileOutputStream(dstFile);

    byte[] buffer = new byte[4096];
    int bytesRead;
    while ((bytesRead = is.read(buffer)) != -1)
        os.write(buffer, 0, bytesRead);
    is.close();
    os.close();

    return dstFile;
}

很抱歉让这个线程在很长一段时间后重新启动。我从“asset”文件夹中读取了一个文件,然后使用“FileOutputStream”写入该文件。我的问题是,“FileOutputStream”保存的文件路径是什么。 - Saad Saadi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接