* 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-0572b91ccdca3.0
parent
3fa629053a
commit
a64db6fc7b
@ -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; |
||||
} |
||||
|
||||
} |
||||
|
@ -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…
Reference in new issue