Update AndroidLocator to allow assets to be stored in Android assets, drawable, or mipmap directories.

Texture assets can now be stored in Android Drawable and Mipmap directories.  Allows Android to automatically select the closest matching image asset for the actual device configuration (ie. lower resolution textures for lower-end devices).  Search order is:  assets -> drawable -> mipmap.  First match found is returned.
define_list_fix
iwgeric 9 years ago
parent b53de6aedc
commit c219ce1b4f
  1. 144
      jme3-android/src/main/java/com/jme3/asset/plugins/AndroidLocator.java

@ -1,6 +1,7 @@
package com.jme3.asset.plugins; package com.jme3.asset.plugins;
import android.content.res.AssetFileDescriptor; import android.content.res.AssetFileDescriptor;
import android.content.res.Resources;
import com.jme3.asset.*; import com.jme3.asset.*;
import com.jme3.system.android.JmeAndroidSystem; import com.jme3.system.android.JmeAndroidSystem;
import java.io.IOException; import java.io.IOException;
@ -12,26 +13,89 @@ public class AndroidLocator implements AssetLocator {
private static final Logger logger = Logger.getLogger(AndroidLocator.class.getName()); private static final Logger logger = Logger.getLogger(AndroidLocator.class.getName());
private android.content.res.AssetManager androidManager;
private String rootPath = ""; private String rootPath = "";
public AndroidLocator() {
}
public void setRootPath(String rootPath) {
this.rootPath = rootPath;
}
@Override
public AssetInfo locate(AssetManager manager, AssetKey key) {
String assetPath = rootPath + key.getName();
// Fix path issues
if (assetPath.startsWith("/")) {
// Remove leading /
assetPath = assetPath.substring(1);
}
assetPath = assetPath.replace("//", "/");
// Not making this a property and storing for future use in case the view stored in JmeAndroidSystem
// is replaced due to device orientation change. Not sure it is necessary to do this yet, but am for now.
android.content.res.Resources androidResources = JmeAndroidSystem.getView().getContext().getResources();
String androidPackageName = JmeAndroidSystem.getView().getContext().getPackageName();
// logger.log(Level.INFO, "Asset Key: {0}", key);
// logger.log(Level.INFO, "Asset Name: {0}", key.getName());
// logger.log(Level.INFO, "Asset Path: {0}", assetPath);
// logger.log(Level.INFO, "Asset Extension: {0}", key.getExtension());
// logger.log(Level.INFO, "Asset Key Class: {0}", key.getClass().getName());
// logger.log(Level.INFO, "androidPackageName: {0}", androidPackageName);
// logger.log(Level.INFO, "Resource Name: {0}", getResourceName(assetPath));
// check the assets directory for the asset using assetPath
try {
InputStream in = androidResources.getAssets().open(assetPath);
if (in != null){
return new AndroidAssetInfo(manager, key, assetPath, in, 0);
}
} catch (IOException ex) {
// allow to fall through to the other checks in the resources directories.
// logger.log(Level.INFO, "Resource[{0}] not found in assets directory.", assetPath);
}
// if not found in the assets directory, check the drawable and mipmap directories (only valid for images)
String resourceName = getResourceName(assetPath);
int resourceId = androidResources.getIdentifier(resourceName, "drawable", androidPackageName);
// logger.log(Level.INFO, "drawable resourceId: {0}", resourceId);
if (resourceId == 0) { // drawable resource not found, check mipmap resource type
resourceId = androidResources.getIdentifier(resourceName, "mipmap", androidPackageName);
// logger.log(Level.INFO, "mipmap resourceId: {0}", resourceId);
}
if (resourceId == 0) { // not found in resource directories, return null;
return null;
}
// try to open a stream with the resourceId returned by Android
try {
InputStream in = androidResources.openRawResource(resourceId);
if (in != null){
// logger.log(Level.INFO, "Creating new AndroidResourceInfo.");
return new AndroidAssetInfo(manager, key, assetPath, in, resourceId);
}
} catch (Resources.NotFoundException ex) {
// input stream failed to open, return null
return null;
}
return null;
}
public class AndroidAssetInfo extends AssetInfo { public class AndroidAssetInfo extends AssetInfo {
private InputStream in; private InputStream in;
private final String assetPath; private final String assetPath;
private int resourceId;
public AndroidAssetInfo(com.jme3.asset.AssetManager assetManager, AssetKey<?> key, String assetPath, InputStream in) { AndroidAssetInfo(AssetManager assetManager, AssetKey<?> key, String assetPath, InputStream in, int resourceId) {
super(assetManager, key); super(assetManager, key);
this.assetPath = assetPath; this.assetPath = assetPath;
this.in = in; this.in = in;
} this.resourceId = resourceId;
public AssetFileDescriptor openFileDescriptor() {
try {
return androidManager.openFd(assetPath);
} catch (IOException ex) {
throw new AssetLoadException("Failed to open asset " + assetPath, ex);
}
} }
@Override @Override
@ -43,55 +107,47 @@ public class AndroidLocator implements AssetLocator {
return in2; return in2;
}else{ }else{
// Create a new stream for subsequent invocations. // Create a new stream for subsequent invocations.
android.content.res.Resources androidResources = JmeAndroidSystem.getView().getContext().getResources();
if (resourceId == 0) {
try { try {
return androidManager.open(assetPath); return androidResources.getAssets().open(assetPath);
} catch (IOException ex) { } catch (IOException ex) {
throw new AssetLoadException("Failed to open asset " + assetPath, ex); throw new AssetLoadException("Failed to open asset " + assetPath, ex);
} }
} else {
try {
return androidResources.openRawResource(resourceId);
} catch (Resources.NotFoundException ex) {
throw new AssetLoadException("Failed to open asset " + assetPath, ex);
}
} }
} }
} }
private AndroidAssetInfo create(AssetManager assetManager, AssetKey key, String assetPath) throws IOException { public AssetFileDescriptor openFileDescriptor() {
android.content.res.Resources androidResources = JmeAndroidSystem.getView().getContext().getResources();
if (resourceId == 0) {
try { try {
InputStream in = androidManager.open(assetPath); return androidResources.getAssets().openFd(assetPath);
if (in == null){
return null;
}else{
return new AndroidAssetInfo(assetManager, key, assetPath, in);
}
} catch (IOException ex) { } catch (IOException ex) {
// XXX: Prefer to show warning here? throw new AssetLoadException("Failed to open asset " + assetPath, ex);
// Should only surpress exceptions for "file missing" type errors.
return null;
} }
} else {
try {
return androidResources.openRawResourceFd(resourceId);
} catch (Resources.NotFoundException ex) {
throw new AssetLoadException("Failed to open asset " + assetPath, ex);
} }
public AndroidLocator() {
androidManager = JmeAndroidSystem.getView().getContext().getAssets();
} }
public void setRootPath(String rootPath) {
this.rootPath = rootPath;
} }
@SuppressWarnings("rawtypes")
@Override
public AssetInfo locate(com.jme3.asset.AssetManager manager, AssetKey key) {
String assetPath = rootPath + key.getName();
// Fix path issues
if (assetPath.startsWith("/")) {
// Remove leading /
assetPath = assetPath.substring(1);
} }
assetPath = assetPath.replace("//", "/");
try { private String getResourceName(String name) {
return create(manager, key, assetPath); int idx = name.lastIndexOf('.');
} catch (IOException ex) { if (idx <= 0 || idx == name.length() - 1) {
// This is different handling than URL locator return name;
// since classpath locating would return null at the getResource() } else {
// call, otherwise there's a more critical error... return name.substring(0, idx).toLowerCase();
throw new AssetLoadException("Failed to open asset " + assetPath, ex);
} }
} }
} }

Loading…
Cancel
Save