0

我编写了一个使用 openGL ES 和 APK 扩展文件的原生 android 应用程序,因为它大于 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);

        ....    
    }
}

... 
}

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

4

2 回答 2

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

于 2014-01-12T01:17:28.903 回答
0

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

于 2013-08-06T15:09:15.833 回答