All Things Android (Common Troubles and FAQ)

Hello friends,

After recognizing a series of common problems in developing Android applications I’ve decided to sum up my knowledge and hopefully address most of the Android specific problems related to Jmonkey engine.

Pretty much all of my programming experience comes from making Android applications in Jmonkeyengine and have experienced many of the problems I’ve seen myself. And trust me I have spent agonizing days and hours on trying to solve everything from black textures and terrain to getting those darn google advertisements to work.

Hopefully this thread will help beginners have the confidence to try their hand at an android application and people who are experienced maybe find a solution to that long time problem or even contribute some of their knowledge.

The hopeful goal of this thread is to create the beginning for more complete Android wiki as it is slightly outdated and doesn’t cover as many as the issues that users have trouble with, and rather than go changing the wiki, use the forums as a place to identify which issues are relevant and the best practice in which to approach them.

Getting Started:

1. How do I make my project an Android Application?

  First you must download the Android SDK for the Jmonkey IDE.

     https://developer.android.com/sdk/index.html?hl=i

 Download the suggested packages (Also the google-play-services if you plan on adding advertisements etc.)

 Make sure to "Download for an Existing IDE" if you plan on using it for the Jmonkey SDK      

  By editing your projects properties by setting a custom configuration 
    1. Disable compiling on save Build->Compiling and unchecking the box.
    2. Enable Android Deployment and Click okay

  If it is your first time it will ask you for the Android SDK Folder. Simply navigate to the proper folder in the file browser that will pop-up

  Now when you build your project you will have an "APK" in your dist folder and you can now test your project on an android device (assuming it is connected to your pc).

  While any project can be deployed whether or not it will work is a different story. Unsurprisingly Android is not as forgiving as pc on file size and fps so scenes and textures must be kept simple and most importantly controls must be made with a touch screen in mind.
2. My project is now an Android Project. How can I test it?
 Setting the project configuration to "Android Device" at the top the SDk.

 *Common Issues for this step*

   "My game is launching normally in PC even though it says 'Android Device' please help!"
     <em>You do not have "Compile on Save Disabled" Disable it in the Project Properties.</em>

   "My game crashes instantly cause I get **** error!"
      <em>See will be covered in next post</em>

3. My Project Is Perfect! How do I create a “signed” version for release?

Once your project is perfect and ready to go and you’re ready to sign it and release it to the world you first must create a “keystore.”

To create a keystore (I assume Java programmers have the SDK on call via an environment variable) simply open your command prompt and type

  <em>keytool -genkey -v -keystore my-release-key.keystore -alias alias_name -keyalg RSA -keysize 2048 -validity 10000</em>

Once your keystore is created you you must edit your project properties to reflect the location and alias you used when you created your keystore.
These properties can be found in the “Important Files” package that is created automatically when you enable Android Deployment for your project.

It will now prompt you for the password you used when you created it. Type in the password and you will now have a “release APK” in the “dist” folder of your project.

You are now ready to upload your project to the Google Play Store!

But wait!

“I want to add game saving and Ads and my own Icon and loading screen!”

Or

“I’m still having bugs with xxxx and am not ready to deploy”

Never fear!

The next post will cover common bugs, the advertisements and loading screens and icons.

9 Likes

The Common Android Specific Issues

Sometimes you will find your project working perfectly well on pc, but on Android something just isn’t right. Having run into these problems more than a few times and seeing others have too I’ve compiled a list of problems and common solutions.

1. “Help! People are complaining about Black Models! But I can see the models fine on my pc/android device!”

This is a problem with terrain currently on all devices and with regular material on what seems to be older devices (specifically samsung devices) in which textures that are not perfect squares xx yy etc. Also these textures must be a power of 2. So 64x64 128x128 etc. REMEMBER! Even though they look fine on your device doesn’t mean they work for everyone.
Be SURE to use perfect squares.

If your issue is with black terrain you will have to invert your terrains alpha map (this is reportedly fixed in the upcoming 3.1).

But currently this can be easily done in gimp by opening the scenes terrain texture in your Projects Assets-Textures->terrain-alpha directory

