JNI读取安卓asset下的文件需要使用以下接口。
#include <android/asset_manager_jni.h>
#include <android/asset_manager.h>
对于错误undefined reference to AAssetManager_fromJava
1.使用 Android.mk ,添加LOCAL_LDLIBS :+= -landroid
解决。
1.JAVA层传递AssetManager
对象
从java端使用getAssets()
得到一个JAVA端的AAssetManager
对象,通过JNI调用传递到C++端。
这里要注意,生成的对象名称是有点特别的:
比如我的原型是:
public class JAVA2C {
public native static void BrawlStars_Init_Ast(AssetManager assetManager, String strDir);
}
在com.hgy413.ndkdemo包下,它自动生成的函数是:
extern "C"
JNIEXPORT void JNICALL
Java_com_hgy413_ndkdemo_JAVA2C_BrawlStars_1Init_1Ast(JNIEnv *env, jclass type, jobject assetManager,
jstring strDir_) {
AAssetManager *pAsm = AAssetManager_fromJava(env, assetManager);
}
注意1Init_1Ast
。
MainActivity中调用BrawlStars_Init_Ast(getAssets(),"assets/brawlStars");
传递到C++层即可。
2.使用AAssetManager_open方法打开文件
这里要特别注意,如果打开的是asserts/bs/skins.csv
,那么传入AAssetManager_open的是bs/skins.csv
,也就是asserts/
不能加上,否则会打开失败。
单文件方式:
AAsset* asset = AAssetManager_open(m_pAsm, strPath.c_str(), AASSET_MODE_UNKNOWN);//根据文件名打开资源文件
if (NULL != asset)
{
off_t bufSize = AAsset_getLength(asset);
char *pBuf = (char *) malloc(bufSize + 1);
memset(pBuf, 0, bufSize + 1);
int iRealRead = AAsset_read(asset, pBuf, bufSize);
// 读取操作
free(pBuf);
AAsset_close(asset);
}
else
{
MyLOGE("读取%s失败",strPath.c_str());
}
文件夹遍历子文件列表:
AAssetDir *assetDir = AAssetManager_openDir(m_pAsm, strDir.c_str());
if (NULL != assetDir)
{
const char* cOpen = AAssetDir_getNextFileName(assetDir);
while (NULL != cOpen)
{
// 转成全路径
std::string strOpen = cOpen;
std::string strFullOpen = strDir + "/";
strFullOpen += strOpen;
// todo.
cOpen = AAssetDir_getNextFileName(assetDir);
}
AAssetDir_close(assetDir);
}
参考:
https://blog.csdn.net/csdn49532/article/details/50524342
https://androidcookie.com/aassetmanager_fromjava.html
https://www.cnblogs.com/willhua/p/9692529.html
https://www.cnblogs.com/willhua/p/9692529.html