方法1:数据文件放在assert目录,java层获得assert句柄,传给NDK,NDK用AAssetManager、AAsset_read去读文件。比较晦涩。
方法2:数据文件放在libs/armeabi目录下,安装之后,这个文件在 /data/data/<package>/lib 目录下,可以直接用fopen读取
另外,NDK可以读取/sdcard路径的文件,但是这不适用于读取apk文件中的数据文件。另外, 要use the Java getExternalStorageDirectory() call to get the real path to the sdcard since newer devices don't simply map it to "/sdcard"。这个方法也不可取。
方法2最简单直接,但是在NDK编译时(ndk-build)会自动删除libs/armeabi目录下的so文件,所以你还需要:
1. 在运行ndk-build后,每次都将so文件们重新拷贝到libs/armeabi目录;
2. 在Eclipse中,build project时,不要编译ndk层。见 这里,不要建立里面的Builder即可。
方法1: http://blog.youkuaiyun.com/happyhell/article/details/7414110
android常见问题之jni读取assets资源文件
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。
-
-
-
-
-
-
-
- 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等。
-
-
-
-
-
-
-
- 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)
方法2:http://stackoverflow.com/questions/2603648/how-to-get-the-path-to-the-lib-folder-for-an-installed-package
|
|
Shared libraries .so files are placed in lib/armeabi in an apk file.
I have read after installation the libs gets extracted to /data/data/application_package/lib
How can I get the exact path to this directory in my application at run time? Is this directory readable by the application? Or is only executeable access allowed? If it is readable - Is this still true for copy protected applications?
|
| |
|
|
|
You can get the exact path with:
String libraryPath = getContext().getApplicationInfo().dataDir + "/lib";
The directory and its files are readable by the application.
The unix permissions are set to rwxr-x--x. So applications with the same group can read the files.
|
|
|
answered
Jan 9 '11 at 11:23
| |
| |
|