什么是从NDK中的扩展文件加载文件的最佳方式

问题描述:

我编写了一个使用openGL ES和APK扩展文件的原生android应用程序,因为它大于50MB。 我所有的纹理都在.obb文件中,我使用java加载(使用APKExpansionSupport)。什么是从NDK中的扩展文件加载文件的最佳方式

这里是我的方法从扩张加载图像

public static Bitmap getImageWithName(String a_path) 
{ 
    Bitmap t_image = null; 
    try 
    { 
     InputStream t_inputStream = expansionFile.getInputStream(a_path); 
     t_image = BitmapFactory.decodeStream(t_inputStream);    
     t_inputStream.close(); 
    } 
    catch (Exception e) 
    { 
     Log.e(LOG_TAG, e.getMessage()); 
    } 
    return t_image; 
} 

这里是我的JNI方法来获取图像:

BImage * WFileLoader::getImage(const BString& a_path, FileLocation a_location) 
{ 
    ... 

    jmethodID javaMethod = env->GetStaticMethodID(cls, "getImageWithName","(Ljava/lang/String;I)Landroid/graphics/Bitmap;"); 

    if(javaMethod) 
    { 
     jobject t_bitmap = env->CallStaticObjectMethod(cls, javaMethod, t_path, t_location); 

     if(t_bitmap) 
     { 
      jclass t_bitmapClass = env->FindClass("android/graphics/Bitmap"); 

      jmethodID t_getWidthMethod = env->GetMethodID(t_bitmapClass, "getWidth", "()I"); 
      jmethodID t_getHeightMethod =env->GetMethodID(t_bitmapClass, "getHeight", "()I"); 

      jint t_width = env->CallIntMethod(t_bitmap,t_getWidthMethod); 
      jint t_height = env->CallIntMethod(t_bitmap,t_getHeightMethod); 

      jmethodID t_getPixelsMethod = env->GetMethodID(t_bitmapClass, "getPixels", "([IIIIIII)V"); 

      jintArray t_intBuffer = env->NewIntArray(t_width*t_height); 
      jint t_offset = 0; 
      jint t_stride = t_width; 
      jint t_x = 0; 
      jint t_y=0; 

      env->CallVoidMethod(t_bitmap,t_getPixelsMethod,t_intBuffer,t_offset,t_stride,t_x,t_y,t_width,t_height); 

     ....  
    } 
} 

... 
} 

纹理加载很长,大约需要30我的CPU时间百分比(BitmapFactory.decodeStream占用了大部分时间)。有没有人有更好的解决方案来加载它?

我正在尝试使用zzip来解决此问题。

我使用Android SDK中的mountObb()来装载我的APK文件。它可以快速高效地读取存储在APK中的文件。

// Get OBB path 
mSM = (StorageManager) getApplicationContext().getSystemService(STORAGE_SERVICE); 
String tPackageName = "main." + versionCode + "." + getPackageName() + ".obb"; 
mObbPath = new File(Helpers.getSaveFilePath(this), tPackageName).getPath(); 

// Mount OBB 
try { 
    // We don't need to synchronize here to avoid clobbering the 
    // content of mStatus because the callback comes to our main 
    // looper. 
    if (mSM.mountObb(mObbPath, null, mEventListener)) { 
     Log.d(TAG, "Attempting to mount OBB"); 
    } else { 
     Log.e(TAG, "Failed to start OBB mount."); 
    } 
} catch (IllegalArgumentException e) { 
    Log.e(TAG, "OBB already mounted."); 
}  

一旦它的安装,您可以访问使用()由getMountedObbPath指定的文件路径中的文件

String tObbPath = mSM.getMountedObbPath(mObbPath)+ "/"; 

你需要做一个安装OBB档案与文件系统的内部文件。

我使用AOSP的obbtool(必须在Linux中克隆和编译repo),但最近我发现jobb似乎能够完成这项工作,并且包含在Android SDK中? (未测试)

http://developer.android.com/tools/help/jobb.html