源自:http://www.rosoo.net/a/201112/15459.html

assets目录底下的文件会被打包到一个apk文件里,这些资源在安装时他们并没被解压,使用时是直接从apk中读取的。这里介绍下怎么在jni内使用 ndk自带api的接口函数读取assets资源文件,和libzip库函数的使用,可以用来读创建修改压缩文档,这里也是以读取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    : 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
  9. ,jobject assetManager,jstring filename)
  10. {
  11. LOGI("ReadAssets");
  12. AAssetManager* mgr = AAssetManager_fromJava(env, assetManager);
  13. if(mgr==NULL)
  14. {
  15. LOGI(" %s","AAssetManager==NULL");
  16. return ;
  17. }
  18. /*获取文件名并打开*/
  19. jboolean iscopy;
  20. const char *mfile = (*env)->GetStringUTFChars(env, filename, &iscopy);
  21. AAsset* asset = AAssetManager_open(mgr, mfile,AASSET_MODE_UNKNOWN);
  22. (*env)->ReleaseStringUTFChars(env, filename, mfile);
  23. if(asset==NULL)
  24. {
  25. LOGI(" %s","asset==NULL");
  26. return ;
  27. }
  28. /*获取文件大小*/
  29. off_t bufferSize = AAsset_getLength(asset);
  30. LOGI("file size         : %d\n",bufferSize);
  31. char *buffer=(char *)malloc(bufferSize+1);
  32. buffer[bufferSize]=0;
  33. int numBytesRead = AAsset_read(asset, buffer, bufferSize);
  34. LOGI(": %s",buffer);
  35. free(buffer);
  36. /*关闭文件*/
  37. AAsset_close(asset);
  38. }

在应用程序内使用定义和使用如下

  1. public native void  readFromAssets(AssetManager ass,String filename);

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

在应用程序内使用定义和使用如下

  1. public native void  readFromAssetsLibzip(String apkpath,String filename);

readFromAssetsLibzip(getPackageResourcePath(),"assets/log.txt");

logcat测试结果

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): 。。。。。。。。。。。。。。。。
上面例子使用android.mk如下

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

JNI读取assets资源文件的更多相关文章

  1. QLGame 2d Engine Android端环境搭建(通过jni读取assets目录的文件)

    QLGame 2d Engine win端已经实现了一个动物的动画了,初步的东西已经完成,考虑在Android端也实现这些基本的东西,这样跨平台的引擎也就实现了! 要在Android下编程,首先要实现 ...

  2. Android学习--Assets资源文件读取及AssetManager介绍

    APK安装过程        复制APK安装包到data/app目录下,解压并扫描安装包,把dex文件(Dalvik字节码)保存到dalvik-cache目录,并data/data目录下创建对应的应用 ...

  3. Hadoop集群上使用JNI,调用资源文件

    hadoop是基于java的数据计算平台,引入第三方库,例如C语言实现的开发包将会大大增强数据分析的效率和能力. 通常在是用一些工具的时候都要用到一些配置文件.资源文件等.接下来,借一个例子来说明ha ...

  4. SpringBoot读取静态资源文件

    ClassPathResource resource = new ClassPathResource(publicKeyCer); File file = null; try { file = res ...

  5. Spring读取properties资源文件

    我们知道可以通过读取资源文件流后加载到Properties对象,再使用该对象方法来获取资源文件.现在介绍下利用Spring内置对象来读取资源文件. 系统启动时加载资源文件链路:web.xml --&g ...

  6. SpringBoot打成jar包后无法读取resources资源文件

    在项目中做了一个支付功能, 需要引入第三方渠道的配置文件config.xml用来初始化文件证书, 将配置文件 config.xml 放到 resources 资源目录下. 本地开发环境下能正常读取该文 ...

  7. 在服务端中,读取properties资源文件中的数据

    1.获取到资源的路径 2.读取数据 //properties文件对象 Properties properties = new Properties(); //通过HttpServletRequest ...

  8. Java项目读取resources资源文件路径那点事

    今天在Java程序中读取resources资源下的文件,由于对Java结构了解不透彻,遇到很多坑.正常在Java工程中读取某路径下的文件时,可以采用绝对路径和相对路径,绝对路径没什么好说的,相对路径, ...

  9. win10 uwp 读取resw资源文件

    ResourceContext resourceContext = ResourceContext.GetForViewIndependentUse(); ResourceMap resourceMa ...

随机推荐

  1. 数据的增量更新之EXISTS

    有时候需要实现是数据的增量更新,因为更新全量会带来时间跟数据库资源的浪费,还有可能是数据出现冗余,所以需要使用增量数据同步,下面是一个数据增量同步的小实例. ---drop table A CREAT ...

  2. Redis 三:存储类型之字符串

    .赋值单个: [赋值多个:mset a b c ] .取值单个: get a [取值多个:mget a b c] .数字递增 incr a 在a的基础上+,那就是返回101 如果预先的值为0,那么返回 ...

  3. linux设备驱动模型

    尽管LDD3中说对多数程序员掌握设备驱动模型不是必要的,但对于嵌入式Linux的底层程序员而言,对设备驱动模型的学习非常重要. Linux设备模型的目的:为内核建立一个统一的设备模型,从而又一个对系统 ...

  4. UML类图总结

    前言 类图和序列图是UML中最常用的两种Diagram.我将做详细的总结.在许多书中,或者网站中,在介绍一个系统的子系统的设计时,很多时候,都是给出简单的类图来简述构成子系统的类之间的关系.这足以说明 ...

  5. Sublime text 取消记住上一次打开的,这功能太墨迹了!

    比较恨,这sublime text的配置全部都是配置文件. 选择菜单:Preferences->Settings-User,增加配置项 //热退出,其实实现一种模拟没有退出的状态,当程序再次启动 ...

  6. BZOJ 3875: [Ahoi2014]骑士游戏 dp+spfa

    题目链接: 题目 3875: [Ahoi2014]骑士游戏 Time Limit: 30 Sec Memory Limit: 256 MB 问题描述 [故事背景] 长期的宅男生活中,JYY又挖掘出了一 ...

  7. Codeforces Round #360 (Div. 2) D. Remainders Game 中国剩余定理

    题目链接: 题目 D. Remainders Game time limit per test 1 second memory limit per test 256 megabytes 问题描述 To ...

  8. ExtJS4.2学习(21)动态菜单与表格数据展示操作总结篇2

    运行效果: 此文介绍了根据操作左侧菜单在右面板展示相应内容. 一.主页 先看一下跳转主页的方式:由在webapp根目录下的index.jsp跳转至demo的index.jsp 下面是demo的inde ...

  9. CSS透明属性详解代码

    透明往往能产生不错的网页视觉效果,先奉上兼容主流浏览器的CSS透明代码: 代码如下: .transparent_class { filter:alpha(opacity=50); -moz-opaci ...

  10. 【HDOJ】【2089】不要62

    数位DP cxlove基础数位DP第一题 用容斥把所有的不吉利数字去掉就得到吉利数字的数量= =(满足区间减法) //HDOJ 2089 #include<cmath> #include& ...