My initial idea was to start at a
beginner level and explain from the very beginning how to make games
for iOS and Android. However, after starting to write, I realised
that I began duplicating a lot of information that is already out there.
So instead, I will be linking other
resources with the basic background knowledge for the concept we are
talking about - a sort of background reading for beginners - and then
explain on a more intermediate level some of the tricks that can help
you use these concepts most effectively. I hope that way this
tutorial will be more useful for both beginners and experts alike.
What you'll find here are a series
of sections covering various topics that I'm often asked about, that
you can read independently of the others.
Kam
Twitter: @Base2solutions
Facebook: http://www.facebook.com/pages/Walkabout/162352637156663
IRC: irc.freenode.net / #Corona
Contents
- Walkabout
- Corona
- Dynamic Image Resolution?
- Error Checking
- Functions
- Transitions
- Android Manifest Customisation
- Groups - removing images effectively [Coming Soon]
- Garbage Collection [Coming Soon]
- Preloading and performance tricks [Coming Soon]
- Performance Tricks 2 [Coming Soon]
- Suspend/Resume handling [Coming Soon]
- Optimising file sizes and music [Coming Soon]
1 - Walkabout

I recently created my first iOS and Android game called 'Walkabout'.
The whole game was made in my spare time in about 3 weeks.
I hope to pass on the tricks that I used to deal with the various
problems that arose during the development of Walkabout.
In these tutorials I will explain concepts in relation to Walkabout
and so I suggest you download the free version for either iOS or
android. The Lite version is totally free, uses no special
permissions and has no Ads.
App Store
http://itunes.apple.com/us/app/walkabout-lite/id423662209?mt=8&ls=1
Android Market:
https://market.android.com/details?id=com.base2.walkaboutdemo
2 -
Corona
Ordinarily, if you wanted to develop for iOS you would need to learn a
language called Objective-C. This isn't a very easy language for
beginners to pick up. Similarly for Android development you would need
to learn Java.
So, if you decided to make a game, and wanted to release it for both
platforms you would need to learn both languages (!).
Fortunately there is a much easier option. These days there
are many SDK's on the market called 'App or Game engines'. These
have a bunch of functions that help you do the common tasks you need
for applications and games. In addition they use a simpler
language
that's a lot easier to pick up.
My tutorial will use one such game engine called 'Corona'. It
is a free download, and you can use it as long as you like. The
code you write can be simulated on a 'virtual' phone on the screen.
Corona isn't totally free though. If you decide you want to
release your game on the App store or Android market you will need to
buy a license.
I encourage you to try your hand at writing games with the free
version, and if you decide this is for you, and manage to make a game
you want to release, you can buy the license at that point.
Corona is available for both Windows and Mac OS X.
You can download Corona here:
http://www.anscamobile.com/
If you are a total beginner to Corona, there are some good getting
started guides here that you should read first:
http://developer.anscamobile.com/resources/docs/
3 -
Dynamic Image Resolution?
Background
One of the first problems you'll encounter with developing on mobile
devices is the varying screen sizes (Resolution) and aspect ratios
(Ratio between the height and width of a screen). Your game may
look amazing on an iPhone 3G, but end up looking stretched, or even
worse leave blank areas on an iPad or Android Tablet.
Corona offers a function called 'Dynamic Image Resolution'.
This works together with Content Scaling to handle different
devices screen sizes. You can read more about it at these two
very good blog posts from Ansca.
http://blog.anscamobile.com/2010/11/content-scaling-made-easy/
http://blog.anscamobile.com/2011/01/dynamic-image-resolution-made-easy/
And the documentation can be found here:
http://developer.anscamobile.com/content/configuring-projects#Runtime_Configuration:_config.lua
Tricks.
So, we know all about the various content scaling modes Corona
offers, namely:
- "none"
-
turns
off
dynamic
content
scaling
- "letterbox"
-
uniformly
scales
up
content
as
much
as
possible,
while
still
showing
all content on the screen. This is similar to watching a wide screen
DVD
on a non-wide screen TV set, except that you can use off-stage content
to
fill the "bleed" areas rather than displaying black bars.
- "zoomEven"
-
uniformly
scales
up
content
to
fill
the
screen,
while
preserving
aspect
ratio. Some content may appear off screen, if the new screen has
a different aspect ratio
- "zoomStretch"
-
non-uniformly
scales
up
content
to
fill
the
screen.
All
content
will
remain on-screen, but it may be stretched vertically or horizontally.
These work well in a lot of situations, but what if you don't want
letterbox borders on your backgrounds AND don't want content off screen
AND don't want to stretch your entire game?
This is exactly the problem I had in Walkabout. If you try the
game on different devices you'll quickly see that the in game graphics
don't end up skewed or stretched, yet the title images fill the entire
screen. Here are some screen shots of Walkabout on iPhone, iPad
and Nexus.






