• android 资源管理之 Asset/raw 2


      Android 中对资源的管理基本会涉及到 asset 、 raw 、私有目录(/data/data/package) 以及 /sdcard,对于后2种,一般都可以采用基本的文件操作来管理,对于asset 、raw 的管理有很多人会讨论到,基本上有如下两种

    raw

    Resources res = getResources();
    InputStream myfile = res.openRawResource(R.raw.文件名);//文件名不加后缀

    assets 

    1 AssetManager assetManager = getAssets();
    2 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 http://www.cnblogs.com/yaozhongxiao/archive/2013/04/21/3034260.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。

    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.    LOGI("ReadAssets");  
    11.    AAssetManager* mgr = AAssetManager_fromJava(env, assetManager); 
    12.    if(mgr==NULL) 
    13.    { 
    14.       LOGI(" %s","AAssetManager==NULL"); 
    15.       return ; 
    16.    } 
    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); 

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

    1. 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等。

    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.    LOGI("ReadAssets");  
    11.   int i=0; 
    12.    jboolean iscopy; 
    13.    const char *mpath = (*env)->GetStringUTFChars(env, assetpath, &iscopy); 
    14.    struct zip* apkArchive=zip_open(mpath, 0, NULL);; 
    15.    (*env)->ReleaseStringUTFChars(env, filename, mpath); 
    16.  
    17.    struct zip_stat fstat; 
    18.    zip_stat_init(&fstat); 
    19.  
    20.    int numFiles = zip_get_num_files(apkArchive); 
    21.    LOGI("File numFiles %i \n",numFiles); 
    22.    for (i=0; i<numFiles; i++) { 
    23.      const char* name = zip_get_name(apkArchive, i, 0); 
    24.      
    25.      if (name == NULL) { 
    26.       LOGE("Error reading zip file name at index %i : %s", zip_strerror(apkArchive)); 
    27.       return
    28.     } 
    29.     
    30.     zip_stat(apkArchive,name,0,&fstat); 
    31.     LOGI("File %i:%s Size1: %d Size2: %d", i,fstat.name,fstat.size ,fstat.comp_size)  ; 
    32.    } 
    33.  
    34.    const char *fname = (*env)->GetStringUTFChars(env, filename, &iscopy); 
    35.    struct zip_file* file = zip_fopen(apkArchive, fname, 0); 
    36.   
    37.    if (!file) { 
    38.      LOGE("Error opening %s from APK", fname); 
    39.      return
    40.     } 
    41.  
    42.    zip_stat(apkArchive,fname,0,&fstat); 
    43.    (*env)->ReleaseStringUTFChars(env, filename, fname); 
    44.    char *buffer=(char *)malloc(fstat.size+1); 
    45.    buffer[fstat.size]=0; 
    46.    int numBytesRead =  zip_fread(file, buffer,fstat.size);; 
    47.    LOGI(": %s\n",buffer); 
    48.    free(buffer); 
    49.    zip_fclose(file); 
    50.    zip_close(apkArchive); 

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

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

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

    上面例子使用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) 

     

      

  • 相关阅读:
    MongoDB初期学习
    springboot+camunda实现工作流1
    一文带你深入理解位运算
    【林超所长】学科01:熵与热力学重要模型
    PM常用的讨论社区及牛人帖子
    C# 2.0 的特性 总结
    小脚本解决生活问题
    Domain Adaption 之 TCA等算法
    强化学习ddpg算法
    bindkey用法
  • 原文地址:https://www.cnblogs.com/yaozhongxiao/p/3057364.html
Copyright © 2020-2023  润新知