jni读取assets资源文件

举报
ShaderJoy 发表于 2021/11/19 01:53:43 2021/11/19
【摘要】 assets目录底下的文件会被打包到一个apk文件里,这些资源在安装时他们并没被解压,使用时是直接从apk中读取的。这里介绍下怎么在jni内使用ndk自带api的接口函数读取assets资源文件,和libzip库函数的使用,可以用来读创建修改压缩文档,这里也是以读取apk安装包内的资源文件为例。 1 用ndk自带的接口函数读apk...
assets目录底下的文件会被打包到一个apk文件里,这些资源在安装时他们并没被解压,使用时是直接从apk中读取的。这里介绍下怎么在jni内使用ndk自带api的接口函数读取assets资源文件,和libzip库函数的使用,可以用来读创建修改压缩文档,这里也是以读取apk安装包内的资源文件为例。

1 用ndk自带的接口函数读apk包

从2.3开始提供这些接口函数,具体看头文件assert.h android/asset_manager.h android/asset_manager_jni.h,可以参考ndk自带例子中samples/native-audio/ jni/native-audio-jni.c。


  
  1. /*******************************************************************************
  2. * Function Name : java_com_fontlose_ReadAssets_readFromAssets
  3. * Description : 定义:public native void readFromAssets(AssetManager ass,String filename);
  4. * Input : AssetManager对象 filename资源名
  5. * Output : None
  6. * Return : None
  7. *******************************************************************************/
  8. void Java_com_fontlose_ReadAssets_readFromAssets(JNIEnv* env,jclass tis,jobject assetManager,jstring filename)
  9. {
  10. LOGI("ReadAssets");
  11. AAssetManager* mgr = AAssetManager_fromJava(env, assetManager);
  12. if(mgr==NULL)
  13. {
  14. LOGI(" %s","AAssetManager==NULL");
  15. return ;
  16. }
  17. /*获取文件名并打开*/
  18. jboolean iscopy;
  19. const char *mfile = (*env)->GetStringUTFChars(env, filename, &iscopy);
  20. AAsset* asset = AAssetManager_open(mgr, mfile,AASSET_MODE_UNKNOWN);
  21. (*env)->ReleaseStringUTFChars(env, filename, mfile);
  22. if(asset==NULL)
  23. {
  24. LOGI(" %s","asset==NULL");
  25. return ;
  26. }
  27. /*获取文件大小*/
  28. off_t bufferSize = AAsset_getLength(asset);
  29. LOGI("file size : %d\n",bufferSize);
  30. char *buffer=(char *)malloc(bufferSize+1);
  31. buffer[bufferSize]=0;
  32. int numBytesRead = AAsset_read(asset, buffer, bufferSize);
  33. LOGI(": %s",buffer);
  34. free(buffer);
  35. /*关闭文件*/
  36. AAsset_close(asset);
  37. }


  
  1. public native void readFromAssets(AssetManager ass,String filename);
  2. readFromAssets(getAssets(),"log.txt");
logcat测试结果
12-15 15:27:33.290: INFO/ReadAssets(3570): ReadAssets
12-15 15:27:33.290: INFO/ReadAssets(3570): file size         : 138
12-15 15:27:33.290: INFO/ReadAssets(3570): : 。。。。。。。。。。。。。。。。
12-15 15:27:33.290: INFO/ReadAssets(3570): 这个例子从jni读取assets内文件
12-15 15:27:33.290: INFO/ReadAssets(3570): 。。。。。。。。。。。。。。。。


2 使用libzip库读apk包

