android常见问题之jni读取assets资源文件(附源码)

news/2025/2/15 21:42:43/
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。
/*******************************************************************************
* Function Name  : java_com_fontlose_ReadAssets_readFromAssets
* Description    : 定义:public native void  readFromAssets(AssetManager ass,String filename);
* Input          : AssetManager对象 filename资源名
* Output         : None
* Return         : None
*******************************************************************************/ 
void  Java_com_fontlose_ReadAssets_readFromAssets(JNIEnv* env,jclass tis,jobject assetManager,jstring filename)
{LOGI("ReadAssets"); AAssetManager* mgr = AAssetManager_fromJava(env, assetManager);if(mgr==NULL){LOGI(" %s","AAssetManager==NULL");return ;}/*获取文件名并打开*/jboolean iscopy;const char *mfile = (*env)->GetStringUTFChars(env, filename, &iscopy);AAsset* asset = AAssetManager_open(mgr, mfile,AASSET_MODE_UNKNOWN);(*env)->ReleaseStringUTFChars(env, filename, mfile);if(asset==NULL){LOGI(" %s","asset==NULL");return ;}/*获取文件大小*/off_t bufferSize = AAsset_getLength(asset);LOGI("file size         : %d\n",bufferSize);char *buffer=(char *)malloc(bufferSize+1);buffer[bufferSize]=0;int numBytesRead = AAsset_read(asset, buffer, bufferSize);LOGI(": %s",buffer);free(buffer);/*关闭文件*/AAsset_close(asset);
}

在应用程序内使用定义和使用如下
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等。
/*******************************************************************************
* Function Name  : java_com_fontlose_ReadAssets_readFromAssetsLibzip
* Description    : 定义:public native void  readFromAssetsLibzip(String apkpath,String filename);
* Input          : apkpath路径 filename 资源名
* Output         : None
* Return         : None
*******************************************************************************/ 
void  Java_com_fontlose_ReadAssets_readFromAssetsLibzip(JNIEnv* env,jclass tis,jstring assetpath,jstring filename)
{LOGI("ReadAssets"); int i=0;jboolean iscopy;const char *mpath = (*env)->GetStringUTFChars(env, assetpath, &iscopy);struct zip* apkArchive=zip_open(mpath, 0, NULL);;(*env)->ReleaseStringUTFChars(env, filename, mpath);struct zip_stat fstat;zip_stat_init(&fstat);int numFiles = zip_get_num_files(apkArchive);LOGI("File numFiles %i \n",numFiles);for (i=0; i<numFiles; i++) {const char* name = zip_get_name(apkArchive, i, 0);if (name == NULL) {LOGE("Error reading zip file name at index %i : %s", zip_strerror(apkArchive));return;}zip_stat(apkArchive,name,0,&fstat);LOGI("File %i:%s Size1: %d Size2: %d", i,fstat.name,fstat.size ,fstat.comp_size)  ;}const char *fname = (*env)->GetStringUTFChars(env, filename, &iscopy);struct zip_file* file = zip_fopen(apkArchive, fname, 0);if (!file) {LOGE("Error opening %s from APK", fname);return;}zip_stat(apkArchive,fname,0,&fstat);(*env)->ReleaseStringUTFChars(env, filename, fname);char *buffer=(char *)malloc(fstat.size+1);buffer[fstat.size]=0;int numBytesRead =  zip_fread(file, buffer,fstat.size);;LOGI(": %s\n",buffer);free(buffer);zip_fclose(file);zip_close(apkArchive);
}


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

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如下
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)


log.txt内容如下

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


jni工程和测试工程源码我已上传到我的资源 有兴趣的童鞋可以下来看下

http://d.download.csdn.net/down/3518697/fontlose





http://www.ppmy.cn/news/228733.html

相关文章

STM32 DAC 输出正弦波、三角波、方波

DAC可以将数字信号转换成模拟信号&#xff0c;在嵌入式系统开发中运用的十分广泛。在STM32实际运用中&#xff0c;可直接将数值映射成端口的电压值&#xff0c;通过大量的采样点输出&#xff0c;可达到输出指定波形的目的。 1、设置系统时钟&#xff08;Clock&#xff09; 2、…

RT 3570 wifi 移植手册

作者&#xff1a;宋老师,华清远见嵌入式学院讲师。 开发环境&#xff1a; 硬件平台&#xff1a;pv210开发板 主机环境&#xff1a;Ubuntu10.04 Linux内核&#xff1a;Linux-2.6.35 无线USB网卡 腾达 型号&#xff1a;W311M WIFI方案&#xff1a;RT5370 驱动下载地址 腾…

Canon iR3570扫描方案

本文出自Simmy的个人blog&#xff1a;西米在线 http://simmyonline.com/archives/604.html 新收购进来的公司那边有一部Canon iR3570的多功能打印机&#xff0c;以前用户都是使用Adobe Photoshop来配合使用其扫描的功能&#xff0c;而且用的是盗版&#xff0c;而我们公司规定…

rpmbuild编译安装制作rpm包

什么是rpm包? rpm 相当于windows中的安装文件,它会自动处理软件包之间的依赖关系。 rpm优点: 包管理系统简单,通过几个命令就可以实现包的安装、升级、卸载。 安装速度比源码包快的多。 缺点: 经过编译,不能看到源代码,功能选择不如源码灵活。依赖性强。 首先说一下流程…

行为型设计模式03-观察者模式

&#x1f9d1;‍&#x1f4bb;作者&#xff1a;猫十二懿 &#x1f3e1;账号&#xff1a;CSDN 、个人博客 、Github &#x1f38a;公众号&#xff1a;猫十二懿 观察者模式 1、观察者模式介绍 观察者模式是一种行为型设计模式&#xff0c;也被称为发布-订阅模式&#xff0c;它定…

ISATAP隧道配置与验证

ISATAP隧道配置与验证 【实验目的】 熟悉IPv6ISATAP隧道的概念。 掌握IPv6和IPv4共存的实现方法。 掌握IPv6 ISATAP地址编址规则。 掌握IPv6 ISATAP隧道的配置。 验证配置。 【实验拓扑】 设备参数如下表所示。 设备 接口 IP地址 子网掩码 默认网关 R1 S0/0 192.…

天玑720和天玑800u哪个好-联发科天玑720和天玑800跑分对比

以搭载天玑720的realme V5为测评&#xff1a;安兔兔跑分为301380分&#xff0c; Geekbench 4中它的单核成绩为2493分&#xff0c;多核成绩为6555分; 以搭载天玑800的OPPO A92s为测评&#xff1a;安兔兔跑分为296455分&#xff0c; Geekbench 5中它的单核成绩为2504分&#xff…

Serv-U FTP服务器安装教程

公司要搭建个FTP服务器&#xff0c;查了下&#xff0c;windows2008R2系统带ftp服务器&#xff0c;但是不好有用&#xff0c;serv-u比较傻瓜式操作&#xff0c;而且权限都是勾选的&#xff0c;找了个绿色版百度网盘 提取码&#xff1a;yvwz 环境&#xff1a;windows2008R2 1执行…