android 资源管理之 Asset/raw 2
2013-05-03 19:48
316 查看
Android 中对资源的管理基本会涉及到 asset 、 raw 、私有目录(/data/data/package) 以及 /sdcard,对于后2种,一般都可以采用基本的文件操作来管理,对于asset 、raw 的管理有很多人会讨论到,基本上有如下两种
raw
assets
而有好学者也会研究通过流(stream) 或者 natvie code (c code)来管理,
为什么对asset 、raw目录下的资源管理会如此复杂,为什么对asset raw目录下资源有大小的限制?
其实 apk文件就是一个压缩包,通过把后缀名字 ××.apk --> **.rar 可以看到打包好的apk应用的目录结构,其中assets就是打包前的assets资源目录,raw目录没有发现?打开/res/ 目录及就发现,就在那里!这可能就是raw/assets的区别的根源吧(android 资源管理之 Asset/raw 1 /article/5095335.html )
从上面对比apk目录结构和应用安装好之后在应用的私有目录存在的文件信息,我们发现lib已经存在于应用的私有目录下面,那assets去哪里了呢?
如果,我们仔细观察下,就可以发现,打包成apk并在手机上安装之后,该应用在手机上会存在如下几个地发,
1)××.apk 文件放在了/data/app/目录下
2)/data/system/packages.xml 中增加了条记录
3)/data/data/packagename/, 下增加了个apk使用到的私有数据
assets是不是偷懒了,assets还存在/data/app/××.apk里面,没有到私有目录下面呢? 是的,就是这样
所以,如果是读取外存设备比如SD卡上的东西,当然是可以的,路径就是/SDCARD/ ,当然对 /data/data/用户数据也是OK的。
那么C语言要读取android上的资源文件比如说assets或者是raw的文件的话,因为这些资源其实是在APK里,而APK是个压缩文件,所以你必须读取压缩文件里的内容,用流来读取或者文件操作都是OK的,如果要通过一般的文件操作接口(fopen,...)来处理当然是可行的,但需要加入对压缩文件的处理的函数接口来读写。
其实已经有人做过这些研究功过了,也实现了这种接口:http://www.rosoo.net/a/201112/15459.html
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 : 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");
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 : 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");
上面例子使用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)
raw
Resources res = getResources(); InputStream myfile = res.openRawResource(R.raw.文件名);//文件名不加后缀
assets
AssetManager assetManager = getAssets(); InputStream inputStream = assetManager.open("xxx.txt");
而有好学者也会研究通过流(stream) 或者 natvie code (c code)来管理,
为什么对asset 、raw目录下的资源管理会如此复杂,为什么对asset raw目录下资源有大小的限制?
其实 apk文件就是一个压缩包,通过把后缀名字 ××.apk --> **.rar 可以看到打包好的apk应用的目录结构,其中assets就是打包前的assets资源目录,raw目录没有发现?打开/res/ 目录及就发现,就在那里!这可能就是raw/assets的区别的根源吧(android 资源管理之 Asset/raw 1 /article/5095335.html )
从上面对比apk目录结构和应用安装好之后在应用的私有目录存在的文件信息,我们发现lib已经存在于应用的私有目录下面,那assets去哪里了呢?
如果,我们仔细观察下,就可以发现,打包成apk并在手机上安装之后,该应用在手机上会存在如下几个地发,
1)××.apk 文件放在了/data/app/目录下
2)/data/system/packages.xml 中增加了条记录
3)/data/data/packagename/, 下增加了个apk使用到的私有数据
assets是不是偷懒了,assets还存在/data/app/××.apk里面,没有到私有目录下面呢? 是的,就是这样
所以,如果是读取外存设备比如SD卡上的东西,当然是可以的,路径就是/SDCARD/ ,当然对 /data/data/用户数据也是OK的。
那么C语言要读取android上的资源文件比如说assets或者是raw的文件的话,因为这些资源其实是在APK里,而APK是个压缩文件,所以你必须读取压缩文件里的内容,用流来读取或者文件操作都是OK的,如果要通过一般的文件操作接口(fopen,...)来处理当然是可行的,但需要加入对压缩文件的处理的函数接口来读写。
其实已经有人做过这些研究功过了,也实现了这种接口:http://www.rosoo.net/a/201112/15459.html
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 : 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");
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 : 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");
上面例子使用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)
相关文章推荐
- Android 资源管理 Asset 、Raw 和Drawable
- Android 资源管理 Asset 、Raw 和Drawable
- android 资源管理之 Asset/raw 1
- Android 资源管理 Asset 、Raw 和Drawable
- Android 资源管理 Asset 、Raw 和Drawable
- Android文件资源(raw/data/asset)的存取
- Android文件资源(raw/data/asset)的存取
- android游戏开发框架libgdx的使用(十八)—资源加载管理AssetManager的使用
- Android文件资源(raw/data/asset)的存取
- Android文件资源(raw/data/asset)的存取
- Android资源管理框架(二)AssetManager创建过程
- PHP资源管理框架Assetic简介
- Android平台的音乐资源管理与播放
- Android中asset和raw区别
- Android assets目录与raw目录存放资源的异同
- Android 三个特殊的资源目录 /res/xml /res/raw 和 /assets
- Android资源文件夹res/raw和assets的使用
- Android学习笔记(一)---一定要看的 Android 资源目录的相关知识 raw drwable values
- android中读取原始(Raw)资源
- Android 读RAW下的资源文件