Then follow these instructions

  1. Choose “Colors -> Components -> Decompose” from the menu and set
    “Color model” to “RGBA”.
  2. A new image is opened with all color channels (including alpha
    channel) decomposed as single layers.
  3. Select the layer “alpha” and choose “Colors -> Invert” from the menu.
  4. Choose “Colors -> Components -> Compose” from the menu, set “Color
    model” to “RGBA” and make sure the layers are correctly mapped to
    the channels (should be given if you did not reorder the layers)

2. “Help I get an Out of Memory Error when xxx Happens!”

Out of Memory Errors will occur 99% of the time due to having too large of textures. NEVER use a texture that is 10241024. 512512 should be your MAXIMUM and you should have a reason to do that. For Android using 6464 or 128128 usually does the job.

Other cases are your object count is too high or your game logic is hicupping but not causing a stack overflow.

Check your loops and be sure you’re properly de-referencing all the things if you are depending on the garbage collector. Just because you cant SEE it in the scene doesn’t mean it’s not in memory

3. “HELP the touch events aren’t working properly as mouse events!”

Be sure that you enable the "Simulate Mouse" feature for the input manager. This can be done through inputManager.setSimulateMouse(true);+
4. "I get 0 Frames Per Second!"

While this is one of the biggest issues you’ll face developing for Android I’ve come up with a few rules for myself when creating scenes and games for Android.

1. No lights. Yes it's sucks to say but lighting is just too heavy for android (crossing my fingers for this "light culling" for 3.1) but for now... 
This means that your terrains will only be able to have 3 layers as that's all that is allowed for unshaded terrains.

Luckily you won't have a lot of work as I've written quite the nifty method to turn any node into unshaded materials. Simply run this method on your root node and it will 
take care of the rest for you.

http://hastebin.com/mubuzofina.avrasm
  1. 30,000 Vertices MAX. If your scene has more than 30,000 vertices your game will suffer. It may be playable on your device but all devices will not. I use an older Galaxy Tab 2 and my rule
    is if it works there its good. Older devices will have to deal with it. But if you’re on the latest Galaxy and you’re skipping and lagging. Then other devices will be unplayable. A good scene
    will have 10-20k and if you MUST 30k should be your limit.

  2. No Filters… Though I have not tried all filters I have found that water and fog are pretty much out. If someone has success otherwise please tell me.

  3. Limit Particle Emitters to 25 particles and 5 particles per second… Your players will probably forgive your imperfect fire before a laggy game.

5. “I have errors in my MainActivity.java and I don’t know why!”

Always attempt to clean and build your project… Your android project uses a different folder for it’s reference libraries, that means your Main Activity does. By cleaning and building the project you will update the Android Project’s libraries and references, and the errors will disappear on build.

NEVER edit the files in the Mobile Project directly without a specific reason.

6. "My Game is way too big! Why is this?"
Remember... this is an Android game and people don't have terabyte hard drives and 24/7 wifi. They will want to download your game on the go and 50 megabytes is quite a lot to commit to your game.

Any larger than 50 MB you should really be a true believer in your game.

Otherwise you will definitely want to keep your file sizes as small as possible and this can get out of hand very quickly. So I’ve come up with a few rules for myself on file size.

  1. Covered before but keep your textures as small as possible. The difference between a 256x256 and 64x64 is a LOT of space. So if you have a lot of models with a lot of textures, you will
    definitely want to make your textures as small as possible.

  2. No Shadow Maps Glow maps… Trust me, you won’t be using lighting (as of now) and those things are just going to take up space. Delete them. They might make your scene look nicer in the
    scene composer but once you go to unshaded materials (see my method above)

  3. **Important tip for those who use the Scene Composer. ALWAYS LINK DO NOT ADD.

Always link the models in the scene composer. Adding the items creates an entire copy of the model in your scene. Keep your scenes under 4mb.

7. My Game Crashes When it closes/ Doesn’t close properly!

In this case you will need to add the following method to the MainActivity.java in the Important Files section of your project

@Override public void onDestroy() { super.onDestroy(); System.runFinalization(); android.os.Process.killProcess(android.os.Process.myPid()); }