libzip 使用 C 库来 读创建修改压缩文档,关于libzip在andorid的移植可以参考老外做的android-ndk-assets.zip这个工程,已在NDK下可以编译了,修改下编译生成libzip.so,利用libzip.so和zip.h建立工程,使用libzip还可以读取apk包内其他压缩文件如AndroidManifest.xml布局xml等。


  
  1. void Java_com_fontlose_ReadAssets_readFromAssetsLibzip(JNIEnv* env,jclass tis,jstring assetpath,jstring filename)
  2. {
  3. LOGI("ReadAssets");
  4. int i=0;
  5. jboolean iscopy;
  6. const char *mpath = (*env)->GetStringUTFChars(env, assetpath, &iscopy);
  7. struct zip* apkArchive=zip_open(mpath, 0, NULL);;
  8. (*env)->ReleaseStringUTFChars(env, filename, mpath);
  9. struct zip_stat fstat;
  10. zip_stat_init(&fstat);
  11. int numFiles = zip_get_num_files(apkArchive);
  12. LOGI("File numFiles %i \n",numFiles);
  13. for (i=0; i<numFiles; i++) {
  14. const char* name = zip_get_name(apkArchive, i, 0);
  15. if (name == NULL) {
  16. LOGE("Error reading zip file name at index %i : %s", zip_strerror(apkArchive));
  17. return;
  18. }
  19. zip_stat(apkArchive,name,0,&fstat);
  20. LOGI("File %i:%s Size1: %d Size2: %d", i,fstat.name,fstat.size ,fstat.comp_size) ;
  21. }
  22. const char *fname = (*env)->GetStringUTFChars(env, filename, &iscopy);
  23. struct zip_file* file = zip_fopen(apkArchive, fname, 0);
  24. if (!file) {
  25. LOGE("Error opening %s from APK", fname);
  26. return;
  27. }
  28. zip_stat(apkArchive,fname,0,&fstat);
  29. (*env)->ReleaseStringUTFChars(env, filename, fname);
  30. char *buffer=(char *)malloc(fstat.size+1);
  31. buffer[fstat.size]=0;
  32. int numBytesRead = zip_fread(file, buffer,fstat.size);;
  33. LOGI(": %s\n",buffer);
  34. free(buffer);
  35. zip_fclose(file);
  36. zip_close(apkArchive);
  37. }




  
  1. public native void readFromAssetsLibzip(String apkpath,String filename);
  2. readFromAssetsLibzip(getPackageResourcePath(),"assets/log.txt");



12-15 15:28:03.430: INFO/ReadAssets(3570): ReadAssets
12-15 15:28:03.440: INFO/ReadAssets(3570): File numFiles 14
12-15 15:28:03.440: INFO/ReadAssets(3570): File 0:assets/log 2.txt Size1: 138 Size2: 55
12-15 15:28:03.440: INFO/ReadAssets(3570): File 1:assets/log.txt Size1: 138 Size2: 55
12-15 15:28:03.440: INFO/ReadAssets(3570): File 2:res/layout/main.xml Size1: 956 Size2: 337
12-15 15:28:03.440: INFO/ReadAssets(3570): File 3:AndroidManifest.xml Size1: 1348 Size2: 531
12-15 15:28:03.440: INFO/ReadAssets(3570): File 4:resources.arsc Size1: 1480 Size2: 1480
12-15 15:28:03.440: INFO/ReadAssets(3570): File 5:res/drawable-hdpi/icon.png Size1: 3966 Size2: 3966
12-15 15:28:03.440: INFO/ReadAssets(3570): File 6:res/drawable-ldpi/icon.png Size1: 1537 Size2: 1537
12-15 15:28:03.440: INFO/ReadAssets(3570): File 7:res/drawable-mdpi/icon.png Size1: 2200 Size2: 2200
12-15 15:28:03.440: INFO/ReadAssets(3570): File 8:classes.dex Size1: 3468 Size2: 1680
12-15 15:28:03.440: INFO/ReadAssets(3570): File 9:lib/armeabi/libzip.so Size1: 217246 Size2: 46140
12-15 15:28:03.440: INFO/ReadAssets(3570): File 10:lib/armeabi/libreadres.so Size1: 3820 Size2: 1779
12-15 15:28:03.440: INFO/ReadAssets(3570): File 11:META-INF/MANIFEST.MF Size1: 852 Size2: 443
12-15 15:28:03.440: INFO/ReadAssets(3570): File 12:META-INF/CERT.SF Size1: 905 Size2: 487
12-15 15:28:03.440: INFO/ReadAssets(3570): File 13:META-INF/CERT.RSA Size1: 776 Size2: 606
12-15 15:28:03.440: INFO/ReadAssets(3570): : 。。。。。。。。。。。。。。。。
12-15 15:28:03.440: INFO/ReadAssets(3570): 这个例子从jni读取assets内文件
12-15 15:28:03.440: INFO/ReadAssets(3570): 。。。。。。。。。。。。。。。。


LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE    := readres
LOCAL_SRC_FILES := readres.c
LOCAL_C_INCLUDES+= /opt/android-ndk-r5/platforms/android-9/arch-arm/usr/include
LOCAL_LDLIBS    += -L/opt/android-ndk-r5/platforms/android-9/arch-arm/usr/lib/ -llog
LOCAL_LDLIBS    += -landroid
LOCAL_LDLIBS    += -lz
LOCAL_LDLIBS    += -L$(LOCAL_PATH) -lzip
include $(BUILD_SHARED_LIBRARY)



。。。。。。。。。。。。。。。。
这个例子从jni读取assets内文件
。。。。。。。。。。。。。。。。





文章来源: panda1234lee.blog.csdn.net,作者:panda1234lee,版权归原作者所有,如需转载,请联系作者。

原文链接:panda1234lee.blog.csdn.net/article/details/11245997

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。