My Experience getting my game running on andriod (still a work in progress)

HI folks, figured I would do a little write up on this (should hopefully help out some other lost souls out there), and a couple of pointed questions…:slight_smile:



My Initial Attempt to get my game on andriod (Asus transform pad 300) (from the perspective of total noob to android…and near noob to jmonkey).


  1. Install Andriod SDK
  • Had issue with not being able to install using .exe, used .zip instead.
  1. Followed the excellent instructions here: http://hub.jmonkeyengine.org/groups/android/forum/topic/android-deployment-via-checkbox-is-here/
  2. Created new project
  3. build and deployed.

    Searched for a long time trying to find the app the was deployed.
  • The Console output indicates the app MyGame was deployed/installed…
  • The actual name of the app (by default is MainAtivity)
  1. Finally was able to run the app, and enjoy the cube.
  2. Time to deploy the real game. :slight_smile:
  3. Stack Trace…(I expected this once…I was still loading my .properties via c:/…)

    – NOTE: you can use “adb.exe catlog” (to tail logs, tools is provided in andriod sdk…note: nbandriod website if offline atm…that may work as well)
  4. Updated code to load properties from class path, and deployed.
  5. Stack Trace…
  • After lots of ‘fartsing’ around determined that you cannot load properties via classpath
  1. Ended up placing properties file in Andriod …/res/raw directory, and loading the properties

    in MainAtivity.onCreate() method, and ‘passing’ it into static class that my actual Main can see.

    11)Deployed (a new StrackTrace)
  • wav files not supported…(and streaming not supported??)
  • For now I just disabled audioNode’s for loading and moved on. (looks like .ogg/mp3 (unstreamed) is the way to go for now. (not sure if wav supported will be added in the future for andriod, anyone know?)
  1. Deployed (SUCCESS)
  • Observed fps of 8 :frowning:
  • Afer warm up is climbed back to 80+ :slight_smile:
  • Noticed …that sometimes it after warm up…fps does not go up over 8 :frowning: (moving on for now)
  1. Updated app for TouchListener
  2. Noticed that x,y locations of taps, indicate resolution is: ~542x320
  • not sure whats up with low resolution, (my screen is 1280x800)
  • Tried main(){appSettings.setResolution(1280,800), and fullScreen(true)} still no change…odd.I must be doing something wrong…
  • Also updated MainActivity.onCreate() to dump screen resolution via:

    DisplayMetrics displaymetrics = new DisplayMetrics();

    getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
  1. Updated TouchListener logic for game mechanics & Deployed (New StackTrace)
  • Crash occured due physics collision(…)
  • Crashing in getNodeA/getNodeB() calls…
  • Searching forums ended up adding this check:

    if (event.getType() != PhysicsCollisionEvent.TYPE_PROCESSED) {

    return;

    }
  • NOTE: I’m wondering if PhycisCollisionEvent type can be used to determine initial/on-going/end collision state…will need to expirement.
  1. Deployed
  2. Fired my first shot (launching ball)
  • Ball Launches…but doesnt move from intial position :frowning:
  1. Reset…(try new demo using physics test (wall)
  • its working fine…hmm…it must be my game sigh… - (going to have to try and adjust my games physics settings for my game…and see what happens
  • noticed: my collision code used event.getNodeA/event.getNodeB…the test code uses getObjectA/getObjectB (I did not add the TYPE_PROCESSED check in the test code)…interesting…I will need to investigate



    anyways hopefully this post will help some people get started, and hopefully I will have update shortly with full success :slight_smile:
2 Likes
  1. wav files are supported as well as ogg. but they have to be in the android’s asset folder (it’s different form the jme’s asset folder).

    What i do is that my build moves all jme assets in android assets folder, so i can seamlessly use them on desktop and android.

    Note that this will change when we’ll use opensl for audio on android (only supported since android 2.3).



    12)All android devices (afaik) are capped to 60 fps (vsynced). If you have 80 it’s just that it’s so slow that the fps counter is messed up (i don’t know why though, i already noticed it a couple of times).

    8 fps is not a surprise if you targeted your game for desktop at first.

    My advices for optimization are :
  • if you use the lighting material, switch to vertex lighting
  • use low poly count models as often as possible
  • if you have your own shaders don’t ever use branching!
  • if you have animated models, they have to be very low poly because buffer updating has been proven very slow on android.


  1. let android handle the resolution and don’t try to change it yourself; Just check that your android manifest has these lines

    [xml]

    <supports-screens

    android:anyDensity=“true”

    android:largeScreens=“true”

    android:smallScreens=“true”

    android:normalScreens=“true”

    />

    [/xml]



    I’m sorry i can’t help much with physics, because i didn’t try it, but some had more success (and performance ) with the native bullet instead of jbullet on android.

Some more Progress :slight_smile:



Turned out the ball launching when added in the touchListener, was not setting the initial velocity correctly (it was too large), I am now able to launch it :slight_smile: and essentially all the mechanics are working. (still the game is running very very slowly, ~8fps).



I will check out the vertiex lighting, maybe that will help, I’m pretty much using the standard shaders, and have no animated models.



The scenes vertex count is: 205k, with 48k triangles. (probably the vertex count is way too high).



Also about the wav files, (would the error be that it could not find the resource rather then not supported?)…probably just artifact of being beta atm, will try and put them in assets folder at some point (once I get a more reasonable fps).



ps. what lines…needed to added to the manifest?

@danomano said:
The scenes vertex count is: 205k, with 48k triangles. (probably the vertex count is way too high).

mhh it can be ok...ofc less vertice will be faster but these counts are not really too high IMO.

@danomano said:
Also about the wav files, (would the error be that it could not find the resource rather then not supported?)..probably just artifact of being beta atm, will try and put them in assets folder at some point (once I get a more reasonable fps).

oh? what error do you have exactly?
I though you had a fileNotFound (this is the usual error)

@danomano said:
ps. what lines..needed to added to the manifest?

sorry, i edited my previous post

The actual stack:

E/AndroidHarness(10859): java.lang.IllegalStateException: No loader registered for type “wav”

E/AndroidHarness(10859): SEVERE AndroidHarness 12:32:24 PM Exception thrown in Thread[GLThread 2760,5,main]: at com.jme3.asset.DesktopAssetManager.loadAsset(248)

E/AndroidHarness(10859): at com.jme3.audio.AudioNode.(182)

E/AndroidHarness(10859): at com.jme3.audio.AudioNode.(209)

@danomano said:
The actual stack:
E/AndroidHarness(10859): java.lang.IllegalStateException: No loader registered for type "wav"
E/AndroidHarness(10859): SEVERE AndroidHarness 12:32:24 PM Exception thrown in Thread[GLThread 2760,5,main]: at com.jme3.asset.DesktopAssetManager.loadAsset(248)
E/AndroidHarness(10859): at com.jme3.audio.AudioNode.(182)
E/AndroidHarness(10859): at com.jme3.audio.AudioNode.(209)

oh..you may have done some roguish initialization in your main activity because this means you are trying to load a file from the Harness (which is bad) and that you are trying to do it with the DesktopAssetManager that is made...for desktop and not for android.

Load your files from your JME app using the provided assetManager.

err, sorry I did’t include the full stack, I didn’t modify the AndriodHarness, its being loaded just like the other assets, from simpleInitApp.



Heres the full stack:

W/dalvikvm(10859): threadid=11: thread exiting with uncaught exception (group=0x40a3e1f8)

E/AndroidHarness(10859): java.lang.IllegalStateException: No loader registered for type “wav”

E/AndroidHarness(10859): SEVERE AndroidHarness 12:32:24 PM Exception thrown in Thread[GLThread 2760,5,main]: at com.jme3.asset.DesktopAssetManager.loadAsset(248)

E/AndroidHarness(10859): at com.jme3.audio.AudioNode.(182)

E/AndroidHarness(10859): at com.jme3.audio.AudioNode.(209)

E/AndroidHarness(10859): at com.hpg.pinball.Managers.AudioManager.buildNode(31)

E/AndroidHarness(10859): at com.hpg.pinball.fx.FxObject.build(35)

E/AndroidHarness(10859): at com.hpg.pinball.PinBallMain.simpleInitApp(121)

E/AndroidHarness(10859): at com.jme3.app.SimpleApplication.initialize(231)

E/AndroidHarness(10859): at com.jme3.system.android.OGLESContext.initInThread(266)

E/AndroidHarness(10859): at com.jme3.system.android.OGLESContext.onSurfaceCreated(217)

E/AndroidHarness(10859): at android.opengl.GLSurfaceView$GLThread.guardedRun(1446)

E/AndroidHarness(10859): at android.opengl.GLSurfaceView$GLThread.run(1216)

E/AndroidHarness(10859):

Still…it should not use the DesktopAssetManager



Could you post your simpleInit code please?

the last line of corresponds to stack trace call at line 121, (maybe I should update to the latest stable release…I’m probably a version or 2 behind).

[java]

@Override

public void simpleInitApp() {

setPauseOnLostFocus(false);



audioMan = new AudioManager(assetManager);

materialManager = new MaterialManager(assetManager);

TableLoader loader = new TableLoader(audioMan, materialManager);



bulletAppState = new BulletAppState();

stateManager.attach(bulletAppState);

scoreData = ScoreManager.getScoreManager(settings);

scoreData.init(guiFont);



PropertiesLoader p = PropertiesLoader.getInstance();

if (p.getProperties() == null) { // preset if andriod

Log.i(TAG,“using default pinball.properties”);

p.setProperties(“pinball_dsktp.properties”);

}

else { // debug dump

Properties x = p.getProperties();

for (Object o : x.keySet()){

Log.i(TAG,o + " == " +p.getString((String)o));

}

}



// load fx definitions

String[] fxNames = p.getString(“fx.names”).split(",");

for (String s:fxNames)

FxObject.build(s,p);





— build Function:

public static FxObject build(String name, PropertiesLoader props) {

if (p == null) p = props;



FxObject o = new FxObject();

String k = “fx.”+name+".";

String tmp = p.getString(k+“sfx”);

if (tmp != null){

o.audioNode = AudioManager.buildNode(tmp);

float vlm = p.getFloat(k+“sfx.vlm”,-1);

if (vlm!=-1f){

o.audioNode.setVolume(vlm);

}

}

tmp = p.getString(k+“mat”);

if (tmp != null){

o.material = MaterialManager.addMaterial(tmp);

}

o.name = name;

objects.put(name,o);

return o;

}

[/java]

yeah update to latest stable, there as been changes since beta on the android part

I just updated to the latest:



Android Support [3.0.0.8829.45 → 3.0.0.9065.45]

jMonkeyEngine3 External Libraries [3.0.0.8829 → 3.0.0.8928]

jMonkeyEngine3 Library [3.0.0.8829 → 3.0.0.9083]

Material Support [3.0.0.8829 → 3.0.0.8875]

NiftyGUI Support [3.0.0.8774.2 → 3.0.0.8929.2]

Project Templates [3.0.0.8829 → 3.0.0.8982]

Project Test Data [3.0.0.8667 → 3.0.0.8913]

SceneComposer [3.0.0.8667 → 3.0.0.9068]

SDK Core [3.0.0.8829.45 → 3.0.0.9075.45]

SDK Engine [3.0.0.8829 → 3.0.0.9083]

SDK Libraries [3.0.0.8829 → 3.0.0.8928]

Terrain Editor [3.0.0.8667 → 3.0.0.9083]

Tests Template [3.0.0.8667 → 3.0.0.9044]



but…I’m getting the exact same stack trace:

W/dalvikvm( 1929): threadid=11: thread exiting with uncaught exception (group=0x40a4a1f8)

E/AndroidHarness( 1929): java.lang.IllegalStateException: No loader registered for type “wav”

E/AndroidHarness( 1929): SEVERE AndroidHarness 5:52:49 PM Exception thrown in Thread[GLThread 198,5,main]: at com.jme3.asset.DesktopAssetManager.loadAsset(248)

E/AndroidHarness( 1929): at com.jme3.audio.AudioNode.(182)

E/AndroidHarness( 1929): at com.jme3.audio.AudioNode.(209)

E/AndroidHarness( 1929): at com.hpg.pinball.Managers.AudioManager.buildNode(31)

E/AndroidHarness( 1929): at com.hpg.pinball.fx.FxObject.build(35)

E/AndroidHarness( 1929): at com.hpg.pinball.PinBallMain.simpleInitApp(108)

E/AndroidHarness( 1929): at com.jme3.app.SimpleApplication.initialize(231)

E/AndroidHarness( 1929): at com.jme3.system.android.OGLESContext.initInThread(260)

E/AndroidHarness( 1929): at com.jme3.system.android.OGLESContext.onSurfaceCreated(211)

E/AndroidHarness( 1929): at android.opengl.GLSurfaceView$GLThread.guardedRun(1446)

E/AndroidHarness( 1929): at android.opengl.GLSurfaceView$GLThread.run(1216)

E/AndroidHarness( 1929):

mhhh i don’t get what’s the issue. Why is it using the DesktopAssetManager…?

could you post your activity code? do you do something special in it?

Yeah, you messed up something, maybe be doing additional steps that seemed logical to you. Here’s the rundown on getting a jme3 android app to work on a blank windows, mac or linux pc.

  1. Install JDK 6
  2. Install and update jME SDK
  3. Install and update Android SDK incl. 2.2+ Android image
  4. Create BasicGame project (do NOT add any android libraries to the project, it does so automatically for the android part)
  5. Go to project settings and enable Android deployment
  6. Disable “Compile on Save” in the project settings
  7. Right click project and make it the main project
  8. Select “Android Device” as run setting (next to the play button)
  9. Connect android phone to pc
  10. Press run button
  11. See blue box on device
  12. Press “x” next to run state (lower right) to stop logging

hmm…I actually have 2 apps works on andriod right now…

  1. A customized ‘new project’ based off of the BasicGame new project.
  • updated this to enable me to test some performance/behavioral differences between desktop/andriod.
  1. My actual game (the only issue here is the audio).



    I will go ahead and try to reproduce the audioNode issue using the Basic Game project.

ok, well I was able to repo the exact same stack trace with my test project, not sure of the best way to get the code to you all…so…



I have uploaded the test project to google-code, link is:



http://test-andriod.googlecode.com/svn/trunk/



The gist of test-project (its pretty basic): it enables users to modify materials on the fly for the ‘provided’ object(s).

(the entire project with apk/etc was uploaded)



There is readme in TestAndriod (root directory) that points out a few things for the main.java.



In summary:

On the Desktop the app performs as expected.

On Android a few things:

  1. If the AudioNode load is enabled the crash from above will appear.

    – Note: both on desktop/android for the purposes of this code base…the audio is never actually played.

    – the audio node is loaded in by default: it needs to uncommented)
  2. The floor does not render on android as expected.
  3. The sphere closest to the camera renders oddly on android.





    fyi:

    On my desktop I get ~2500fps (vertexLighting) 2200 fps non vertex lighting)

    On android I get 15fps (vertexLighting) 18fps vertex lighting.



    note: andoid version: 4.0.3

    device: asus tranformer pad TF300T

Well I just tried uninstalling/reinstalling the sdk.



In regards to the audioNode issue with and .wav files I get the same issue.



This time I created a new project, and added android support as normal.



I tried 3 tests:

  1. Load with no audioNode referencing a .wav — load with no issue
  2. Load with audio reference to .wav in jmonkeys asset path

    – crash
  3. Load with audio reference to .wav that simply exists no where.

    – crash



    IN both cases 2 and 3 this was the resulting stack trace: (again with the DesktopAssetLoader)

    E/AndroidHarness( 2627): java.lang.IllegalStateException: No loader registered for type “wav”

    E/AndroidHarness( 2627): SEVERE AndroidHarness 6:13:29 PM Exception thrown in Thread[GLThread 252,5,main]: at com.jme3.asset.DesktopAssetManager.loadAsset(248)

    E/AndroidHarness( 2627): at com.jme3.audio.AudioNode.(182)

    E/AndroidHarness( 2627): at com.jme3.audio.AudioNode.(209)

    E/AndroidHarness( 2627): at com.jme3.audio.AudioNode.(232)

    E/AndroidHarness( 2627): at mygame.Main.simpleInitApp(32)

    E/AndroidHarness( 2627): at com.jme3.app.SimpleApplication.initialize(231)

    E/AndroidHarness( 2627): at com.jme3.system.android.OGLESContext.initInThread(260)

    E/AndroidHarness( 2627): at com.jme3.system.android.OGLESContext.onSurfaceCreated(211)

    E/AndroidHarness( 2627): at android.opengl.GLSurfaceView$GLThread.guardedRun(1446)

    E/AndroidHarness( 2627): at android.opengl.GLSurfaceView$GLThread.run(1216)

    E/AndroidHarness( 2627):



    Code for the basic game is shown below:

    [snippet id=“38”]

I’ll test that