Android应用中C++原生库能否访问文件系统?Java如何传字符串到NDK库
问题原因排查
- 硬编码路径不可靠:不同Android版本、多用户场景下,应用私有目录的路径不是固定格式,比如Android 10+部分设备私有目录路径会有调整,硬编码的
/data/user/0/<App name>/files/otp.txt大概率会出现路径不匹配问题。 - 权限不存在限制:同应用的原生库和Java层共享同一UID,天然有权限访问应用内部私有目录,不需要额外申请权限,所以你的问题基本可以确定是路径不匹配导致的。
更优的Java到C++字符串传递方案
JNI直接传参(优先推荐)
不需要中间文件做中转,直接在JNI调用时把字符串作为参数传入原生方法,无IO开销、逻辑最稳定:
- Java层声明带字符串参数的原生方法
public native String otp(String inputStr);
- C层对应的JNI方法直接接收字符串参数,转换为C/C可用的字符串格式即可
extern "C" JNIEXPORT jstring JNICALL Java_你的包名_对应Activity名_otp(JNIEnv *env, jobject thiz, jstring input_str) { // jstring转std::string const char *c_str = env->GetStringUTFChars(input_str, nullptr); std::string otp_content(c_str); env->ReleaseStringUTFChars(input_str, c_str); // 此处执行原有业务逻辑 // 若需要返回结果,转换为jstring返回即可 return env->NewStringUTF(otp_content.c_str()); }
原生层全局缓存方案
如果你现有C代码的otp()函数签名已经固定、无法新增参数,可以在应用启动时先调用一个专属初始化JNI方法,把字符串传到C层存入全局变量,后续otp()函数直接读取全局变量即可:
#include <string> // 全局缓存传入的字符串 static std::string g_otp_str; // 初始化用的JNI方法,Java层启动时调用传入目标字符串 extern "C" JNIEXPORT void JNICALL Java_你的包名_对应Activity名_setOtpContent(JNIEnv *env, jobject thiz, jstring input_str) { const char *c_str = env->GetStringUTFChars(input_str, nullptr); g_otp_str = std::string(c_str); env->ReleaseStringUTFChars(input_str, c_str); } // 原有otp函数直接读全局变量 const char* otp() { return g_otp_str.c_str(); }
修复原文件方案
如果一定要用文件中转的方案,不要硬编码路径:Java层调用getFilesDir().getAbsolutePath()拿到当前设备的正确私有目录路径,拼接文件名后通过JNI传入C++层,替换掉编译时硬编码的WORD_FILE宏即可。
内容的提问来源于stack exchange,提问作者Shin
相关产品推荐
相关产品推荐