8. My game is draining peoples battery/making my device too hot!

Limiting your game to 30 fps will stop the gpu from doing so much work heating the device and saving your users batter! Of course if you are going over 30 fps perhaps you could add some more
features to your game! If not congratulations on making such an efficient application!

9. “I get IllegalArgumentException: object id must be greater than zero!”

This occurs when objects are added and removed from the scene quickly. The exact cause of this error is unknown to me, but the solution is to slow down the creation and removal of objects in the scene.
5 Likes

Useful Tips and Stuff for your Apps

Of course since you plan on having other people play your applications you would want the shiny loading screens and custom icon.

Perhaps some advertisements from google play in your game. Well through mind numbing processes I’ve gotten those things down to a science.

Also you might want some models for your games but the ones you’ve been using are far too big and complex for Android!

Read on!

1. I want a nice icon to appear on the android screen!
If you want an icon (the one that appears on the devices home screen or whatever) just:

1. Create an Icon
2. In the Files window go to your Project-&gt;Mobile-&gt;Res
3. In this Folder there are 4 Folders with the names xxx_Drawable
4. The Default Icon will be called ic_launcher.png. You can delete this and repace with your own.
5. Go back your the projects window, go to important files. Go to your android manifest and change &lt;application android:icon="@drawable/ic_launcher" to the name of your new icon.
2. I want a super cool loading screen when my app opens!

A loading screen when the app opens is a splash screen. If you want one to pop up follow these instructions:

1: Locate the Drawables folders in your projects Files YourProject->Mobile-res->***_Drawable
2. Place your splash screen in these folders
3. Open your MainActivity.java in your projects Important Files
4. In the constructor method (The MainActivity() method) just add the line
splashPicID = R.drawable.thenameofyourimage;
so if your splash picture is splash.png you would add
splashPicID = R.drawable.splash;

3. I want to have advertisements from Google Play Services!

These Instructions are for banner ads*

Of course a lot of us do our work for free… But that doesn’t mean we can’t put some advertisements in there! So if you want to take
advantage of google play services advertisement features and don’t want to go through days of rage as I did, simply follow these instructions:

1. Download the google-play-services.jar from the Android SDK.
2. Right click your libraries folder and add the jar to your project
3. CLEAN AND BUILD YOUR PROJECT! Adding the jar to your project doesn't add it to the mobile project right away. If you wont clean and build your
MainActivity will not have access to the google play stuff. (The errors would fix on build but you will have to know the imports)
4. Okay... Here's were it gets a bit tough. You need to add an "integers.xml" into your Project-&gt;mobile-&gt;res-&gt;values directory
You will need to create this file
Copy and paste what is in here https://github.com/GoDieBawb/Village/blob/master/Village/mobile/res/values/Integers.xml
That link will also give you a reference to where the folder is.
5. In the values folder referenced above there is a pregenerated "strings.xml", this is also where you set the name of your application as it appear on the device.
You need to add a line that says "&lt;string name="app_id"&gt;App Name&lt;/string&gt;"
An example and a reference of where to find it can be found here. (in the same folder you should add the integers.xml in step 5)
https://github.com/GoDieBawb/Village/blob/master/Village/mobile/res/values/strings.xml
6. Now... In the Important Files section of your project. Go to your android manifest

And place these lines in the application section of your Manifest.xml

` &lt;meta-data android:name="com.google.android.gms.games.APP_ID"
android:value="@string/app_id" /&gt;
&lt;meta-data android:name="com.google.android.gms.version"
android:value="@integer/google_play_services_version"/&gt;`

Also these two lines are added in the manifest section.

&lt;uses-permission android:name="android.permission.INTERNET"/&gt; &lt;uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/&gt;

For a reference of how this is done here is an example of a complete manifest of my Manifest.
https://github.com/GoDieBawb/Village/blob/master/Village/mobile/AndroidManifest.xml
  1. Finally, Go to your main Activity located in the important files section of your project.

Override the onCreate() method and create the advertisement as according to google-play-services
https://developers.google.com/mobile-ads-sdk/docs/admob/android/banner

