How to make Android and Desktop specific code blocks?

Hey, I’m new to development with Android, and I’ve never encountered a situation quite like this in Java development.



I’m going through all the tutorials, and I’m trying to make sure things work right on both the Desktop testing and on Android, but the ziploader doesn’t work right in android. But I have code that works for both.



package mygame;

import com.jme3.app.SimpleApplication;
import com.jme3.asset.AndroidAssetManager;
import com.jme3.asset.plugins.AndroidLocator;
import com.jme3.asset.plugins.ZipLocator;
import com.jme3.font.BitmapText;
import com.jme3.light.DirectionalLight;
import com.jme3.material.Material;
import com.jme3.math.Vector3f;
import com.jme3.scene.Geometry;
import com.jme3.scene.Spatial;
import com.jme3.scene.shape.Box;

/**
* Sample 3 - how to load an OBJ model, and OgreXML model, a material/texture,
* or text.
*/
public class Main extends SimpleApplication {

public static void main(String[] args) {
Main app = new Main();
app.start();
}

@Override
public void simpleInitApp() {

/*Spatial teapot = assetManager.loadModel("Models/Teapot/Teapot.obj");
Material mat_default = new Material(
assetManager, "Common/MatDefs/Misc/ShowNormals.j3md");
teapot.setMaterial(mat_default);
rootNode.attachChild(teapot);*/

// Create a wall with a simple texture from test_data
/*Box box = new Box(Vector3f.ZERO, 2.5f, 2.5f, 1.0f);
Spatial wall = new Geometry("Box", box);
Material mat_brick = new Material(
assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
mat_brick.setTexture("ColorMap",
assetManager.loadTexture("Textures/Terrain/BrickWall/BrickWall.jpg"));
wall.setMaterial(mat_brick);
wall.setLocalTranslation(2.0f, -2.5f, 0.0f);
rootNode.attachChild(wall);*/

// Display a line of text with a default font
guiNode.detachAllChildren();
guiFont = assetManager.loadFont("Interface/Fonts/Default.fnt");
BitmapText helloText = new BitmapText(guiFont, false);
helloText.setSize(guiFont.getCharSet().getRenderedSize());
helloText.setText("Demo Text");
helloText.setLocalTranslation(300, helloText.getLineHeight(), 0);
guiNode.attachChild(helloText);

// Load a model from test_data (OgreXML + material + texture)
Spatial ninja = assetManager.loadModel("Models/Ninja/Ninja.mesh.j3o");
ninja.scale(0.05f, 0.05f, 0.05f);
ninja.rotate(0.0f, -3.0f, 0.0f);
ninja.setLocalTranslation(0.0f, -5.0f, -2.0f);

rootNode.attachChild(ninja);
// You must add a light to make the model visible
DirectionalLight sun = new DirectionalLight();
sun.setDirection(new Vector3f(-0.1f, -0.7f, -1.0f));
rootNode.addLight(sun);

/*Spatial gameLevel = assetManager.loadModel("Scenes/town/main.j3o");
gameLevel.setLocalTranslation(0, -5.2f, 0);
gameLevel.setLocalScale(2);
rootNode.attachChild(gameLevel);*/

assetManager.registerLocator("town.zip", ZipLocator.class);
Spatial scene = assetManager.loadModel("main.scene");
rootNode.attachChild(scene);


AndroidAssetManager assMan = new AndroidAssetManager();
assMan.registerLocator("town.zip", AndroidLocator.class);
Spatial scene = assMan.loadModel("main.scene");
rootNode.attachChild(scene);

}
}


The bottom two blocks are the ones in question. How can I make it so the bottom one executes when running on android and the other in a Desktop deployment?

You can use JmeSystem.getAssetManager() in this case but why do you create an AssetManager at all? Every application has one and its threadsafe.

https://wiki.jmonkeyengine.org/legacy/doku.php/jme3:android contains info on how to have code separate for android in case its actually necessary.

Right, I mean I can load assets in just fine, but it’s the step of loading the zip that doesn’t work. The ZipLocator can’t find the root when you deploy it to android. But it does work when you use the AndroidLoader and Locator.



19:48:42.180 12865 com.mycompany.mygame ERROR AndroidHarness Caused by: java.io.FileNotFoundException: /town.zip (No such file or directory)

19:48:42.180 12865 com.mycompany.mygame ERROR AndroidHarness at org.apache.harmony.luni.platform.OSFileSystem.open(Native Method)

19:48:42.180 12865 com.mycompany.mygame ERROR AndroidHarness at dalvik.system.BlockGuard$WrappedFileSystem.open(BlockGuard.java:232)

19:48:42.180 12865 com.mycompany.mygame ERROR AndroidHarness at java.io.RandomAccessFile.(RandomAccessFile.java:132)

19:48:42.180 12865 com.mycompany.mygame ERROR AndroidHarness at java.io.RandomAccessFile.(RandomAccessFile.java:173)

19:48:42.180 12865 com.mycompany.mygame ERROR AndroidHarness at java.util.zip.ZipFile.(ZipFile.java:133)

19:48:42.180 12865 com.mycompany.mygame ERROR AndroidHarness at com.jme3.asset.plugins.ZipLocator.setRootPath(ZipLocator.java:72)

19:48:42.180 12865 com.mycompany.mygame ERROR AndroidHarness … 11 more



Is there any real benefit to using Zip Locators? When you load the Android app, does it load everything from the Assets folder into memory or what?



About the Android page you linked, it definitely gets your app working, but kinda left me lost on how to code specifically for android. Like you have to use touch listeners, but how do you disable mouse listeners? It doesn’t seem clear how to make that work.

Hmm, I think I get it now. Didn’t realize that the Main activity could import my project files. So I have set up a simple singleton that I can set up before executing that can allow for checks on the platform that it is running on. I’ll see if that works.

Yeah, it depends. The code in main() for example is only executed on desktop and the android activity is only executed on android. You can also check for the platform as you said which will probably be necessary anyway to avoid the use of post processors etc.

The last time I tried to load the town.zip, it worked as long as the zip file was on the root of the SDCARD directory. I never looked into why.



As far as creating Android specific blocks of code, the link below was a previous post asking how to do it.



http://hub.jmonkeyengine.org/groups/android/forum/topic/how-can-i-pass-on-the-custom-class-instance-from-adroidharness-to-simpleapplication/?topic_page=2&num=15#post-157404