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

时间:2013-05-14 14:08:38

标签: android opengl-es android-ndk java-native-interface

我写了一个原生的Android应用程序,它使用openGL ES和APK扩展文件,因为它大于50MB。 我的所有纹理都在.obb文件中,我在java中加载它(使用APKExpansionSupport)。

这是我从扩展

加载图像的方法
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);

        ....    
    }
}

... 
}

纹理加载非常长,大约占我CPU时间的30%(BitmapFactory.decodeStream占用较大的部分)。是否有人有更好的解决方案来加载它?

2 个答案:

答案 0 :(得分:0)

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

答案 1 :(得分:0)

我使用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