Or of course what kind of tutorial would it be if I didn’t have an example.

*Note the adView is a field of MainActivity… So private AdView adview;

@Override public void onCreate(Bundle state) { super.onCreate(state); int androidVersion = android.os.Build.VERSION.SDK_INT; if (androidVersion &gt; 10) { adView = new AdView(this); adView.setAdSize(AdSize.SMART_BANNER); adView.setAdUnitId("THE AD UNIT FROM GOOGLE THAT THEY GIVE YOU"); adView.buildLayer(); LinearLayout ll = new LinearLayout(this); ll.setGravity(Gravity.BOTTOM); ll.addView(adView); addContentView(ll, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); AdRequest adRequest = new AdRequest.Builder() .build(); // Start loading the ad in the background. adView.loadAd(adRequest); adView.bringToFront(); adView.requestFocus(); } }

REMEMBER create an admob account and enter the proper number up there... It's not magic.

8. Collect dat money!

4. I want to tell which operating system I’m on what’s the easiest way to do this?

Great question for any person who has half a brain! Why do all the work on pc… and why not just have the different controls set up.

Just a simple

boolean isAndroid = "Dalvik".equals(System.getProperty("java.vm.name"));

And you know what you need to! And knowing is half the battle!

3 Likes

This is really excellent stuff. I’ll give other developers some time to contribute their own gotchas and then we should throw this into a blog post with credits to all co-authors.

2 Likes

Might also make sense to simply add this to the documentation at http://hub.jmonkeyengine.org/wiki/doku.php/jme3:android

2 Likes

@normen

That is the intention of this thread to in the future to update the android wiki you just mentioned. The plan is to get enough input to get to an appropriate point to go start updating the wiki.

But hopefully soon we will have a more complete identification of the Android specific issues and a really great wiki to go with the awesome android deployment!

3 Likes

Awsome Thanks !!

few comments for the Google Ad part: in your MainActivty.java you need to add the following imports :

import com.google.android.gms.ads.AdView;
import com.google.android.gms.ads.AdSize;
import com.google.android.gms.ads.AdRequest;
import android.widget.LinearLayout;
import android.os.Bundle;
import android.view.Gravity;
import android.view.ViewGroup;

Pretty cool collection of information you have there :). I would add that you should use a minimum of Android 3.0 (API 11), as this a) rules out the older phones (< 10% of the market), which probably can’t handle the graphics anyways, and you also (and more importantly) need it if you want to be on the Google Play ‘Designed for Tablet’ section.

Other tips would be to preload all models (and if you are using them for picking, then create the collision data at the same time), to reduce pauses while things are generated/loading. Batch as much as possible, low object count is crucial. The stats screen generates a lot of garbage, so keep that in mind. Garbage collection is probably the biggest killer, and the thing which makes the garbage collector takes a long time is not freeing unused objects, it’s having to trawl through all the alive objects looking for the actual objects to free!!

There are a few things in the engine I had to change to reduce GC. I will have to create a post about them at some point. I remember one was about the .ogg vorbis loader. I ended up using the AndroidMediaPlayer.

For skeleton animation, make sure you use HW skinning, and I found that the number of bones has to be quite small (< 20), otherwise some devices won’t be able to load all the necessary skinning data to the GPU.

Profile, profile, profile!!! There is a program that comes with the android SDK, which allows you to profile your app, generally only care about the memory allocations.

@wezrule said: Garbage collection is probably the biggest killer, and the thing which makes the garbage collector takes a long time is not freeing unused objects, it's having to trawl through all the alive objects looking for the actual objects to free!!
Have you attempted using object pools? Is it a viable strategy for e.g. reducing GC pauses by reusing particle effects or models which appear and disappear often?
@wezrule said: I remember one was about the .ogg vorbis loader. I ended up using the AndroidMediaPlayer.
All audio issues should be fixed in jME3.1. OGG/Vorbis files are now decoded in C++, and OpenAL Soft is used to play them with full 3D sound effects. The only thing Java code is doing is passing buffer pointers around ...
@wezrule said: For skeleton animation, make sure you use HW skinning, and I found that the number of bones has to be quite small (< 20), otherwise some devices won't be able to load all the necessary skinning data to the GPU.
I have some modifications locally which allows to double the number of bones that can be used. However, it disallows use of non-uniform scaling on bones. Unfortunately, the Jaime model uses non-uniform scaling and therefore cannot use this feature. I am not sure on how to implement this reliably and handle all edge cases.
1 Like

