zoukankan      html  css  js  c++  java
  • [AndroidTips]jni读取assets资源文件

    http://blog.csdn.net/fontlose/article/details/6686161

    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







  • 相关阅读:
    数据分析三剑客 numpy,oandas,matplotlib(2)
    数据分析三剑客 numpy,oandas,matplotlib
    爬虫 crawlSpider 分布式 增量式 提高效率
    RestTemplate:带 header 的 get 请求
    Java:md5 摘要
    Java:Base64 编码
    Java:将字符串转换为枚举
    RestTemplate:使用 Map 传递参数
    Spring cloud:网关-Zuul路由
    Spring cloud:熔断器-Hystrix Dashboard
  • 原文地址:https://www.cnblogs.com/androidme/p/2389449.html
Copyright © 2011-2022 走看看