The big Android noob thread inc. Optimising + more

Monkey Targets Forums/Android/The big Android noob thread inc. Optimising + more

Grey Alien(Posted 2014) [#1]
Hey all, I've been researching possible Android game dev pitfalls by trawling through these forums (went over a year into the past) and so far I've come up with this list but can you suggest anything more and is any of this stuff out of date? Thanks for your help!

ALSO is there some kind of "how to setup Monkey X to compile fpr Android and run on an Android device etc." reference you can point me too? Thanks!

Optimisations:

1) Use object pooling (e.g. particles, bullets, sprite etc) so that you aren't allocating memory a lot in the main game loop. Or is this more just for older devices?
2) Use Sprite atlases to avoid texture swapping as much as possible.
3) Avoid changing alpha and colour as much as possible (what about scale?) Also not changing blending mode a lot (e.g. from normal alpha to Additive)
4) Precache images as you load them (to avoid stutter on first upload to VRAM/CPU)
5) Manually cull off-screen objects when rendering (is this really necessary? Someone suggested there may be better optimisations.)
6) Additive blending is slow (is that only true for old devices?). I was going to use this for particle effects. Perhaps I could only show particles on more modern OSes if I can detect that?

Some general questions:

1) What is the minimum version of Android OS I should target for decent performance and to avoid hassle? I don't mind excluding some old users if I don't have to code as many workarounds and I can ship a better game and not get bad reviews from people with crappy phones/tablets.
2) I read that early Android had problems with textures over 1024x1024. But is it safe to use 2048x2048 if I filter out older devices?
3) What sound format to use? I read ogg is best for music, but is wav OK for sound effects? (I heard that oggs may have a lag on some systems)
4) Do APK files still need to be <50Mb?
5) Do I need this Angelfont fix for plain fonts or is it just for older OSes with bad GC: http://www.monkeycoder.co.nz/Community/posts.php?topic=4964
6) Do I need to do anything in the manifest to be able to save/load data or do I just use brl.datastream for LoadString?
7) How can I find out more about the manifest file and signing apks? I've heard this mentioned but I really know nothing about it.
8) A year or two ago some Android devs were going on about there being 3 different texture types in use or something, and making sure your app supported them all so it ran on all devices. Is that true or does Monkey X handle it?

Super-thanks in advance for any help you can offer.


therevills(Posted 2014) [#2]
Wow, lots of questions!!

ALSO is there some kind of "how to setup Monkey X to compile fpr Android and run on an Android device etc." reference you can point me too?

Here's one I did ages ago: http://www.monkeycoder.co.nz/Community/posts.php?topic=1014&post=8800

These days you can skip steps 5, 6, 7, 8f and 8g by adding the following to your source code:
#ANDROID_APP_LABEL="Flying Flappy Monkey"
#ANDROID_APP_PACKAGE="com.therevillsgames.flyingflappymonkey"
#ANDROID_SCREEN_ORIENTATION="portrait"              'one of: user, portrait, landscape
#ANDROID_VERSION_CODE="1"
#ANDROID_VERSION_NAME="1.00"
#ANDROID_KEY_STORE="../../yourProject.keystore"
#ANDROID_KEY_ALIAS="yourProject.keystore"
#ANDROID_KEY_STORE_PASSWORD="123456"
#ANDROID_KEY_ALIAS_PASSWORD="123456"
#ANDROID_SIGN_APP=True

Strict

Import diddy

Function Main:Int()

And then just compile your game in release mode (for more performance).
Or a pure Android one can be found here: http://docs.apportable.com/publishing.html

1) Use object pooling (e.g. particles, bullets, sprite etc) so that you aren't allocating memory a lot in the main game loop. Or is this more just for older devices?

I would suggest using it, its best practice but yes it is more for older devices (<2.3).
2) Use Sprite atlases to avoid texture swapping as much as possible.

Correct - create your atlases with a maximum of 1024x1024 for best compatibility, I recommend TexturePacker Pro.
3) Avoid changing alpha and colour as much as possible (what about scale?) Also not changing blending mode a lot

I haven't found this to be too much of an issue myself.
4) Precache images as you load them (to avoid stutter on first upload to VRAM/CPU)

Yep, but if you are going to use atlases, you will only need to draw one sprite from that atlas and the entire atlas is cached.
5) Manually cull off-screen objects when rendering

Yep, it doesn't take much to do and it does help performance - I've tested this on a few devices myself.
6) Additive blending is slow (is that only true for old devices?). I was going to use this for particle effects. Perhaps I could only show particles on more modern OSes if I can detect that?