hello i have the following issue when adding Google Ads:

if i override the Android Main Activity class with this :

    @Override
    public void onCreate(Bundle state) 
    {
        super.onCreate(state);
        int androidVersion = android.os.Build.VERSION.SDK_INT;
        if (androidVersion > 10) 
        {
            AdView adView = new AdView(this);
            adView.setAdSize(AdSize.SMART_BANNER);
            adView.setAdUnitId("MyAdUnitID");
            
            adView.buildLayer();
            LinearLayout ll = new LinearLayout(this);
            ll.setGravity(Gravity.TOP);
            ll.addView(adView);
            addContentView(ll, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
            AdRequest adRequest = new AdRequest.Builder() 
                                        .addTestDevice(AdRequest.DEVICE_ID_EMULATOR)
                                        .addTestDevice("TEST_DEVICE_ID")
                                        .build();
            // Start loading the ad in the background.
            adView.loadAd(adRequest);
            adView.bringToFront();
            adView.requestFocus();
         }
    } 

as you can see the only difference i have with the provided example is that i add test devices.

i have the following error message when launching the application on android (off course i don’t have the issue on Desktop)

com.jme3.AssetNotFoundException:
Interface/Fonts/Default.fnt
Exception Thrown in Thread[GLThread2598,5,main]

I tried to create a Default.fnt font in my Assets Project folder and the problem vanishes BUT i have then an exception on Common/MatDefs/Misc/Unshaded.j3md
If i comment the method the issue goes away.
To be more precise it seems that the call causing the issue is : adView.loadAd(adRequest); as when commented the problem goes away. Off course no adds is added so it limits the added value of all the rest …
I don’t know what i missed on the project/and configuration files… Any lead ?

Thanks for your help

adView.loadAd(adRequest); as when commented the problem goes away.

Weird. Maybe wrap it in a try/catch(Throwable) to see if it is throwing an exception that then messes up the rest of initialization?

@Momoko_Fan said: Have you attempted using object pools? Is it a viable strategy for e.g. reducing GC pauses by reusing particle effects or models which appear and disappear often?
Yeh I used them a bit, it was TempVars in particular though. Most of my GUI in my recent game is just 1 object in a BatchNode (to allow for animation).

I created 2 to 10 Quads (depends on how many I need) of each object and batch them at the start. I made them all 1px big (so they were not visible), and when I needed an object I would just get it from the pool and resize as necessary.

@Momoko_Fan All audio issues should be fixed in jME3.1. OGG/Vorbis files are now decoded in C++, and OpenAL Soft is used to play them with full 3D sound effects. The only thing Java code is doing is passing buffer pointers around ...
Oh that's pretty nice :). I'm ashamed to say I'm still on a jME version a couple years old now.
@Momoko_Fan I have some modifications locally which allows to double the number of bones that can be used. However, it disallows use of non-uniform scaling on bones. Unfortunately, the Jaime model uses non-uniform scaling and therefore cannot use this feature. I am not sure on how to implement this reliably and handle all edge cases.
Ah nice. My original character was 2000 vertices and had about 100 bones in it. Fully IK rigged, 3 bones for each finger etc.. This allowed me to make some nice animations, but was not HW skinnable on my phone, and created so much garbage. I found a way to bake my animations into fewer bones (20 or so), and this allowed for GPU skinning, and I also Decimated my character to 300 vertices, and it works a dream now :)

@Woodworf

I’m pretty sure I know your problem

Here’s me going through it
http://hub.jmonkeyengine.org/forum/topic/android-game-release-bugs/#post-285466

Here’s an unfortunately unanswered thread with a similar problem
http://hub.jmonkeyengine.org/forum/topic/sometimes-assetnotfoundexception-interfacefontsdefault-fnt-thrown/

