
在 Android NDK 开发中,可通过 JNI 将应用专属目录路径(如 /data/data//files/)从 Java/Kotlin 层传递至 C 代码,再用 fopen() 等标准 C 文件 API 直接操作,无需额外权限。
在 android ndk 开发中,可通过 jni 将应用专属目录路径(如 `/data/data/
Android 应用的内部存储路径(如 context.filesDir)默认指向 /data/data/<package-name>/files/</package-name>,该路径对应用私有、无需声明任何运行时或清单权限。但由于 C 代码运行在 Native 层,无法直接访问 Java 的 Context 对象,因此必须通过 JNI 显式传入路径字符串。
实现步骤如下:
-
在 Kotlin/Java 中获取并传递路径
在 Activity 或 Application 类中,调用getFilesDir().absolutePath获取完整路径,并作为String参数传入 JNI 函数:external fun readFile(filePath: String) override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) val fullPath = File(filesDir, "config.dat").absolutePath readFile(fullPath) // 传入 C 函数 } -
在 C 中接收并使用路径
使用GetStringUTFChars安全转换 Java 字符串为 C 风格const char*,完成文件操作后务必调用ReleaseStringUTFChars释放资源,避免内存泄漏:#include <jni.h> #include <stdio.h> #include <stdlib.h> JNIEXPORT void JNICALL Java_com_example_hellojni_HelloJni_readFile(JNIEnv *env, jobject thiz, jstring filePath) { const char *path = (*env)->GetStringUTFChars(env, filePath, NULL); if (path == NULL) { // 处理 OOM 异常(JNI 字符串转换失败) return; } FILE *fp = fopen(path, "rb"); if (fp != NULL) { // 示例:读取前 1024 字节 uint8_t buffer[1024]; size_t len = fread(buffer, 1, sizeof(buffer), fp); fclose(fp); // ... 处理数据 } else { // 日志建议:使用 __android_log_print 或自定义回调上报错误 } (*env)->ReleaseStringUTFChars(env, filePath, path); // 关键:必须释放! }</stdlib.h></stdio.h></jni.h>
注意事项:
- ✅ 路径必须为绝对路径(如
/data/data/com.example.app/files/config.dat),相对路径在 Native 层行为不可靠; - ✅
GetStringUTFChars返回的是 UTF-8 编码的只读指针,不可修改,且需配对ReleaseStringUTFChars; - ⚠️ 不要缓存
jstring或其转换后的const char*跨 JNI 调用——每次调用都应独立转换与释放; - ? 应用专属目录天然沙箱隔离,无需
<uses-permission></uses-permission>声明,但切勿将此路径硬编码或暴露给外部应用; - ? 如需频繁访问,可考虑在首次调用时将
filesDir路径缓存为全局char*(需手动管理生命周期),但需确保线程安全与进程存活期匹配。
通过这一模式,C/C++ 模块即可无缝集成 Android 应用的内部文件系统,兼顾安全性、简洁性与原生性能。











