AssetManager problem with android

Hello,

I have a problem when I try to load a texture or anything else using the assetManager for an Android application.

I put my materials in the asset directory of my Android project, then in my test application I call (for example):

[java]

Texture tex = assetManager.loadTexture("Textures/Sky/Bright/BrightSky.dds");

[/java]

And it returns null.

If I try to load a texture that is in the commons/MatDefs/… of the jmonkeyengine3-android-dist.jar it works, but if the texture is in the android project asset directory it fails.



Do I have to do or call something ?



Thanks.

Well I guess you dont add the assets jar file to the classpath, if you generate it at all.

dds files are not supported, at least last time i tried to load a dds sky it failed because of the format.

jpg and png work for me, but i am using my own AndroidAssetManager which is derived from DesktopAssetManager.

Check the logcat output for errors.



If you want to give it a try use the following code:

[java]package com.jme3.asset;



import com.jme3.texture.Texture;

import com.jme3.texture.plugins.AndroidImageLoader;

import java.net.URL;

import java.util.logging.Logger;



import com.jme3.asset.plugins.AndroidLocator;



/**

  • <code>AssetManager</code> is the primary method for managing and loading
  • assets inside jME.

    *
  • @author Kirill Vainer

    */

    public class AndroidAssetManager extends DesktopAssetManager {



    private static final Logger logger = Logger.getLogger(AndroidAssetManager.class.getName());



    public AndroidAssetManager(){

    this(null);

    }



    @Deprecated

    public AndroidAssetManager(boolean loadDefaults){

    //this(Thread.currentThread().getContextClassLoader().getResource("com/jme3/asset/Android.cfg"));

    this(null);

    }



    /**
  • AndroidAssetManager constructor
  • If URL == null then a default list of locators and loaders for android is set
  • @param configFile

    */

    public AndroidAssetManager(URL configFile)

    {

    super(configFile);

    System.setProperty("org.xml.sax.driver","org.xmlpull.v1.sax2.Driver");



    if (configFile == null)

    {

    // Set Default

    this.registerLocator("", AndroidLocator.class);

    this.registerLoader(AndroidImageLoader.class, "jpg", "bmp", "gif", "png", "jpeg");

    this.registerLoader(com.jme3.material.plugins.J3MLoader.class, "j3m");

    this.registerLoader(com.jme3.material.plugins.J3MLoader.class, "j3md");

    this.registerLoader(com.jme3.font.plugins.BitmapFontLoader.class, "fnt");

    this.registerLoader(com.jme3.texture.plugins.DDSLoader.class, "dds");

    this.registerLoader(com.jme3.texture.plugins.PFMLoader.class, "pfm");

    this.registerLoader(com.jme3.texture.plugins.HDRLoader.class, "hdr");

    this.registerLoader(com.jme3.texture.plugins.TGALoader.class, "tga");

    this.registerLoader(com.jme3.export.binary.BinaryImporter.class, "j3o");

    this.registerLoader(com.jme3.scene.plugins.OBJLoader.class, "obj");

    this.registerLoader(com.jme3.scene.plugins.MTLLoader.class, "mtl");

    this.registerLoader(com.jme3.scene.plugins.ogre.MeshLoader.class, "meshxml", "mesh.xml");

    this.registerLoader(com.jme3.scene.plugins.ogre.SkeletonLoader.class, "skeletonxml", "skeleton.xml");

    this.registerLoader(com.jme3.scene.plugins.ogre.MaterialLoader.class, "material");

    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.");

    }



    /**
  • Loads a texture.

    *
  • @return

    */

    @Override

    public Texture loadTexture(TextureKey key){

    Texture tex = (Texture) loadAsset(key);



    // Needed for Android

    tex.setMagFilter(Texture.MagFilter.Nearest);

    tex.setAnisotropicFilter(0);

    if (tex.getMinFilter().usesMipMapLevels()){

    tex.setMinFilter(Texture.MinFilter.NearestNearestMipMap);

    }else{

    tex.setMinFilter(Texture.MinFilter.NearestNoMipMaps);

    }

    return tex;

    }



    }[/java]

@Normen

What is the assets jar file? I add this jar “jmonkeyengine3-android-dist.jar”, and with the assetManager I am able to load texture included in this jar.

But I can’t load texture included in the android project asset directory.



@larynx

Tomorow I will send my logcat output.

And I will try your class.



Thanks.

The DDS texture format is not supported on android. You will need to use JPEG/PNG images instead

Is that a class that I can found on the net?

import com.jme3.asset.plugins.AndroidLocator;

i forgot the AndroidLocator, here it is:



[java]

package com.jme3.asset.plugins;



import android.content.res.AssetManager;

import android.content.res.Resources;

import com.jme3.asset.AssetInfo;

import com.jme3.asset.AssetKey;

import com.jme3.asset.AssetLocator;

import com.jme3.system.JmeSystem;

import java.io.IOException;

import java.io.InputStream;

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 AssetManager androidManager;

private String rootPath = "";



private class AndroidAssetInfo extends AssetInfo {



private final InputStream in;



public AndroidAssetInfo(com.jme3.asset.AssetManager manager, AssetKey key,

InputStream in){

super(manager, key);

this.in = in;

}



@Override

public InputStream openStream() {

return in;

}

}





public AndroidLocator(){

resources = JmeSystem.getResources();

androidManager = resources.getAssets();

}



public void setRootPath(String rootPath)

{

this.rootPath = rootPath;

}



public AssetInfo locate(com.jme3.asset.AssetManager manager, AssetKey key) {

InputStream in = null;

String sAssetPath = rootPath + key.getName();

// Fix path issues

if (sAssetPath.startsWith("/"))

{

// Remove leading /

sAssetPath = sAssetPath.substring(1);

}

sAssetPath = sAssetPath.replace("//", "/");

try {

in = androidManager.open(sAssetPath);

if (in == null)

return null;



return new AndroidAssetInfo(manager, key, in);

} catch (IOException ex) {

if (in != null)

try {

in.close();

} catch (IOException ex1) {

}

logger.log(Level.WARNING, "Failed to locate {0} ", sAssetPath);

}

return null;

}

}