I’ve had it a trillion times before (also test devices aren’t necessary if you’re using a debug version of your APK)

But I had this problem a long time ago (I’m surprised I forgot to add it)

My guess is that you’re game is in Landscape and you’re opening in portrait.

You need to specify the screen layout in the manifest

android:screenOrientation=“landscape”

In the activity section of your manifest

Found here on line 10.

Also make sure you have the On Destroy method I posted above!

You must have the onDestroy method!

You rock it was that :

  1. android:screenOrientation=”landscape”
  2. onDestroy method

One additional remark : i had also to add the following in my manifest in the application node:
<activity android:name=“com.google.android.gms.ads.AdActivity” android:configChanges=“keyboard|keyboardHidden|orientation|screenLayout|uiMode|screenSize|smallestScreenSize”/>

Many thanks

@Woodworf

Awesome!

I can’t believe I forgot about this error after having had this issue for so long!

The problem happens when you open a game in the wrong mode (portrait in most cases) and it flips around. It destroys the activity and then restarts it which also leads to the problem with the lack of onDestroy() method.

I’ll update the topic

Hello i have 1 additional remarks/questions : I noticed a drop from ~30 FPS to ~20FPS just by adding the Ads.
Is there some special adivse i shoudl follow to avoid such a drop ? (i’m using Nifty for information)

Thanks for your help

Hello, i need to read/write into a file from android local storage.
In order to do so i would like to use the following snippet of code :

       public void writeToFile(String data)
       {
           try 
           {
                OutputStreamWriter outputStreamWriter = new OutputStreamWriter(openFileOutput(SAVE_FILE, Context.MODE_PRIVATE));
                outputStreamWriter.write(data);
                outputStreamWriter.close();
            }
            catch (IOException e) 
            {
                Log.e("Exception", "File write failed: " + e.toString()
            );
    } 
       }
       
       public String loadSaveFile()
       {
        String ret = "";

           try 
           {
                InputStream inputStream = openFileInput(SAVE_FILE);

                if ( inputStream != null ) {
                    InputStreamReader inputStreamReader = new InputStreamReader(inputStream);
                    BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
                    String receiveString = "";
                    StringBuilder stringBuilder = new StringBuilder();

                    while ( (receiveString = bufferedReader.readLine()) != null ) {
                        stringBuilder.append(receiveString);
                    }

                    inputStream.close();
                    ret = stringBuilder.toString();
                }
           }
           catch (FileNotFoundException e) {
               Log.e("login activity", "File not found: " + e.toString());
           } catch (IOException e) {
               Log.e("login activity", "Can not read file: " + e.toString());
           }
           return ret;      
       }

I see 2 options:

  1. i launch this code from my Main Activity and set a variable with the string content of the file into an object i will be able to access from the simpleInitApp() method.
    Question: how do i set this variable up ? How do i retrieve this data from SimpleInitApp ? Is it possible in the mobile project to add depedencies on my desktop project ?
  2. i call this code fromsimpleInitApp()
    Question: the issue i have is, from my Project i don’t know how to retrieve the Context Object of my Android Activity

Do you know how to do it ?

Well you’d have to use a little bit of both. you need to create a level of abstraction.
On JME’s side, make a java interface called for example SaveHandler with a loadSaveFile method.
Add a SaveHandler savehandler attribute to your simple application with accessors. Whenever you want to load your game call saveHandler.loadSaveFile();
Then, make your MainActivity implment SaveHandler and implement your loadSaveFile method with all android cooking.
Then override the onCreate method (don’t forget to call super.onCreate() ) then add app.setSaveHandler(this)

That said, for this particular example, we have a built in structure that I encourage you to use, because it will handle on the android things and will also work seamlessly on desktop.
We have a class named SaveGame that can save things for you as long as they implements Savable. So you just have to make you game files Classes Savable and implemrn tthe read and write method, then call SaveGame.save or SaveGame.load from JME’s side, and it’s gonna work.

Great thanks for the tips. I’ll try that !

You can create an app state in the main activity and pass the local string using the state manager.