It all depends on what devices you are targeting. The more you add the slower it will be. Yes you can detect what OS they are running but its the hardware which will push them around.

1) What is the minimum version of Android OS I should target for decent performance and to avoid hassle?

Android 2.3 came with a better GC which helps when creating new objects at runtime - but I would still be careful of this.
2) I read that early Android had problems with textures over 1024x1024. But is it safe to use 2048x2048 if I filter out older devices?

OpenGL ES1 has the limitation of 1024x1024, so any device which is still running that will still have the limitation. Again I would create them as 1024x1024 to be safe.
3) What sound format to use? I read ogg is best for music, but is wav OK for sound effects? (I heard that oggs may have a lag on some systems)

Android has a really bad latency for sounds in general - I use OGGs and its fine and saves space.
4) Do APK files still need to be <50Mb?

You can spilt them up and use expansion files.
5) Do I need this Angelfont fix for plain fonts or is it just for older OSes with bad GC

There are a few of us working on modules to "fix" fonts in Monkey:
http://www.monkeycoder.co.nz/Community/posts.php?topic=8190
http://www.monkeycoder.co.nz/Community/posts.php?topic=8262
Currently I am using my own and/or Ziggy's FontMachine.
6) Do I need to do anything in the manifest to be able to save/load data or do I just use brl.datastream for LoadString?

For the Mojo LoadString you don't need anything, and I believe the default manifest is already set up to read internal files.
7) How can I find out more about the manifest file and signing apks?

See above answers.
8) A year or two ago some Android devs were going on about there being 3 different texture types in use or something, and making sure your app supported them all so it ran on all devices. Is that true or does Monkey X handle it?

Not quite sure what you mean here. MonkeyX will load in pngs and its fine for all the devices I've tested on... or you could mean loading different resources depending on the DPI of the device - if so you need to code this yourself: If DPI > 500 Then texture = LoadImage("BigTexture.png") else LoadImage("SmallTexture.png").


rIKmAN(Posted 2014) [#3]
Sorry to hijack this, but I have an Android question to add, so it seems better to add it here than another thread.

9)
On iOS there are basically only 3/4 resolutions to work to, so it's easy enough to create a few different sets of assets, load them at runtime and then let autofit scale them if needed.

With so much fragmentation in the Android market, what is the suggested Monkey approach for dealing with all the different for Android resolutions without having way too many sets of assets?


therevills(Posted 2014) [#4]
With so much fragmentation in the Android market, what is the suggested Monkey approach for dealing with all the different for Android resolutions without having way too many sets of assets?

We went thru a lot of options the other day regarding resolutions here:
http://www.monkeycoder.co.nz/Community/posts.php?topic=8229&post=83146

With assets, currently I am only using one set of assets and a set resolution - but I think the best solution is to target two resolution HD and SD (with the same aspect ratio), then create assets just for those resolutions and you should cover a wide range of devices.


Nobuyuki(Posted 2014) [#5]
3) What sound format to use? I read ogg is best for music, but is wav OK for sound effects? (I heard that oggs may have a lag on some systems)


Might as well use OGG. The penalty is only for when first loading them into a SoundPool, not during playback. Unfortunately, SoundPool has a limit of 1mb raw, and mojo only allocates one of these for the entire audio system, so try to keep your sounds as short and simple as possible when loading them into memory, or else some sounds will silently fail to load (no pun intended). There really should be a fix for this, but since heap limits are already ridiculously low on some devices, I don't see it happening, unless it's given to us via precompiler directive.

5) Do I need this Angelfont fix for plain fonts or is it just for older OSes with bad GC


With angelfont-tryouts, you can load with XML again and it should be faster than the previous iterations of AngelFont. The GC remains the same no matter what OS unless you change the target API in the application's manifest, AFAIK. This means that sweeps can still eat up a lot of your frame time, and if too large, will cause visible hiccups. I forget what the minimum API level to set was to basically force the new GC into use, but there was a thread on it somewhere. LoadPlain() is still useful if you prefer its format for readability better.

8) A year or two ago some Android devs were going on about there being 3 different texture types in use or something, and making sure your app supported them all so it ran on all devices. Is that true or does Monkey X handle it?


Hardware texture compression is one of the most badly-fragmented parts of the Android ecosystem, and I wouldn't even mess with it. The advantages to your game wouldn't be that great vs. the other optimizations, anyway, considering how much work it would be to support all of the systems. It's easier just to load lower resolution textures on crappier devices.


