|
@@ -1,6 +1,7 @@
|
|
|
package com.jme3.asset.plugins;
|
|
|
|
|
|
import android.content.res.AssetFileDescriptor;
|
|
|
+import android.content.res.Resources;
|
|
|
import com.jme3.asset.*;
|
|
|
import com.jme3.system.android.JmeAndroidSystem;
|
|
|
import java.io.IOException;
|
|
@@ -12,26 +13,89 @@ public class AndroidLocator implements AssetLocator {
|
|
|
|
|
|
private static final Logger logger = Logger.getLogger(AndroidLocator.class.getName());
|
|
|
|
|
|
- private android.content.res.AssetManager androidManager;
|
|
|
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 {
|
|
|
|
|
|
private InputStream in;
|
|
|
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);
|
|
|
this.assetPath = assetPath;
|
|
|
this.in = in;
|
|
|
- }
|
|
|
-
|
|
|
- public AssetFileDescriptor openFileDescriptor() {
|
|
|
- try {
|
|
|
- return androidManager.openFd(assetPath);
|
|
|
- } catch (IOException ex) {
|
|
|
- throw new AssetLoadException("Failed to open asset " + assetPath, ex);
|
|
|
- }
|
|
|
+ this.resourceId = resourceId;
|
|
|
}
|
|
|
|
|
|
@Override
|
|
@@ -43,55 +107,47 @@ public class AndroidLocator implements AssetLocator {
|
|
|
return in2;
|
|
|
}else{
|
|
|
// Create a new stream for subsequent invocations.
|
|
|
+ android.content.res.Resources androidResources = JmeAndroidSystem.getView().getContext().getResources();
|
|
|
+ if (resourceId == 0) {
|
|
|
+ try {
|
|
|
+ return androidResources.getAssets().open(assetPath);
|
|
|
+ } catch (IOException 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);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public AssetFileDescriptor openFileDescriptor() {
|
|
|
+ android.content.res.Resources androidResources = JmeAndroidSystem.getView().getContext().getResources();
|
|
|
+ if (resourceId == 0) {
|
|
|
try {
|
|
|
- return androidManager.open(assetPath);
|
|
|
+ return androidResources.getAssets().openFd(assetPath);
|
|
|
} catch (IOException ex) {
|
|
|
throw new AssetLoadException("Failed to open asset " + assetPath, ex);
|
|
|
}
|
|
|
+ } else {
|
|
|
+ try {
|
|
|
+ return androidResources.openRawResourceFd(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 {
|
|
|
- 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 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 {
|
|
|
- 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);
|
|
|
+ private String getResourceName(String name) {
|
|
|
+ int idx = name.lastIndexOf('.');
|
|
|
+ if (idx <= 0 || idx == name.length() - 1) {
|
|
|
+ return name;
|
|
|
+ } else {
|
|
|
+ return name.substring(0, idx).toLowerCase();
|
|
|
}
|
|
|
}
|
|
|
}
|