The solution you'll find in the Ansca blog entry is to oversize your
images so that they bleed into the letterbox regions. The 'magic'
image size makes an assumption about the aspect ratios and screen sizes
of currently available devices.
With the number of new devices released on Android, particularly
tablets, I wanted a more universal solution.
In
Walkabout,
rather
than
use
dynamic
image
scaling
with
the
"@2"
type
notation
in the config.lua, I calculate the screen scale in code, and
use this to setup a ImageSuffix variable.
The
background
image
from
the
title
screen
you
can
see
above
is
saved in three sizes
as follows:
Filename
|
X
|
Y
|
Platform Target
|
Title-480.jpg
|
480
|
320
|
iPhone
(480
by
320
Screens)
|
Title-800.jpg
|
800
|
480
|
Nexus/Droid
(8xx
by
480
Screens)
|
Title-1024.jpg
|
1024
|
768
|
iPad,
Tablets
(1024
by
xxx
Screens) |
In
the
game
initialisation
code,
a
check
is
made
against
the
content
scaling
Corona is currently doing:
CODE
|
scale =
tonumber(string.format("%." .. (1) .. "f", 1/display.contentScaleY))
if scale
== 1 then
ImageSuffix = "-480"
elseif
scale == 1.5 then
ImageSuffix = "-800"
else
ImageSuffix = "-1024"
end
|
Checking
this
in
code
allows
you
to
make
decisions
per
graphic
rather
than in
the entire game. As a side note you can find the actual number of
pixels the device has by doing:
CODE
|
scaleX =
tonumber(string.format("%." .. (1) .. "f", 1/display.contentScaleX))
scaleY
=
tonumber(string.format("%."
..
(1)
..
"f",
1/display.contentScaleY))
pixelsX = scaleX * display.contentWidth
pixelsY
=
scaleY
*
display.contentHeight
|
By
using
scale
=
letterbox
in
the
config.lua
you
can
decide
programatically
if
and how you want to stretch the image:
CODE
|
letterbox = display.newImageRect( "Title" .. ImageSuffix .. ".jpg",
display.contentWidth,
display.contentHeight)
zoomEvenX = display.newImageRect( "Title" .. ImageSuffix .. ".jpg",
display.contentWidth
-
display.screenOriginX*2,
display.contentHeight * (1 -
display.screenOriginX*2 / display.contentWidth)
zoomEvenY
=
display.newImageRect(
"Title" .. ImageSuffix ..
".jpg",
display.contentWidth * (1 - display.screenOriginY*2 / display.contentHeight,
display.contentHeight
-
display.screenOriginY*2)
zoomStretch
=
display.newImageRect(
"Title"
..
ImageSuffix ..
".jpg",
display.contentWidth
-
display.screenOriginX*2,
display.contentHeight -
display.screenOriginY*2)
|
NOTE:
These
are
for
landscape
orientation.
4 -
Error Checking
The biggest annoyance and pitfall is basic errors caused by
typos. In Lua, unlike other languages, you don't need to declare
variables.
http://www.lua.org/pil/1.2.html
If you use a variable without declaring it, it becomes a global.
This can cause uncaught errors if you have a typo. Consider the
following:
CODE
|
local
levelComplete = true
if LevelComplete == true then
print("you won")
end
|
Notice
the
typo,
'LevelComplete'
with
a
capital
'L'.
Lua/Corona
won't
catch
this
and
instead make 'LevelComplete' a new global, and of course
it will never be set to true, and so you could never win this game!
To get around the problem you can add this code to the beginning of
your main.lua to catch these issues. This will prevent ALL
globals from being declared, and so would catch the above by displaying
an error.
CODE
|
function
declare (name, initval)
rawset(_G, name, initval or false)
end
setmetatable(_G, {
__newindex = function(_ENV, var, val)
if var ~= "tableDict" then
error(("attempt to set undeclared
global\"%s\""):format(tostring(var)), 2)
else
rawset(_ENV, var, val)
end
end,
__index = function(_ENV, var, val)
if var ~= "tableDict" then
error(("attempt to read undeclared
global\"%s\""):format(tostring(var)), 2)
else
rawset(_ENV, var, val)
end
end,
})
|
if
you
do
want
to
use
a
Global
then
you
need
to
use declare as below:
CODE
|
declare("Levels")
declare("BonusLevels")
|
Here Levels and BonusLevels are two globals. You should use
this for debugging and in your final build comment them out. I
personally leave a multi line comment --[[ and ]]-- around my
debugs so I can quickly comment them in and out. Remember comment
out the whole block, even the declares as they will automatically
become globals.
Another good debugging technique is to use print("error") etc in your
code. I'm sure you are familiar with that already, but in case
you didn't know these prints also show in logcat on Android and the
xcode organiser's Console window on the device. On iOS you should
turn off the output buffer if your messages are lagging:
CODE
|
io.output():setvbuf('no')
|
Again leave this in the big block at the top of your file and comment
it out for the final release build!
One last error checking mechanism is xpcall. This is a lua
function that calls the passed function in protected mode. It
will catch any errors in that function and call the second function
that you pass it. For example:
CODE
|
xpcall(LoadLevel, ErrorHandler)
|
If an error occurs in LoadLevel it will call ErrorHandler() to
handle it. This is good to handle strange errors like with
partially written suspend/resume/save files. In Walkabout, the
calls to my file load functions all use xpcall. If an error is
detected the save file is deleted and recreated. It's an easy
short cut, rather than having to implement complex save file checking
mechanisms.
However when debugging it will also catch those errors and you won't
get an error message in the Corona log window! To override it for
debugging purpose just add this to the top of your code:
CODE
|
local function xpcall (f, a)
f()
end
|
Again leave this in the debug block at the top of your file and comment
it all in one go for release builds.
DON'T be lazy and use xpcall for functions that you know have an
error. Spend the time to debug the function properly.
You'll be much
better off in the long run!
5 -
Functions
In most Corona docs I see functions being defined in this format:
CODE
|
hello("bob")
local function hello (a)
print("hello" .. a)
end
|
The above code would actually give you an error, as the function
'hello' isn't defined until after
it is called. You could re-arrange the code so that the call to
'hello' was after the function definition, but this isn't always
convenient. It cant get a little complicated trying to find an
order that works when you have functions calling other functions which
in turn call other functions.
Instead it's better to get into the habit of defining functions like
this:
CODE
|
-- My Functions
local hello
-- Main code
hello("bob")
hello = function (a)
print("hello" .. a)
end
|
Define variables for all the functions you will use at the top of your
main.lua, and then don't worry about the order you define them.
You can then group functions together in a more logical way - one that
fits with sections of your game. e.g.. Title functions, In Game
functions, End Level functions etc.
Another situation which led me to some bad habits was dealing with
functions like performWithDelay. These expect a function pointer,
and so cannot handle functions with parameters:
CODE
|
-- My Functions
local hello
hello = function (a)
print("hello" .. a)
end
--
Main
code
timer.performWithDelay(500, hello("bob")) --
ERROR
timer.performWithDelay(500,
hello)
--
Valid,
but
how
to
pass
"bob"
as
a
parameter?
|
The solution is quite simple:
CODE
|
-- My Functions
local hello
local closure
hello = function (a)
print("hello" .. a)
end
closure = function()
hello("bob")
end
--
Main
code
timer.performWithDelay(500, closure)
|
This works, but if we wanted to pass "Tom" next time, we would have to
create another closure function. It's not a great solution.
Fortunately Lua lets you define functions anywhere, even in the middle
of performWithDelay:
CODE
|
-- My Functions
local hello
hello = function (a)
print("hello" .. a)
end
--
Main
code
timer.performWithDelay(500, function() hello("bob")
end)
|
This is a much more elegant solution, and doesn't leave a bunch of
single use functions laying around in your code. This concept
becomes even more fun when working with transitions.....
6 -
Transitions
It's quite typical to use a lot of transitions in your game/app.
A
good example is in Walkabout on the level selector.
Each level select square transitions into the main screen. It's
tempting to just add one transition per square in the loop that you
used to create them, but this is a performance hog!
Instead add them all to a layer and transition the layer instead.
Another pitfall is where you have multiple transitions at the same
time,
and then do something once they complete. For example scene
changing. In Walkabout going from the Main Screen to the level
selector the 'Walkabout' title transitions off the screen, as does the
'Play' icon and the sound icons. The background also alpha's to
zero.
Again it's very tempting to do this:
CODE
|
transition.to (Walkabout, {time = 200, alpha = 0
x =
100})
transition.to (background, {time = 200, alpha =
0, x
= 200})
transition.to (playicon, {time = 200, alpha = 0,
x =
300})
transition.to (volumeicon, {time = 200,
alpha =
0, x
= 400})
timer.performWithDelay(200, LoadLevelScreen)
|
In this case you can't put them all into one layer as each transition
is different. But, you are relying on all the transitions to have
finished at time = 200 so that your level screen can load.
Technically this should work fine, but in the real world you can
end up with odd glitches when a transition didn't actually complete
exactly on time. Worse you might remove an object before it's
actually totally off screen.
A better way is to use onComplete:
CODE
|
local WaitingFor
local LoadLevel = function()
WaitingFor = WaitingFor - 1
if WaitingFor == 0 then LoadLevelScreen end
end
WaitingFor
=
4
-- Waiting for 4 transitions
transition.to
(Walkabout, {time = 200, alpha = 0, x = 100, onComplete = LoadLevel})
transition.to (background, {time = 200, alpha = 0, x = 200, onComplete = LoadLevel})
transition.to (playicon, {time = 200, alpha = 0, x = 300, onComplete = LoadLevel})
transition.to (volumeicon, {time = 200, alpha = 0, x = 400, onComplete = LoadLevel})
timer.performWithDelay(200, LoadLevelScreen)
|
This way you can be totally sure the next function is only called once
all transitions are finished.
CODE
|
-- OK
transition.to (Title, {time = 200, alpha = 0})
transition.to (Level1, {delay = 200, time = 200,
alpha = 1})
timer.performWithDelay(400, AddLevelListeners)
-- Better
transition.to (Title, {time = 200, alpha = 0, onComplete = function()
transition.to (Level1, {time = 200, alpha = 1, onComplete = function()
AddLevelListeners()
end
})
end
})
|
7 -
Android Manifest Customisation
A about a year or two ago, I bought a Samsung Galaxy I-7500, which was
a 528MHz Qualcomm based Android phone with very similar hardware to the
HTC Hero. The only problem was that it only had 192MB of RAM, and
came with OS 1.5 installed.
Myself and a group of people on Androidforums started an effort to root
it and tweak it to deal with the low levels of RAM. This later
led to a merge with separate French and German groups trying to achieve
the same thing. They joined my channel #i7500 on freenode and we
began working on porting 2.1, 2.2 and now 2.3 to this underpowered
little device!
Since then I had bought a Nexus 1, and all my on-device testing for
Walkabout was done on that. Once Walkabout was looking good
enough for me to show other people, a few of my friends on the
i7500 channel ran a test version of my game, and to my horror the
performance was terrible! I spent a lot of time making sure that
Walkabout ran well on these old slow devices, and eventually
succeeded. I will explain the methods I used in later chapters.
Anyway, after all the optimising, my game was complete! I
uploaded it to the Android Market and happily announced it to all my
friends in #I7500. Great, mass excitement in the channel,
everyone stopped what they were doing, started screaming out of their
windows - well not quite - but lets say a lot of my friends rushed to
the Android market to download the free version of my game.
Disaster - my game did not appear for them on the Android Market.
Some were running the latest official 1.6 OS from Samsung, but most
were running one of our 2.1 or 2.2 custom builds. How could this
be? I had built for iOS 1.6.......
So many
Android versions, so many Corona versions...
The first obvious reason why an application may not show in the Android
Market for a certain device is that it's built for a newer Android
version. As I'm sure you all know, Ansca have dropped support for
Android OS versions below 2.2.
A lot of people ask on the Corona IRC channel, and the Corona forums
whether many people still use version 2.1 and below. Here are
some
real world statistics based on sales and downloads of Walkabout:
Android Version
|
Percentage share
of downloads
|
Android
2.2
|
67.2%
|
Android
2.1
|
24.7%
|
Android
2.3.3
|
5.2%
|
Android
2.3
|
0.7%
|
Android
1.6
|
0.2%
|
Android
2.0.1
|
0%
|
Android
1.5
|
0%
|
I don't know about you but I'm not ready to drop the 24.7% of my
customers who are still using 2.1! So what options are there to
support Android 2.1 and below? There are many different Corona
versions, and although Corona build 319 and below support 2.1, they all
have some trade-offs.
Corona
243, and the Touch bug 1...
Corona build 243 is a previous release build. You can still
download it from here:
http://developer.anscamobile.com/sites/default/files/CoronaSDK_2010.243.dmg
On some devices, the touch screen driver sends move events to Android
in a specific way. This together with the way that Corona handles
these events means that a touch event is fired every frame. This
bug was discovered after 243 was released. Therefore some very
old devices like the G1, and possibly many others exhibit very very
slow performance. When I say slow, I mean 1 to 5 fps, where a
similarly powered device may show 30fps. If you use Build 243,
your app will be unusable on these devices. Unfortunately I don't
have a full list of devices affected, but there are several posts about
it in the forums.
Worse, ALL Motorola based Android phones will crash if you touch the
screen excessively. If you use this version you should make a
note to say Motorola Android phones are not supported.
Corona
268, and the Touch bug 2...
Corona Build 268, is the previous release build. You can still
download it from here:
https://developer.anscamobile.com/sites/default/files/CoronaSDK_2011.268.dmg
Ansca attempted to fix the bug in 243 and all looked good. I used
this version to release Walkabout back on 1st March 2011. I
quickly started receiving complaints and 1 star ratings from various
users.
Some further research showed that the problem on the G1 etc was fixed,
however, the fix had caused the same problem on different
devices. Worst of all these devices were:
Samsung Galaxy S
Nexus S
ALL Motorola Android phones
These are some of the most popular Android phones out there, and worse
the most powerful. There is no ambiguity that it's your apps
fault
and not the power of the phone. Chaos ensued as I received email
after email, and poor rating after poor rating!
Corona 319
- A daily build, a brighter day...
Corona Build 319, is a daily build only available to subscribers.
If you are a subscriber and logged in, you can download it from here:
http://developer.anscamobile.com/sites/default/files/corona/2011.319/CoronaSDK-2011.319.dmg
This version fixed the touch bug, and I have no reported problems on
any phones or firmware versions
Corona 484
- The latest Release, a step backwards?
The latest release version for Corona contains various enhancements
which make huge performance gains. However they all rely on arm7
support, which is generally only available on the newest devices.
Ansca have also removed Android 2.1 support, and some modules for
arm6. This means that many old devices will no longer be able to
run builds made with this version, even if they have Android 2.2.
Additionally there is a bug that crashes HoneyComb based tablets.
I would advise you to think very carefully about whether you need the
speed enhancements in this version, and if you are willing to trade all
those
users for it.
Another
bug - idletimer...
I will explain handling suspend and resume in a later chapter, but it's
worth mentioning here. If your device sleeps due to inactivity
with the screen, the app will 'suspend'. If you do not
specifically add code to handle this and resume, your game will simply
restart when the user wakes the phone. One way to get around
having to handle this situation is to prevent the phone from sleeping
while your game is running, you can use the following api:
CODE
|
system.setIdleTimer( false ) -- disable (turn off)
the idle timer
|
However, a bug in Corona versions prior to daily 310 mean it does not
work. So if you want to use this API you must use daily 310, or
above (e.g. Release 484.
Summary
So which version should you use? If you are a subscriber it is
definitely daily build 319. If not, then it depends. See
the summary below:
Corona Version
|
G1 & Old phones
|
Nexus S & new phones
|
Idlestimer & Suspend
|
Android 2.1
& below
|
Release
243
|
Touch
Bug
1
|
(except
Motorola)
|
IdleTimer
bug
|
OK
|
Release
268
|
OK
|
Touch
Bug
2
|
IdleTimer
bug |
OK
|
Daily
319
|
OK
|
OK
|
OK
|
OK
|
Release
484
|
OK
|
OK
|
OK
|
No
Support
|
Moving on
swiftly....
So, to continue my story, I had already built Walkabout for version
2.0.1, and yet it still did not appear on the Android Market for my
friends in the #i7500 channel. The reason? - Corona predefines a
few requirements in the AndroidManifest.xml file that is included
inside your final build. In addition it misses out others!
The AndroidManifest.xml is similar to the info.plist in iOS, and
defines the minimum OS, minimum hardware, screen size and permissions
required by the application - such as Internet for example. The
AndroidManifest.xml is compressed and encoded into the apk and cannot
be edited directly.
However with a bit of work and the amazing Apk Manager tool from
#xda-developers you can edit the AndroidManifest. Is it worth the
hassle I hear you ask? Well here are the benefits:
- Remove vibrate permission if you don't use it - so on install the
user would see 'no special permissions required' assuming you don't use
any other permissions.
- Add small screen support - so QVGA devices, and some other
devices that require the tag can see your app in the market
- Remove opengl 1.1. requirement, so lower end phones which only
support opengl 1.0 or don't define opengl support can see your app in
the market.
- Add apps2sd for 2.2+ while still allowing it to run on < 2.2
- Appear like you target honeycomb, and support xlarge screens so
that your app shows as a honeycomb app on new devices like the xoom.
- Decrease APK file size.
I have edited the tool to incorporate the new Honeycomb
frameworks. You will need the following two files:
http://www.mediafire.com/file/s4w33a52fdilstr/apk_manager_4.zip
http://www.mediafire.com/file/ydplueldeypu622/1.apk
Unfortunately this only works on a PC at the moment. The OS X
version of apk manager has issues with Corona built apk files. I
will update this section when the issue is resolved.
1) Download and extract the apk_manager zip file onto your desktop
2) Open a command prompt and type 'java' (without the quotes) and press
enter. If you receive command not found, then go to the following
link and download the JAVA JDK before proceeding.
http://www.oracle.com/technetwork/java/javase/downloads/index.html
3) Open the Apk manager folder, and place your Corona build apk file in
the folder place-here-for-modding.
4) Double click script.bat, and ignore the error about adb not being
found. Press menu option 22 and then 1 to select your apk.
Then press option 9 to extract your apk.
5) ONLY ONCE. Browse to
c:\users\<yourusername>\apktool\frameworks\resource and replace
the 1.apk with the one you downloaded above.
6) You fill find your extracted apk in the projects folder of apk
manager. Edit your AndroidManifest in a text editor and save the
changes (More on how below). Then select option 11 in apk manager
to compile your new APK. Press 'n' to 'Is this a system apk'
7) You will find a new apk in the place-here-for-modding folder that
has the same name as your original apk but 'unsigned' prepended to
it. Transfer this back over to your Mac.
8) Sign the apk with your key. You will need to use the keystore
you generated for Corona and the alias you used. If you don't
remember your alias, you can build for Android in Corona, select your
key and the alias will be in the second drop down. Here is an
example of how I sign Walkabout (That is all one line):
CODE
|
jarsigner -verbose -keystore
~/Desktop/Walkabout_Submission/base2-release-key.keystore
~/Desktop
/unsignedWalkaboutLite.apk
base2_release
|
9) Finally zipalaign the apk - Corona doesn't do this for some reason
(?!). You can read more about zipaligning here:
http://developer.android.com/guide/developing/tools/zipalign.html
CODE
|
/android-sdk-mac_86/tools/zipalign -v 4
~/Desktop/unsignedWalkaboutLite.apk ~/Desktop/WalkaboutLite.apk
|
You're final apk will be on your desktop enjoy!
Changes
you say?
So, what changes can and should you make I hear you ask? Firstly
I recommend you build with Daily 319 for 2.0.1 and you will end up with
an Android Manifest similar to the following:
CODE
|
<?xml version="1.0" encoding="UTF-8"?>
<manifest android:versionCode="1" android:versionName="1.0"
package="com.base2.walkaboutdemo"
xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission
android:name="android.permission.VIBRATE" />
<uses-feature android:glEsVersion="65537" />
<application
android:theme="@android:style/Theme.NoTitleBar"
android:label="@string/app_name" android:icon="@drawable/icon">
<activity
android:label="@string/app_name" android:name=".MyCoronaActivity"
android:launchMode="singleInstance"
android:screenOrientation="landscape">
<intent-filter>
<action
android:name="android.intent.action.MAIN"
/>
<category
android:name="android.intent.category.LAUNCHER"
/>
</intent-filter>
</activity>
</application>
<uses-sdk android:minSdkVersion="6" />
</manifest>
|
Lets go through the changes one by one:
Apps 2 SD
- Only Android 2.2 supports installing to the SD card to save internal
space. Usually this is only possible if you build for 2.2.
If you want to support older Android versions you lose the option to
install to SD, or do you?
CODE
|
In this line:
<manifest android:versionCode="1" android:versionName="1.0"
package="com.base2.walkaboutdemo"
xmlns:android="http://schemas.android.com/apk/res/android">
Add the section in red:
<manifest
android:versionCode="1" android:versionName="1.0" android:installLocation="auto"
package="com.base2.walkaboutdemo"
xmlns:android="http://schemas.android.com/apk/res/android">
|
OpenGL
Corona automatically adds Vibrate permissions, and an OpenGL 1.1
requirement. Some older phones (the trusty i7500 for example)
only supported 1.0 on launch, and although it was updated to 1.1, it
was never specified properly. In fact even the old OS with only
1.0 support works fine with Corona apps. The 1.1 requirement is
unnecessary, and just narrows your user base. Also the vibrate
permissions isn't used in my app - by removing it, I have a nice 'This
app doesn't use any special permissions' when a user installs the app!
CODE
|
Delete these two lines:
<uses-permission
android:name="android.permission.VIBRATE" />
<uses-feature android:glEsVersion="65537" />
|
Small
Screens and Large Screens! Honeycomb anyone?
By default the SDK version you built against defines the default
settings for small and large screen support. This means by
default qvga devices will not be able to run your app.
Additionally, targeting an OS version below 9 will NOT enable xlarge
screens support for new Honeycomb tablets like the xoom. So lets
fix that, shall we!
CODE
|
Add the 2 lines in RED after the
minSDKVersion line:
<uses-sdk android:minSdkVersion="6" />
<uses-sdk android:targetSdkVersion="11" />
<supports-screens android:anyDensity="true"
android:smallScreens="true" android:normalScreens="true"
android:largeScreens="true" android:xlargeScreens="true"/>
|
This will enable support for ALL screen types and densities - as well
as
honeycomb support. This only works with the modded framework file
1.apk you downloaded earlier.
Smaller
file size?
Apk manager uses the maximum compression rate possible, which should
reduce your final apk size. The zip align process will also make
the app more efficient on device.
Remember you MUST sign your apk after the process. If you want to
just try this out, you can use the 'sign' option in APK manager.
This will use a test key - DON'T RELEASE With this key (!), only use it
for testing if you're lazy to sign every version until release.
Is it
worth it?
Of course you want your app visible to as many users on the Android
mMarket as possible. However if your app barely runs on the
latest phones, it may not be a good idea to enable things like small
screen support, or to build for very old OS's. I chose 2.0.1 as
my minimum, as I don't think very old phones would be able to handle
the graphics in my game. Also even Google shows that <= 1.6
has less than 5% users, so it's not a huge sacrifice.
Be careful, enabling ALL versions and screen types, just for the heck
of it may lead to 1 star reviews where the users don't have the the
good sense to realise their phone is just incapable of running your
game!
Having said that, with a bit of work, I transformed the performance
from < 5fps to a playable 20 fps on the galaxy, and opened up a
whole new set of users. Image how many HTC hero users there are
out there for example!
Also, there is a HUGE opportunity to target Xoom and other HoneyComb
users. The number of apps and games they see as HoneyComb
compatible is very small, and typically apps not designed for HoneyComb
and their very high res screen open up in a smaller window. With
Dynamic image scaling and the AndroidManifest tricks I've shown you
here, you can fully support these devices TODAY!
Support
If you would like to show your support, please download the Free
version of Walkabout on Android or iOS and leave me an honest
rating! Every rating helps achieve presence on the app
store. Just search 'Walkabout' in either App Store or Android
Market.
If you're looking for help or support you can find me on
irc.freenode.net at #corona and of course #i7500
Thanks for listening!