Grey Alien(Posted 2014) [#6]
Wow GREAT answers thanks @therevills and @Nobuyuki

Ok it sounds like I'm on the right track. To clarify a couple of things

@therevills my question 8) was about texture compression (but I wasn't clear) which @Nobuyuki has answered now, so that's cool.

@Nobuyuki One of the threads I found mentioned lag when loading oggs into the soundpool (even small ones) and something about stopping the soundpool from flushing itself by leaving a silent looping sound playing. Pretty weird stuff. Anyway, so are you saying that no (raw) sounds should be over 1MB or that ALL sounds need to fit within 1MB because that's a crazy crap limitation. To check raw size I should just turn into a wav right?

@Nobuyuki When you say it's easy to load lower res textures on crappy devices, how could I determine that it's a crapper device in code to make that decision?

@rIKmAN I'm using the autofit module and currently have one set of assets. However, I'm checking the device DPI and screen resolution so that I can figure out if the device is approximately a phone or tablet size (in the real world), and then I slightly alter the control set (make buttons bigger on phones for example). I guess the same approach could be used to change assets too, or just check DPI and decide if it's HD or SD and change assets for that.


Grey Alien(Posted 2014) [#7]
@Nobuyuki Also I found some threads that mention which SDK verison to use to cut out crappy GC:


Go to /targets/android/template/templates and open the AndroidManifest.xml

Look for:

<uses-sdk android:minSdkVersion="3" android:targetSdkVersion="7" />

And change it to anything you want.

The new GC is integrated since Android 2.3. Using android:minSdkVersion=9
Kicks around 15% of the user but avoids the stuttering because of the old not concurrent garbage collector.




Grey Alien(Posted 2014) [#8]
By the way I was considering limiting to v 4.0 of the OS because I read some current Google stats that showed it would only cut out 19% of users. I don't think that's too bad especially considering that I'd have to do lots of optimisations for older crapper devices and also people with a new OS are more likely to spend money on games.

Still I guess it's possible to have an underpowered phone still running 4.0 or higher right?


Grey Alien(Posted 2014) [#9]
One more thing how much VRAM should I expect on modern devices (as a minimum)? I ask because if I precache TOO much stuff then it could push out textures that were cached first. Really I should only precache what I actually plan to use on the current screen (and not like options screen stuff if that is not showing for example)


therevills(Posted 2014) [#10]
By the way I was considering limiting to v 4.0 of the OS because I read some current Google stats that showed it would only cut out 19% of users.

That is still a large chunk of the market.

Here are my Pirate Solitaire current stats:


And heres the total installs:


Still I guess it's possible to have an underpowered phone still running 4.0 or higher right?

Yep, but I believe that Android 4+ requires an ARMv7 processor.


Nobuyuki(Posted 2014) [#11]
One more thing how much VRAM should I expect on modern devices (as a minimum)? I ask because if I precache TOO much stuff then it could push out textures that were cached first. Really I should only precache what I actually plan to use on the current screen (and not like options screen stuff if that is not showing for example)


Don't worry about it. Focus on organizing atlases closer to each other in the draw order so there's less texture thrash instead, I'd say. I don't remember if ARM has a separate VRAM/RAM architecture, or if you're dipping from the same resource pool. Your app though in standard RAM has a heap limit which you shouldn't expect to be larger than 24mb on a phone approximately 2 years old. You'll know when you hit it, because your app will crash and you'll be able to see the error in logcat.


Grey Alien(Posted 2014) [#12]
@Therevills thanks for sharing. Looks like a lot have 2.3.3 then. Any idea what "others" is?

@Nobuyuki so is the heap just for allocating memory to new objects or does it include all assets loaded (gfx, sfx, data)?


therevills(Posted 2014) [#13]
Any idea what "others" is?

The "Others" would be Android versions 1.5 thru to 2.0 - due to the age of the game (it was released in 2011) there were a lot of users at the time with those versions - that's why its so large for "Total Installs" and pretty small for "Current Installs".

Here's a link to the developer's guide for memory management on Android:
http://developer.android.com/training/articles/memory.html


Grey Alien(Posted 2014) [#14]
Ah I see thanks. So it looks like limiting to 4.0 would cut out 28% based on your stats. That is quite a lot. Thx for link too.

OK I read the link. Have you ever used Monkey commands to call getMemoryClass() and see how much heap the app has? Also are there other related commands to see how much of that has actually been used? Or should this be done through some kind of debugger (I use Instruments on iOS to check the mem use)? (I found this page: http://developer.android.com/tools/debugging/debugging-memory.html)

Also does Monkey automatically call zipalign or is that a manual task? "Note: Google Play Store does not accept APK files that are not zipaligned."


AdamRedwoods(Posted 2014) [#15]
Also does Monkey automatically call zipalign or is that a manual task? "Note: Google Play Store does not accept APK files that are not zipaligned."

Yes. ANT will auto-zip align. You can see it in the console output.
Keep in mind, you will need to apply your own developers key to the ANT process before delivering to Android stores.

is the heap just for allocating memory to new objects or does it include all assets loaded (gfx, sfx, data)?

all assets.


rIKmAN(Posted 2014) [#16]
Good info in this thread, thanks to all posters.

Just a couple more of my own...
What are the most common screen resolutions / aspect ratios on Android (ie iOS is 960x640, 1136x640, 1024x768, 2048x1536)
Does it even work like this on Android or do we have to use the DPI stuff?
Can two matching resolution screens can have differing DPI?


Supertino(Posted 2014) [#17]
Q: What are the most common screen resolutions / aspect ratios on Android (ie iOS is 960x640, 1136x640, 1024x768, 2048x1536)?
A: Resolutions can be all over the shop, aspects are most commonly 16:9 or 16:10 with some 5:3 mixed in to keep things interesting.

Q: Does it even work like this on Android or do we have to use the DPI stuff?
A: Best to pick an aspect and/or resolution and use Autofit or Autoscale to scale your game to the devices display.

Q: Can two matching resolution screens can have differing DPI?
A: Yes if their physical size is different such as a 7" tablet running a 720p screen and a 5.5" phone running a 720p screen.

Also be careful with DPI checking on Android;

It's tempting to use ...
displayMetrics.xdpi
displayMetrics.ydpi

... but are not reliable for returning true values, these are entered 90% of the time incorrectly by the manufacture of the device.

Instead ...
displayMetrics.density 

... should be used to return a bucket value; ldpi 120 (0.75), mdpi 160 (1.0), hdpi 240 (1.5) etc. It's not precise and some devices could be off by as much at 20% if their DPI does not fall bang on one of the bucket values but it's reliable to a point. I use this to load different media based on device DPI and to size UI elements.


bazmonkey(Posted 2014) [#18]
I'm still fairly new to android dev. The Monkey CONFIG settings are very handy and do most of the signing steps for you (though I worked it out in Eclipse too).

I use Logcat/Monitor to check for basic memory leaks/usage. Not all the emulators start-up on my mac mini, particularly the high dpi ones, due to ram I guess.

The issue with max texture size is the most confusing one for me. I found that my (crappy) 4.0 tablet can sometimes load 2048x textures, and sometimes not -- the allocated heap size seems to vary. The general advice I see is to stick with 1024x to be safe. (At what point could you use 2048x?).

My old phone running 2.3 has much better performance than my 4.0 tablet, so OS version is not a great guide either :/

The other thing I have yet to fully sort out is that Android has many 'inbetween' resolutions like 450x800, which don't really match the iOS sizes that I am used to. So I either scale up, scale down (via autofit), or add more asset sets (something between retina and regular iOS). I havent really attempted a proper solution based on dpi yet.

As for manifest permissions:
I added a 'supports-screens' section, ie http://developer.android.com/guide/topics/manifest/supports-screens-element.html. Not sure if vital or not.
Another thing I spotted - the manifest in the Monkey template has com.android.vending.BILLING enabled. In the Google Play store, apps with this permission are labelled as 'offering IAP', even if they do not, so I remove this one.


rIKmAN(Posted 2014) [#19]
Thanks Supertino and baz, again good info.

I just remembered why I decided to do iOS first before porting to Android - this screen stuff seems overly complicated for no reason.

Seems I have a lot of testing to do but without a device it will have to be all through Bluestacks, will this mess up DPI/resolution testing?


Grey Alien(Posted 2014) [#20]
@AdamRedwoods OK thanks for clarification on zipalign and heap

@bazmonkey great tips, thanks! Also that's a good one about removing com.android.vending.BILLING so that some customers don't get scared about IAP.

@rIKmAN This is the DPI thread I was looking at (and there's a link to another thread at the top). It also mentions to test on actual device not emulator. I wonder what DPI it'll return in emulator?: http://www.monkeycoder.co.nz/Community/posts.php?topic=5415#84657