设为首页 加入收藏

TOP

Android: 在native中访问assets全解析(一)
2019-09-01 23:13:50 】 浏览:75
Tags:Android: native 访问 assets 解析

本文总结在Android Native C++开发中访问APK中的assets资源的方法

在CMake中添加相关NDK LIB的 依赖

因为我们接下来用到的一些函数实现在NDK库libandroid.so中,因此我们直接在CMakeList.txt中添加对其依赖即可:

target_link_libraries( # Specifies the target library.
                       native-lib
                       #lib to link
                       android
                       # other libs
                       )

如果没有添加此依赖,显然会提示undefined reference错误,比如:

error: undefined reference to 'AAssetManager_fromJava'
error: undefined reference to 'AAssetManager_open'
error: undefined reference to 'AAsset_getLength'
error: undefined reference to 'AAsset_getBuffer'
error: undefined reference to 'AAsset_close'
error: undefined reference to 'AAssetManager_open'
error: undefined reference to 'AAsset_getLength'
error: undefined reference to 'AAsset_openFileDescriptor'
error: undefined reference to 'AAsset_close'
error: undefined reference to 'AAssetManager_openDir'
error: undefined reference to 'AAssetDir_getNextFileName'
error: undefined reference to 'AAssetManager_open'

获得AssetManager

在Java中,我们可以通过Context.getAssets()轻松获得AssetManager。在NDK中,提供了AAssetManager_fromJava来获得Native中对应的AAssetManager。顾名思义,fromJava,肯定是要从Java层获取了,也即意味着要通过JNI来获得。代码如下:

/***code in Java, such as MainActivity.java***/

//decale the jni func
public native void setNativeAssetManager(AssetManager assetManager);

//call it, such as during Activity.onCreate()
setNativeAssetManager(getAssets());

/***end of java***/


/***code in native c++***/
extern "C"
JNIEXPORT void JNICALL
Java_willhua_androidstudioopencl_MainActivity_setNativeAssetManager(
    JNIEnv *env, 
    jobject instance,
    jobject assetManager) {
            AAssetManager *nativeasset = AAssetManager_fromJava(env, assetManager);
            
            //the use of nativeasset
}

下面所有的代码都是在Java_willhua_androidstudioopencl_MainActivity_setNativeAssetManager内实现。

访问assets下的文件

我们知道,assets文件夹下面是可以有子文件夹的,因为,下面我以读取图片为例,介绍各种情况的访问方法。例子中用到OpenCV的相关方法,在此不介绍,自行了解。
测试用assets文件夹目录:
iutTBt.jpg

已知完整路径的访问

如果我们已经知道assets下某个文件的完整路径,比如"sz.jpg","dir/cs.jpg",那么我们可以直接把这个路径传给AAssetManager_open来获得AAsset.

//open file
AAsset *assetFile = AAssetManager_open(nativeasset, "sz.jpg", AASSET_MODE_BUFFER);
//this will also be ok 
//AAsset *assetFile = AAssetManager_open(nativeasset, "dir/cs.jpg", AASSET_MODE_BUFFER);
//get file length
size_t fileLength = AAsset_getLength(assetFile);
char *dataBuffer2 = (char *) malloc(fileLength);
//read file data
AAsset_read(assetFile, dataBuffer2, fileLength);
//the data has been copied to dataBuffer2, so , close it
AAsset_close(assetFile);

//decode the file data to cv::Mat 
std::vector<char> vec2(dataBuffer2, dataBuffer2 + fileLength);
cv::Mat mat2 = cv::imdecode(vec2, CV_LOAD_IMAGE_COLOR);
LOGD("asset file %d x %d  %d", mat2.cols, mat2.rows, mat2.channels());

//free malloc
free(dataBuffer2);

获取文件下的名字并访问之

如果我们只知道文件夹的名字,但并不知道文件夹下面有哪些具体文件,比如我们只知道有个dir文件夹,但不知道下面的具体情况。那么我们可以使用AAssetDir_getNextFileName来获取文件夹的文件名。但是有个问题,这个方法只能获得文件夹下的文件名,而无法获得子文件夹,有哪位知道的请告知。
注意AAssetDir_getNextFileName只返回文件名,而不是该文件的完整路径,比如只会返回cs.jpg,而不是dir/cs.jpg,所以如果直接把AAssetDir_getNextFileName的返回结果传给AAssetManager_open会读取不到正确的文件,返回NULL.

AAssetDir *assetDir = AAssetManager_openDir(nativeasset, "dir");
const char *filename = AAssetDir_getNextFileName(assetDir);
while (filename != NULL){
    char fullname[1024];
    sp
首页 上一页 1 2 3 下一页 尾页 1/3/3
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇安卓投屏助手(B1358)之辅助调试 下一篇Android内嵌PDF预览

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目