[/java]

Thank you for your respones.

When I try to run the Hello Collision tutorial on Android the project fails on the line

[java] assetManager.registerLocator(“town.zip”, ZipLocator.class.getName());

[/java]



The logcat is

[java]

08-15 22:03:01.184: ERROR/AndroidHarness(25073): com.jme3.asset.AssetLoadException: Failed to open zip file: town.zip

08-15 22:03:01.184: ERROR/AndroidHarness(25073): Exception thrown in Thread[GLThread 8,5,main]: com.jme3.asset.plugins.ZipLocator.setRootPath(78) com.jme3.asset.ImplHandler.tryLocate(120) com.jme3.asset.DesktopAssetManager.loadAsset(234) com.jme3.asset.DesktopAssetManager.loadModel(373) com.jme3.asset.DesktopAssetManager.loadModel(383) com.interstatewebgroup.JMonkeyAndroidApp.Game5.simpleInitApp(47) com.jme3.app.SimpleApplication.initialize(230) com.jme3.system.android.OGLESContext.initInThread(263) com.jme3.system.android.OGLESContext.onSurfaceCreated(214) android.opengl.GLSurfaceView$GLThread.guardedRun(1317) android.opengl.GLSurfaceView$GLThread.run(1116)

[/java]



I’ve tried putting the file in a few different places including the project root, the assets folder, etc. I’d like to stay away from custom classes that don’t come with the jmonkeyengine if I can help it.



Is there any known problems with the assetManager with Android?

Probably you have to specify a full path like /sdcard/town.zip and put the file in the root of the sdcard. Also make sure you specify the proper permission in your android manifest

That worked like a charm. Thanks! No special permissions were needed in the manifest. I think that is just for writing to the sdcard.



Does the ZipLocator not support zip files in the asset directory?

ZipLocator adds a new search root to the assetManager root, for directories a FileLocator is used. Having a FileLocator on a folder where a ZIP rests inside thus only exposes the zip file to any loader that might want to load the zip file directly.

There might be a way to support loading zip files inside the assets … although I don’t see the point. Thing is, your APK file is already compressed as zip so it doesn’t make much sense to put a zip file inside another zip file.

Not a big deal. I was just wondering. Thanks for the info.