)android常見問題之jni讀取assets資源檔(附源碼)

來源:互聯網
上載者:User

(轉)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);}

 

在應用程式內使用定義和使用如下

<pre name="code" class="cpp">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);}

 

在應用程式內使用定義和使用如下

<pre name="code" class="cpp"><pre name="code" class="cpp">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

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.