* Andrid - AndroidLocator now follows spec when regards to multiple call support with AssetInfo.openStream()

* Android - fix exception with recycled bitmaps that occurs when jME3 application is restored/maximized after pause

git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@9144 75d07b2b-3a1a-0410-a2c5-0572b91ccdca
3.0
Sha..rd 13 years ago
parent 3fa629053a
commit a64db6fc7b
  1. 26
      engine/src/android/com/jme3/asset/AndroidAssetManager.java
  2. 92
      engine/src/android/com/jme3/asset/plugins/AndroidLocator.java
  3. 5
      engine/src/android/com/jme3/renderer/android/OGLESShaderRenderer.java
  4. 11
      engine/src/android/com/jme3/renderer/android/TextureUtil.java
  5. 70
      engine/src/android/com/jme3/texture/plugins/AndroidImageLoader.java

@ -37,8 +37,6 @@ import com.jme3.audio.plugins.AndroidAudioLoader;
import com.jme3.texture.Texture;
import com.jme3.texture.plugins.AndroidImageLoader;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Logger;
/**
@ -49,7 +47,6 @@ import java.util.logging.Logger;
public class AndroidAssetManager extends DesktopAssetManager {
private static final Logger logger = Logger.getLogger(AndroidAssetManager.class.getName());
private List<ClassLoader> classLoaders;
public AndroidAssetManager() {
this(null);
@ -67,10 +64,8 @@ public class AndroidAssetManager extends DesktopAssetManager {
* @param configFile
*/
public AndroidAssetManager(URL configFile) {
System.setProperty("org.xml.sax.driver", "org.xmlpull.v1.sax2.Driver");
// Set Default Android config
this.registerLocator("", AndroidLocator.class);
this.registerLocator("", ClasspathLocator.class);
@ -92,25 +87,9 @@ public class AndroidAssetManager extends DesktopAssetManager {
this.registerLoader(com.jme3.scene.plugins.ogre.SceneLoader.class, "scene");
this.registerLoader(com.jme3.shader.plugins.GLSLLoader.class, "vert", "frag", "glsl", "glsllib");
logger.info("AndroidAssetManager created.");
}
public void addClassLoader(ClassLoader loader){
if(classLoaders == null)
classLoaders = new ArrayList<ClassLoader>();
classLoaders.add(loader);
}
public void removeClassLoader(ClassLoader loader){
if(classLoaders != null)
classLoaders.remove(loader);
}
public List<ClassLoader> getClassLoaders(){
return classLoaders;
}
/**
* Loads a texture.
*
@ -120,7 +99,10 @@ public class AndroidAssetManager extends DesktopAssetManager {
public Texture loadTexture(TextureKey key) {
Texture tex = (Texture) loadAsset(key);
// Needed for Android
// XXX: This will improve performance on some really
// low end GPUs (e.g. ones with OpenGL ES 1 support only)
// but otherwise won't help on the higher ones.
// Strongly consider removing this.
tex.setMagFilter(Texture.MagFilter.Nearest);
tex.setAnisotropicFilter(0);
if (tex.getMinFilter().usesMipMapLevels()) {

@ -1,74 +1,90 @@
package com.jme3.asset.plugins;
import android.content.res.Resources;
import com.jme3.asset.AssetInfo;
import com.jme3.asset.AssetKey;
import com.jme3.asset.AssetLocator;
import com.jme3.asset.*;
import com.jme3.system.android.JmeAndroidSystem;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import java.util.logging.Level;
import java.util.logging.Logger;
public class AndroidLocator implements AssetLocator {
private static final Logger logger = Logger.getLogger(AndroidLocator.class.getName());
private Resources resources;
private android.content.res.AssetManager androidManager;
private String rootPath = "";
private class AndroidAssetInfo extends AssetInfo {
private final InputStream in;
private InputStream in;
private final String assetPath;
public AndroidAssetInfo(com.jme3.asset.AssetManager manager, AssetKey<?> key, InputStream in)
{
super(manager, key);
public AndroidAssetInfo(com.jme3.asset.AssetManager assetManager, AssetKey<?> key, String assetPath, InputStream in) {
super(assetManager, key);
this.assetPath = assetPath;
this.in = in;
}
@Override
public InputStream openStream() {
return in;
if (in != null){
// Reuse the already existing stream (only once)
InputStream in2 = in;
in = null;
return in2;
}else{
// Create a new stream for subsequent invocations.
try {
return androidManager.open(assetPath);
} catch (IOException ex) {
throw new AssetLoadException("Failed to open asset " + assetPath, ex);
}
}
}
}
public AndroidLocator()
{
resources = JmeAndroidSystem.getResources();
androidManager = resources.getAssets();
private AndroidAssetInfo create(AssetManager assetManager, AssetKey key, String assetPath) throws IOException {
try {
InputStream in = androidManager.open(assetPath);
if (in == null){
return null;
}else{
return new AndroidAssetInfo(assetManager, key, assetPath, in);
}
} catch (IOException ex) {
// XXX: Prefer to show warning here?
// Should only surpress exceptions for "file missing" type errors.
return null;
}
}
public void setRootPath(String rootPath)
{
public AndroidLocator() {
androidManager = JmeAndroidSystem.getResources().getAssets();
}
public void setRootPath(String rootPath) {
this.rootPath = rootPath;
}
@SuppressWarnings("rawtypes")
@Override
public AssetInfo locate(com.jme3.asset.AssetManager manager, AssetKey key)
{
InputStream in = null;
String sAssetPath = rootPath + key.getName();
public AssetInfo locate(com.jme3.asset.AssetManager manager, AssetKey key) {
String assetPath = rootPath + key.getName();
// Fix path issues
if (sAssetPath.startsWith("/"))
{
if (assetPath.startsWith("/")) {
// Remove leading /
sAssetPath = sAssetPath.substring(1);
assetPath = assetPath.substring(1);
}
sAssetPath = sAssetPath.replace("//", "/");
try {
in = androidManager.open(sAssetPath);
if (in == null)
return null;
return new AndroidAssetInfo(manager, key, in);
}
catch (IOException ex)
{
//logger.log(Level.WARNING, "Failed to locate {0} ", sAssetPath);
assetPath = assetPath.replace("//", "/");
try {
return create(manager, key, assetPath);
}catch (IOException ex){
// This is different handling than URL locator
// since classpath locating would return null at the getResource()
// call, otherwise there's a more critical error...
throw new AssetLoadException("Failed to open asset " + assetPath, ex);
}
return null;
}
}

@ -36,6 +36,7 @@ import android.opengl.GLES10;
import android.opengl.GLES11;
import android.opengl.GLES20;
import android.os.Build;
import com.jme3.asset.AndroidImageInfo;
import com.jme3.light.LightList;
import com.jme3.material.RenderState;
import com.jme3.math.*;
@ -1915,7 +1916,7 @@ public class OGLESShaderRenderer implements Renderer {
if (target == GLES20.GL_TEXTURE_CUBE_MAP) {
// Upload a cube map / sky box
@SuppressWarnings("unchecked")
List<Bitmap> bmps = (List<Bitmap>) img.getEfficentData();
List<AndroidImageInfo> bmps = (List<AndroidImageInfo>) img.getEfficentData();
if (bmps != null) {
// Native android bitmap
if (bmps.size() != 6) {
@ -1923,7 +1924,7 @@ public class OGLESShaderRenderer implements Renderer {
+ "Cubemap textures must contain 6 data units.");
}
for (int i = 0; i < 6; i++) {
TextureUtil.uploadTextureBitmap(GLES20.GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, bmps.get(i), false, powerOf2);
TextureUtil.uploadTextureBitmap(GLES20.GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, bmps.get(i).getBitmap(), false, powerOf2);
}
} else {
// Standard jme3 image data

@ -3,6 +3,7 @@ package com.jme3.renderer.android;
import android.graphics.Bitmap;
import android.opengl.GLES20;
import android.opengl.GLUtils;
import com.jme3.asset.AndroidImageInfo;
import com.jme3.math.FastMath;
import com.jme3.texture.Image;
import com.jme3.texture.Image.Format;
@ -118,12 +119,16 @@ public class TextureUtil {
boolean generateMips,
boolean powerOf2){
if (img.getEfficentData() instanceof Bitmap){
Bitmap bitmap = (Bitmap) img.getEfficentData();
uploadTextureBitmap(target, bitmap, generateMips, powerOf2);
if (img.getEfficentData() instanceof AndroidImageInfo){
// If image was loaded from asset manager, use fast path
AndroidImageInfo imageInfo = (AndroidImageInfo) img.getEfficentData();
uploadTextureBitmap(target, imageInfo.getBitmap(), generateMips, powerOf2);
return;
}
// Otherwise upload image directly.
// Prefer to only use power of 2 textures here to avoid errors.
Image.Format fmt = img.getFormat();
ByteBuffer data;
if (index >= 0 || img.getData() != null && img.getData().size() > 0){

@ -1,78 +1,20 @@
package com.jme3.texture.plugins;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import com.jme3.asset.AndroidImageInfo;
import com.jme3.asset.AssetInfo;
import com.jme3.asset.AssetLoader;
import com.jme3.asset.TextureKey;
import com.jme3.texture.Image;
import com.jme3.texture.Image.Format;
import com.jme3.util.BufferUtils;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
public class AndroidImageLoader implements AssetLoader {
public Object load2(AssetInfo info) throws IOException {
ByteBuffer bb = BufferUtils.createByteBuffer(1 * 1 * 2);
bb.put((byte) 0xff).put((byte) 0xff);
bb.clear();
return new Image(Format.RGB5A1, 1, 1, bb);
}
public Object load(AssetInfo info) throws IOException {
InputStream in = null;
Bitmap bitmap = null;
try {
in = info.openStream();
bitmap = BitmapFactory.decodeStream(in);
if (bitmap == null) {
throw new IOException("Failed to load image: " + info.getKey().getName());
}
} finally {
if (in != null) {
in.close();
}
}
int width = bitmap.getWidth();
int height = bitmap.getHeight();
Format fmt;
switch (bitmap.getConfig()) {
case ALPHA_8:
fmt = Format.Alpha8;
break;
case ARGB_4444:
fmt = Format.ARGB4444;
break;
case ARGB_8888:
fmt = Format.RGBA8;
break;
case RGB_565:
fmt = Format.RGB565;
break;
default:
return null;
}
if (((TextureKey) info.getKey()).isFlipY()) {
Bitmap newBitmap = null;
Matrix flipMat = new Matrix();
flipMat.preScale(1.0f, -1.0f);
newBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), flipMat, false);
bitmap.recycle();
bitmap = newBitmap;
if (bitmap == null) {
throw new IOException("Failed to flip image: " + info.getKey().getName());
}
}
Image image = new Image(fmt, width, height, null);
image.setEfficentData(bitmap);
AndroidImageInfo imageInfo = new AndroidImageInfo(info);
Bitmap bitmap = imageInfo.getBitmap();
Image image = new Image(imageInfo.getFormat(), bitmap.getWidth(), bitmap.getHeight(), null);
image.setEfficentData(imageInfo);
return image;
}
}

Loading…
Cancel
Save