Android Programming For Beginners
Android Programming For Beginners
Every effort has been made in the preparation of this book to ensure the
accuracy of the information presented. However, the information contained
in this book is sold without warranty, either express or implied, neither the
author nor its dealers and distributors will be held liable for any damages
caused or alleged to be caused directly or indirectly by this book.
WHY I WROTE T HIS BOOK
Today, there are so many available softwares for developing Mobile Apps
and Games but they require high spec and quality computers. How about those
people who want to learn or develop Apps with low end computer and cant
afford high end computer? In addition, documentations or resources are also
hard to find or even if you found some they rarely give you working examples.
The internet is now too crowded. I know, we hate to wait or research and
download large files or read long chapters, blog posts or documentations with
too much information and yet it only has little of what we really need. So I
wrote this book to share my knowledge in developing Apps the fast and easiest
way even you dont have experience in developing one before.
I am not a guru or geek and I barely know Java and C# but I can still
develop my own Apps and Games and what more interesting is that it is easy
to learn. So if you have idea in mind then get ready for making it real.
WHY YOU SHOULD READ T HIS BOOK
You want to learn how to develop Mobile Apps but you dont have the
resources and your computer doesnt meet the system requirements? No
problem, this book is for you.
This book will guide you on how to develop an Android Application but
consider this as a compilation and tutorials of simple start up Applications in
developing your first Android Apps.
Learn while doing actual codes, see results in real time right away from
your device without rebuilding the App. Display images, text, vectors, play
sounds and animate objects with just few lines.
I assure you, you dont need to download 300mb IDE, 2GB SDK, or
upgrade your laptop just to be able to develop and learn how to code your first
App. I will not try to be complete or precise but I want you to start learning as
quickly as possible. We will focus on what is currently needed or commonly
used APIs so we wont get stuck.
T ABLE OF CONTENTS
Why I Wrote This Book
Why You Should Read This Book
Table Of Contents
Chapter 1: Introduction to Android
What is Android?
What is An Android App?
What are the Editors and Tools available online?
What are the basic skills needed to develop an App?
Chapter 2: Getting Ready
Introduction to Corona SDK
System Requirements
What do we need?
Setting up Corona SDK
Corona Simulator
Corona Simulator Output
A Short Introduction to Sublime Text
Chapter 3: Building Your First App
Chapter 4: Simultaneous Device Testing
Creating a Live Build
Starting the Corona Server
Connecting the Device and Testing
Closing the Live Server
Chapter 5: The Project Files
The build.settings
The config.lua
The Ultimate config.lua
Icons
Chapter 6: Status Bar and Android System UI Visibility
What is Status Bar?
How to Change Status Bar?
What is Android System UI Visibility?
Chapter 7: Understanding Tables, Functions, Methods and Events Listeners
Tables
Functions
Methods
Events
Chapter 8: Tips and Understanding Errors
Runtime Errors
Tips
Chapter 9: Creating a Simple IO App
Interface
Text Display Object
Native Text Field
Button Widget
Native Alerts
Chapter 10: Simple App Using Composer API
Scenes
Overlay Scene
Calling a Parent Scene Method from an Overlay
Chapter 11: Creating a Simple Movie List App
Movie List Module
Menu Scene Interface
Detail Scene Interface
Chapter 12: Using SQLite3
Creating and Connecting a Database
Executing SQL Command
Closing the Connection
Chapter 13: A Simple App with Database
Setting up The Database
Interface
The Process
About The Author
CHAPTER 1: INTRODUCTION TO ANDROID
Let us view a short introduction of Android.
What is Android?
Android is an Operating System that is designed for touchscreen devices
such as tablets and smartphones. Android Version Names are based on sweet
desserts. Android Version 1.5 or also known as Cupcake was released in
April 2009, followed by Donut (1.6) in September 2009, clair (2.0 2.1) in
October 2009, Froyo (2.2 2.2.3) in May 2010, Gingerbread (2.3 2.3.7)
December 2010, Honeycomb (3.0 3.2.6) February 2011, Ice Cream
Sandwich (4.0 4.0.4) October 2011, Jelly Bean (4.1 4.3.1) July 2012,
Kitkat (4.4 4.4.4) October 2013, Lollipop (5.0 5.1.1) November 2014,
Marshmallow (6.0 6.0.1) October 2015 and the latest version, Nougat (7.0
7.1.1) which was released in August 2016.
Since Android is Open Source it became popular and it became the best-
seller OS on tablets since 2013. In September 2015, Android had 1.4 billion
active users making it the most used OS for mobile devices. Android is now
used for TVs, watches, notebooks, digital cameras, game consoles and many
more. Android was owned by Android Inc. which later on bought by Google in
2005.
System Requirements
Corona SDK on Windows only supports building Android and Windows
32 Applications and it requires the following basic system elements:
Windows 10, Windows 8, Windows 7, Vista, or XP Service Pack 3
1 GHz processor (recommended)
1 GB of RAM (recommended)
OpenGL 2.1 or higher (available in most modern Windows systems)
In order to build Apps for Android, you should download and install Java
7 Development Kit if not yet installed. You can click here to go to the
download page. Read the license agreement and accept it if you agree. Then
download the JDK for Windows x86 (even if your system is 64 bit).
Make sure to install JRE as part of installation.
Note that Corona SDK built Applications only supports Android devices
that runs Android 4.0.3 (ICS) or higher with ARMv7 processor. ARMv6 is
not supported.
What do we need?
Here are the things that you need to get started:
1. Download Corona SDK and create an account with Coronalabs.com
1. Go to https://coronalabs.com/ and enter your email then click Download
Free SDK.
2. You will be redirected to a new page where you need to register or login
if already a member. Remember your account email and password for
you will use it to activate Corona SDK after installation.
3. After creating an account you will be redirected to a new page. Click
Download Corona SDK
4. If you can see below, the system requirements are enough to install it on
a notebook. Click Download.
5. Install Corona SDK and open the Corona Simulator. You will be ask to
login. Enter your information from Coronalabs.com account and your
SDK will be activated.
2. Download Offline Version of Corona SDK documentation.
1. From the current page, scroll to the very bottom and you will see the
Corona SDK daily build. Look for the corresponding CoronaApiDocs
zip for your downloaded Corona SDK version and download it.
2. Now, look for the zip file and extract it to anywhere you want and open
the index.html file.
3. Open it with your favorite browser and pin it so you can access it
anytime you want without opening the directory where it is stored.
Just right click the tab and click Pin tab.
4. Now, you can browse the documentation of Corona SDK offline. This
is handy when you are stuck in a situation that you need examples and
API reference while you are offline. You can also visit Coronalabs
Forum here anytime when you are online. Every time you encounter a
new API or function, go to Coronalabs Documentation and click for
API Reference-> press ctrl+f enter the API or function and click
the highlighted link.
b) Download Sublime Text editor and choose the version that fits your
OS.
c) Extract it to local C under Program Files and create a shortcut to
your desktop by simply right-click -> send to -> Desktop (Create
Shortcut).
4. The Sublime Text Editor should now Display a menu Corona Editor.
Restart Sublime if Corona Editor Menu doesnt appear.
5. Sublime Text Editor is now integrated with Corona Editor. Lastly, lets
set our default syntax to Corona SDK Lua. Go to View -> Syntax ->
Corona SDK Lua.
Setting up Corona SDK
After downloading Corona SDK, install it and open Corona Simulator. The
Corona Simulator will prompt you to login (if not yet logged in).
Corona Simulator
Corona Simulator is where you can simulate your Apps. But there are
functionalities that the simulator cant simulate like multi touch, GPS,
notifications, accelerometer, gyroscope and camera. Good thing Corona
enables developers to create a live build where your Apps can be tested in
real time without rebuilding it. But the downside of it is that sometimes you
cant track the errors in live builds, thats why it is still important to run the
simulator while your live build is connected.
Just make sure that you set the syntax so that the auto-complete function
will suggest syntax that is related to that particular language that you use. You
can press the tab for completing the arguments of the syntax.
This error occurred because I run my project while the opened file was
inside a subfolder lib while my main.lua resides outside of that folder.
Thats why it prompts that the main.lua file was not found.
Before we move on, here are some Sublime Text useful keyboard
shortcuts.
1. ctrl+] and ctrl+[ increase and decrease indent of the line.
2. ctrl+g go to line number. Using this you can quickly jump to lines
where an error occurred.
3. ctrl+h search and replace a word.
4. ctrl+f search for a word.
5. ctrl+r search for function name
6. ctrl+/ - comment a line or highlighted lines.
7. ctrl+shift+up moves a line or highlighted lines upward.
8. ctrl+shift+down moves a line or highlighted lines downward.
For the next chapters please download the project files here.
CHAPTER 3: BUILDING YOUR FIRST APP
Making your first App will be easy but your next Apps will be difficult but
challenging.
Go and create a simple App. Print a simple hello world to the simulator
output or build panel. Follow the instructions bellow.
1. Open Corona Simulator and go to File -> New Project. You can also use
the keyboard shortcut ctrl+n. Enter Hello World as the Application
Name. You can change the directory of your project just click Browse and
locate the directory that you want for the project. For now, we will let the
settings that way.
2. The folder of your project will pop up. Open the file main.lua to your
Sublime Text Editor. If opened via notepad then set the default application
for opening Lua files. You can do this by right clicking the Lua file
1. Right click the file. Open with -> Browse -> Locate the
sublime_text.exe.
2. Click ok then check the Always use the selected program to open
this kind of file. then click Ok.
3. Once the file is opened, write the following code and save it:
print(Hello World!);
8. Android Build Setup will now appear. Note that you need internet
connection and JDK installed in your PC. Now, fill in the following
information needed.
Change the Target App Store to none and if you want to change the
directory where your App will be saved you can browse and locate the
directory that you want. For now, you will use the default values. If the
Simulator ask for a password, input android and save it and click Build.
9. Once completed, wait for Corona to notify you that building is complete.
Copy the file to your device. (This process is not recommended) Now look
for the App in your device and install it. If the App is blocked, enable your
device to install non-market Apps. Click the Settings icon on your device,
select Applications, and then check the box next to Unknown Sources. If
you cant locate the Unknown Sources, try under Lock Screen and
Security. For the complete documentation on how to build and test android
Apps using Corona, visit the offline version of Corona SDK documentation
that you pinned in your browser.
1. Open browser where you pin the offline version of Corona SDK
documentation.
2. Click Guides -> Look and click for Building and Distribution ->
Click Building and Signing Android.
3. Click Device installation.
10. When finished installing, look for the icon and launch it. And there you
have it.
CHAPTER 4: SIMULTANEOUS DEVICE T ESTING
Corona has a feature where you can test your App in real time. To be able to
use Live Builds on Windows, you need to install iTunes. This feature requires
Corona Daily Build 2016.2993 or later. Note that this will only work for
debug keystores.
Try to build your Hello World App and check Create Live Build.
After building the App, Corona Live Server will automatically start. Inside
the Corona Live Server is the project folder Hello World. Note that inside
your root folder is a file named .CoronaLiveBuild. This file syncs your
project from your PC to your installed App.
Starting the Corona Server
Distribute and install your App (the Live Build .apk file) to any Android
device. If the Corona Live Server doesnt automatically start, try to locate and
run it from Drive C:/Program Files/Corona Labs/Corona SDK or C:/Program
Files (x86)/Corona Labs/Corona SDK where Corona SDK is installed and
open Corona.LiveServer.exe.
If Corona Live Server is empty, you can drag and drop your projects
folder which contains the .CoronaLiveBuild file. You can also use the +
button and locate the project folder.
After saving the code, the App from your device should now restart and the
text displayed is now changed to Live Build.
Closing the Live Server
If you want to close and exit the Corona Live Server, go to the system tray
and Right click-> Exit. Note that the Server will not exit by just closing the
window.
settings =
{
android =
{
usesPermissions =
{
"android.permission.INTERNET",
"android.permission.WRITE_EXTERNAL_STORAGE", -- saving media and camera
support
"android.permission.ACCESS_FINE_LOCATION", -- allow access to GPS
"android.permission.ACCESS_COARSE_LOCATION", -- allows getting location from
WIFI/Cellular Service
},
},
}
Android Features are parameters that tells the Android App Store which
hardware does the App requires. You can do this by adding a feature inside the
usesFeatures table like the example below.
settings =
{
android =
{
usesFeatures =
{
{ name="android.hardware.camera", required=true }, -- required
{ name="android.hardware.location", required=false }, -- optional
{ name="android.hardware.location.gps", required=false }, -- optional
}
},
}
Note that if your App grants permission to use the camera, the Android
assumes that you also require this feature. In this case, all devices without
camera will unable to install your App. So if your App is granted a permission
that is optional, you can set the required key to false like the example above.
In addition, if you want your App to be categorized as Game in Google
Play, set isGame to true. If your App supports Android TV set supportsTV to
true.
settings = {
android = {
supportsTV = true,
isGame = true,
},
}
Other settings will be discussed later. So far these are the basic things that
you need to know about build.settings.
The config.lua
The config.lua file sets the basic configuration of your App. This file
consists of application table which has sub-table content.
application = {
content = {
-- Parameters
}
}
The variable aspectRatio is the scale factor for the current device. This is
where the width and height of the App will be based. If the aspectRatio is
greater than 1.5, width will set to 800 else it will be set to 1200 divided by
aspectRatio. In most cases the width is always set to 800. The same
computation is done with the height. This ensures that the width and height of
the App will be relative to 800x1200. The scale method is set to
zoomStretch since some App Store requires fullscreen and Apps with black
bars are discouraged, though you can still set it to letterbox. Dont worry, in
this configuration the zoomStretch will fit to any screen dimension and
image wont be stretched that much. Lastly, the xAlign and yAlign are set to
left and top. By default, the alignment of the screen is set to center. In
some cases the immersiveSticky mode drags the screen or objects towards
the edge when alignment was set to default. Note that the above config template
is intended for games. Since we will be creating Apps we will change 800 to
320 and 1200 to 480 to make the dimension relative to 320x480 which is the
standard dimension for Apps.
Icons
Android requires 6 different Icon that follows the standard Android icon
names and sizes. These icons should be located in your root folder alongside
with your main.lua file. You can create your own Icons using Photoshop or
other similar software.
Name Size (wxh)pixels
Icon-xxxhdpi.png 192x192
Icon-xxhdpi.png 144x144
Icon-xhdpi.png 96x96
Icon-hdpi.png 72x72
Icon-mdpi.png 48x48
Icon-ldpi.png 36x36
You can create your own Android Template Folder that consists of the
mentioned files above.
Rename the folder to Android Template. Every time you will create a
project, simply create a copy of the template and rename it to your Project
Application Name.
Lets recap what you have learned and what you have done so far:
1. You learned what Android is.
2. You also learned what an Android Application is.
3. You are introduced to the tools and IDE available online.
4. You downloaded the installers and files that you needed.
5. You installed, configured and activated the SDK and IDE.
6. You built your first simple App and installed it into your device.
7. You built your first live build App and able to test it in your device in
real time.
8. You learned about project files and have a template to start an Android
Application.
CHAPTER 6: STATUS BAR AND ANDROID SYSTEM
UI VISIBILITY
Status bar and System UI are the first thing that you want to change or modify
for your App before starting and building them.
Tables
Tables in Lua are arrays that can be indexed not only with numbers but
also with strings. Lua tables can also have any values including functions
except for nil. To avoid confusions about indexing, lets call the integer index
as index and lets call the string index as property or key.
Name
t[1] Index
t[name] Property
Here is an example on how to initialize a table and put values into it:
local t = {}
t[1] = 1
t[2] = 2
t[3] = hi
Inline:
local t = {name = Aj, age = 2, msg = hi}
The example above is a table with string indices. You can access the
values by using brackets.
print(t[name]) output Aj
Also remember that if a table has holes (nil), all elements will be
evaluated if the last element is not nil. If the last element is nil, only the last
non-nil value element will be evaluated and skips the rest.
Now if the last element is a non-nil value element, all of the integer indices
will be counted including the nil value element.
Functions
Functions like in other Programming Languages, it executes a group of
statements or simply perform a task where the result can be returned. An
example is the built-in function print( ). A Function is composed of scope, a
name, body, optional argument and an optional return statement. Functions are
also variables that can be stored in a property that enables you to group them in
one table as a library like the math library. You can return multiple values as
well.
Declaring a Function
The following is an example of declaring a function:
local function getName( parameter )
local params = parameter
local name = params.name
return name
end
The local statement is the function scope. The function can only be
accessed through out the code where it is declared. The getName is the
function name which you can call for execution of the function. The parameter
is the argument for the function. Inside the function is the body of the
function. It is a group of statements or process that executes when the function
is called. Lastly the return statement which returns a value to the handler.
Global declaration:
-- global declaration
function function_name( )
-- body
end
function_name = function( )
-- body
end
Methods
What is a Method in Lua?
The difference of common Functions from Methods is their syntax and the
way they access the keyword self (the object itself). A common Function that is
stored in a property is called by the use of . dot operator while Methods are
called by the use of : colon operator.
object:getLabel()
Note the keyword self is the same with the keyword this in other
programming language.
Methods can access the keyword self without passing an argument self to
the function method.
function object:touch(e)
local target = self
end
Note that Objects are represented by tables and no need to put a scope for
the method.
Note that in Lua, semicolons at the end of every statement are optional.
Events
Events are the interaction or the activities of the user or the system. Corona
has many different events including touch, tap, accelerometer, collision, key,
sprite, system, timer, orientation etc. Events can be registered using the
method object:addEventListener(eventName, eventListener). Where the eventName is
the name of the event and eventListener is the function listener.
local rect = display.newRect( display.contentCenterX, display.contentCenterY, 400, 200 )
rect:setFillColor( 0.4, 0.45, 0.8 )
function rect:touch( e )
print( e.phase )
end
There are many ways on how to declare a listener and how to register
them. The above example is using an object method and registering the object
as object listener where e is the event argument.
local rect = display.newRect( display.contentCenterX, display.contentCenterY, 400, 200 )
rect:setFillColor( 0.4, 0.45, 0.8 )
The example above will result to an error of nil value. In this case, e is now
considered the self or the object where e.phase property doesnt exist.
For complete information about Events, visit Corona Documentation. Go to
Guides -> Events and Listeners-> Basic Interactivity and Event Detection.
CHAPTER 8: T IPS AND UNDERSTANDING ERRORS
As a developer, you will occasionally encounter problems in your code,
including incorrect logic, improper usage of an API, or any number of other
issues.
Runtime Errors
Runtime Errors are those that crashes your App. These will abort the
program and display an information box which includes the filename where the
error occurred, the line where the error occurred, the reason for the error and
the stack trace which can help you locate the origin of the error.
Arithmetic statements expects number values not table, string or nil. This
is also caused by wrong call or usage of APIs.
2. Upvalue error
- This is caused by using the same name or identifier/variable name and
assigning it with two different data types. For example from the
Coronalabs blog post:
Before the statement local is where the error occurred. In this example,
the previous statement is incomplete. Line 3 is an incomplete statement.
Tips
To avoid some common issues, we should be aware of them and use some
tools to help us resolve them.
1. Proper Indention
- Using Integrated Development Environment (IDE), this will help you
automatically indent your codes. When your code is indented correctly, it
will be easy to see if there are omitted end statement in your code and
the block of codes will be easy to read.
2. Descriptive Naming
- Using a name with the same behavior it represent is easier to read and
other developers may understand or know what you are trying to
achieve. For example, if you are adding numbers and created a function
for the addition process, you should name the function addition or
add so that other developers know that the function you made is for
adding numbers.
3. Device Consideration
- The simulator is not case sensitive when it comes to project files, but
when an App is built for actual device, it causes errors since the device
is case sensitive. For example, the filename background.PNG is
different from background.png when it comes to the actual device. So
use the same case when accessing filenames and use lowercase for file
extensions.
Interface
Open the main.lua file from your Hello World Project. Clear the content
and save it. Notice that your App from your device restarts. Now your App is
empty and turned into a black blank App. Lets change the default background
color of your App.
display.setDefault( "background", 1, 1, 1 ) -- white
This doesnt have effect yet since we only require the API. The next thing
we need to do is to declare constants.
-- constants
local centerX = display.contentCenterX
local centerY = display.contentCenterY
local _W = display.contentWidth
local _H = display.contentHeight
You will also learn in this chapter on how to display a label, text field and
a button. The output later on should look like this:
Using Corona Editor integrated to Sublime Text, you will see suggestions
like this:
Notice the brackets in the syntax? These are optional arguments. Delete
parentGroup and use tab to go to the next argument. Fill in the text, x, y, font and
fontSize like the code below:
label = display.newText( "Name:", 0, 0, native.systemFont, 20 )
The Name: is the text displayed to the Device, x and y are the coordinates
of the text object, native.systemFont is the font of the text field and 20 for the
fontSize of the text. Note that coordinates [0,0] is located at the top left corner
of the screen and every display object has an anchor point (center) where the
coordinates of the object will be based on. Since the background color is
white and the default color for text object is white, we need to change the color
of the text object to be able for use to see the label.
label:setFillColor( 0.2, 0.2, 0.2 )
The setFillColor method is only for display objects like text, image and
shapes. For more information about setFillColor go to Coronalabs
Documentation and click API Reference-> press ctrl+f and enter
setFillColor -> click the highlighted link.
As you can see, the label is on the top left corner of the screen.
Lets go and try to change the anchor point of the object. If you are familiar
with Photoshop, anchor point is the circle inside an object when using
transform tool. This is where they based the rotation and coordinates of the
object. Use the . operator and set anchorX and anchorY any value from 0 to 1.
The default value is 0.5. Go ahead and experiment.
label.anchorX = 0
Now, we will change the coordinates of the object to 10 pixels from left
and 80 pixels up from center y.
label.x = 10
label.y = centerY - 80
For more information about display.newText() go to Coronalabs
documentation -> API Reference-> press ctrl+f and enter newText and
click the highlighted link.
In some cases, we may want to change the font size and the font of the text
field. We can do this by:
inputText.size = 20
inputText.font = native.newFont( "Arial.ttf", 30 )
The size property will set the font size to 20 pixels. The font property
changes the font of the text field together with the font size. For now only the
size property will be used to our App. Changing the font size wont change the
height of the text field, if you want to make the text field to resize and fit the
font size just call the following method.
inputText:resizeHeightToFitFont()
We can also change the inputType of the text field by changing the value of
the inputType property of the text field.
inputText.inputType = "default"
Button Widget
Now we have an object to get an input from the user, what we need next is
an object that will process the input value and will output a message. This time
we will create a button widget. We already required the widget API so all we
have to do now is to display and create a button.
submitBtn = widget.newButton( {
label = "Submit",
onRelease = onRelease,
emboss = false,
-- Properties for a rounded rectangle button
shape = "roundedRect",
width = _W-50,
height = 60,
cornerRadius = 5,
labelColor = {default={0.2, 0.2, 0.2}, over={1, 1, 1}},
fillColor = { default={0, 0.9, 0.9}, over={0, 0.6, 0.5, 0.8} },
})
Let me discuss the above code line by line. The first line is the creation of
the submit button. The function widget.newButton accepts a table as argument.
1. label is the label or text for the button.
2. onRelease is an event listener that is triggered when the user released his
finger from the screen. We will create a function for that later.
3. emboss Boolean value. Makes the label embossed or not.
Native Alerts
Lastly is showing an alert or dialog to the user. The native.showAlert accepts the
following arguments:
1. title the title of the alert.
2. message the message of the alert.
3. buttonLabels table of string for the corresponding button labels. Example:
{Ok,Cancel}.
4. listener the function listener that to be called when the user taps a button
from the alert. The listener can be either a function listener or a table
listener and the event dispatched to the listener will have the following
additional properties:
1. event.action represents how the alert was dismissed: "cancelled"
indicates that native.cancelAlert() was called to close the alert, while
"clicked" indicates that the user clicked on a button to close the alert.
2. event.index is the index of the button pressed. It corresponds to the index
in the buttonLabels parameter. First button from the left is 1 and the next
button is 2 and so on.
Note that in the message argument ("Hi "..inputText.text.."!"), the two dots (..)
represents concatenation in Lua. Identifiers or handlers in Lua accepts any
value including functions except for nil and automatically converts the value
when being processed. For example:
local a = 1
local b = "2"
local c = a + b
print( c )
-- text field
inputText = native.newTextField( centerX, 0, _W-50, 60 )
inputText.y = label.contentBounds.yMax + (inputText.height * 0.5)
inputText.placeholder = "Enter your name:"
inputText.inputType = "default"
inputText.size = 20
inputText:resizeHeightToFitFont()
Now, test the App and make experiments like odd or even or leap year.
CHAPTER 10: SIMPLE APP USING COMPOSER API
In this chapter we will learn how to create scenes using Composer API.
Scenes
Scenes are like pages in a book, scenes in a story or levels in a game. In
some cases there are some scenes that are overlaying another scene like
dialogs. These scenes are called overlay scenes. They are temporarily
overlaying the current scene to give information or another task to the user.
Composer API is a scene creation and management library that helps you
organize objects in a scene. However, Composer only allows one overlay
scene at a time. Corona also provided a template for using Composer Scenes.
Composer Scenes are individual Lua files that can be called by
composer.gotoScene or composer.showOverlay function. In displaying the initial
scene you need to initialize the composer API from the main.lua and go to
initial scene by using composer.gotoScene function. Scene name is the scene
filename without .lua file extension.
Example:
local composer = require( "composer" )
composer.gotoScene( "menu" )
Assuming that menu.lua file exists and contains the Composer Scene
Template. Note that I wont discuss all of the Composer APIs functions but you
can read it all at Coronalabs documentation. What Im going to show you is
how to create a Simple App using Composer API and help you understand
Composer in actual development and on how you can use the parent scene
custom methods on your overlay scenes.
1. Create a copy of your Template and rename it to Scene App or create a
new Project.
2. Go to the simulator Sample Apps. Click help from menu and click Sample
Projects -> Select Interface and open Composer project.
3. Go to File-> Show Project Files.
The first line hides the status bar. The second line requires the Composer
Library to our code. The last line moves the scene to menu. The main.lua
is not a scene, this is where we will initialize the composer. Now look at
the output through live build or run your code to the simulator by pressing
ctrl+bor +f10. Error sometimes wont appear on live builds so run
it also to your simulator just in case that you cant see the errors from the
live built App.
7. Open the menu.lua file and at the upper part of the code require widget API.
local widget = require( "widget" )
8. Declare handle bg and button after the require statements. The reason why
we declare it outside the methods is that we need them to be accessible
throughout the entire code.
local composer = require( "composer" )
local widget = require( "widget" )
local scene = composer.newScene()
9. Inside the scene:create method is where you will display or initialize the
scene. Write the following code:
bg = display.newRect( sceneGroup, display.contentCenterX, display.contentCenterY,
display.contentWidth, display.contentHeight )
bg:setFillColor( 0.8, 0.2, 0.2 )
This is our simple background for the menu scene. It is positioned to the
center of the screen. We set its color to Red.
10. Below the bg initialize a widget button that will bring us to the view scene
later. We will create a simple rounded rectangle and position it to the center
of the screen. Dont forget to insert the objects to the sceneGroup. The
sceneGroup will hold all of the display objects inside the scene so if you
forgot to insert the objects they will float at the surface of the screen.
button = widget.newButton( {
label = "Go to View Scene >>",
onRelease = function ( self, e )
composer.gotoScene( "view", {effect = "slideLeft", time = 200} )
end,
emboss = false,
-- Properties for a rounded rectangle button
shape = "roundedRect",
width = 300,
height = 80,
cornerRadius = 5,
x = bg.x,
y = bg.y,
labelColor = {default={0.2, 0.2, 0.2}, over={1, 1, 1}},
fillColor = { default={0, 0.9, 0.9}, over={0, 0.6, 0.5, 0.8} },
})
sceneGroup:insert(button)
The additional parameters added to the gotoScene function are the effect and
time of the transition. You can view the full information about effects for
scenes go to Coronalabs Documentation -> API Reference -> press ctrl+f
enter gotoScene and click the highlighted link.
11. Before we go to the next scene. Remember to remove the display objects if
you dont need them anymore. You can do this inside the scene:destroy
method. The method object:removeSelf() removes the display object from the
screen but the memory is not yet released. To release used memory assign
nil to the handler.
print(menu destroyed)
bg:removeSelf( ); bg = nil;
button:removeSelf( ); button = nil;
button = widget.newButton( {
label = "Go to View Scene >>",
onRelease = function ( self, e )
composer.gotoScene( "view", {effect = "slideLeft", time = 200} )
end,
emboss = false,
-- Properties for a rounded rectangle button
shape = "roundedRect",
width = 300,
height = 80,
cornerRadius = 5,
x = bg.x,
y = bg.y,
labelColor = {default={0.2, 0.2, 0.2}, over={1, 1, 1}},
fillColor = { default={0, 0.9, 0.9}, over={0, 0.6, 0.5, 0.8} },
})
sceneGroup:insert(button)
end
end
---------------------------------------------------------------------------------
-- Listener setup
scene:addEventListener( "create", scene )
scene:addEventListener( "destroy", scene )
---------------------------------------------------------------------------------
return scene
13. Open the view.lua file and just like menu.lua we will require the widget API
and declare handlers bg and button.
14. We will initialize the bg and button the same manner we did in menu.lua file.
The difference is the bgs fill color which we will set to blue (0.2, 0.2, 0.8)
and the function composer.gotoScene arguments inside the onRelease function
of button.
button = widget.newButton( {
label = "<<Go to Menu Scene",
onRelease = function ( self, e )
composer.gotoScene( "menu", {effect = "slideRight", time = 200} )-- <<
end,
emboss = false,
-- Properties for a rounded rectangle button
shape = "roundedRect",
width = 300,
height = 80,
cornerRadius = 5,
x = bg.x,
y = bg.y,
labelColor = {default={0.2, 0.2, 0.2}, over={1, 1, 1}},
fillColor = { default={0, 0.9, 0.9}, over={0, 0.6, 0.5, 0.8} },
})
sceneGroup:insert(button)
Dim is a background that darkens the screen when the overlay fully
displayed on the screen. We will transition it later on scene:show method.
The property alpha is the opacity of the object. Setting it to 0 will make
the object invisible. The bgs width and height is set to 300 so we can
see the dim and the current scene behind it.
3. Inside the scene:show under the phase did, insert the following code:
transition.to( dim, {alpha = 0.5, time = 200} )
Inside the onRelease function, we cancel the transition of the dim since the
user may tap or hide the overlay while the transition is still running. We
also set its alpha to 0 and call for the function composer.hideOverlay. It
will hide the overlay with transition effect zoomOutInFade with time 200
milliseconds. If you want to just hide the overlay without transitioning,
just omit the effect and time.
This method will change the label of the button in the menu.lua.
2. Open overlay.lua and go to scene:hide method and write inside the did
phase:
if (parent) then
parent:changeButtonLabel()
end
3. The widgets button in the menu will change into Label changed after
hiding the overlay.
Wrapping Up
The Composer API must be initialized in the main.lua file and set the initial
scene to show using composer.gotoScene function. Composer scenes when
called for the first time calls the create method to initialize the scene view.
After creating the scene view the Composer Scene will now call for the
show method which has two phases, the will and did phase. The will
phase is when the scene is still off-screen and currently transitioning while the
did phase is when the scene is already onscreen. The did phase is where
you can start your animations, timers and music.
Before the current scene will go to the next scene, the hide method of the
current scene will be called first. This method is where you can cancel
transition, timers and remove event listeners. Like show method, this also has
two phases, the will and did phase. The will phase is when the scene is
still onscreen and the did phase is when the scene is completely removed
from the stage or now off-screen.
Lastly, the destroy method of the scene is called when composer.removeScene
is called. This method is where you want to put the removal of objects.
Parent methods are methods created outside the scene methods. This
custom methods are accessible by overlay scenes show and hide methods.
CHAPTER 11: CREATING A SIMPLE MOVIE LIST
APP
In this chapter we will learn about how to use a widget table view to create a
list of movie titles and display its details by the help of composer API. Create
a copy of the Template Project folder and rename it to Movie List App.
The interface will be simple. The main menu view will have a simple App
bar at the top of the screen and a table view as the content. The detail view
will have a simple App bar and text objects for the details of the movie
selected.
Movie List Module
A module is a part of a program that does a specific task. In Lua, modules
are simply table objects. Create a new file and save it as movies.lua. Open
the file and write the following.
local M = {}
M[1] = {
title = "Transformers",
description = "Science Fiction Movie",
year = "2016",
}
M[2] = {
title = "The Avengers Age of Ultron",
description = "Science Fiction",
year = "2016",
}
M[3] = {
title = "Batman",
description = "Fiction, Action",
year = "2016",
}
M[4] = {
title = "Superman the Dawn of Justice",
description = "Fiction, Action",
year = "2016",
}
M[5] = {
title = "The Suicide Squad",
description = "Fiction, Action",
year = "2016",
}
return M
Open the main.lua file and configure the first scene to display including the
background color.
display.setStatusBar( display.HiddenStatusBar )
display.setDefault( "background", 0.9, 0.9, 0.9 ) -- light grey
local composer = require("composer")
composer.gotoScene( "menu" )
In requiring a module to your code, simply use the require function and pass
the directory of the module without the .lua extension. If your module is inside
a subfolder, use a dot (.) to separate the folder names from the filename. For
example:
local movieList = require( "lib.movies" )
We will need the 3 handlers that will hold the objects such as the App Bar,
App title, and the table view.
Next is to declare constant variables. Localizing variables is much faster
compared to non-local variables. We will declare local constants for the
screen dimensions.
-- declare constans
local centerX = display.contentCenterX
local centerY = display.contentCenterY
local _W = display.contentWidth
local _H = display.contentHeight
Now we will display our App Bar and the Title of the App. Write the
following codes inside the create method of the scene.
appBar = display.newRect( sceneGroup, centerX, 0, _W, 56 )
appBar.anchorY = 0
This will display a white bar at the top of the screen and Title text in the
middle of the App Bar. Note that sceneGroup holds the entire scene objects.
We will now create a table view widget where we will display the movie
titles. Write the following code below the title object code.
tableView = widget.newTableView( {
width = _W,
height = _H - appBar.contentBounds.yMax,
onRowRender = onRowRender,
onRowTouch = onRowTouch,
hideBackground = true,
isBounceEnabled = false,
rowTouchDelay = 10,
x = centerX,
y = appBar.contentBounds.yMax + 3,
})
tableView.anchorY = 0
sceneGroup:insert(tableView)
Nothing will happen to the interface yet until we add rows to our table
view widget. Lets insert row base on the number of movies we have. Note
that # denotes the length of a table.
for i=1, #movieList do
tableView:insertRow({
rowHeight = 48,
rowColor = { default={0.9, 0.9, 0.9}, over={0.2, 0.2, 0.2, 0.5} },
})
end
The e.row is the parent group that holds all the objects in the row. The
contentWidth and contentHeight are the cache width and height of the row. The
index is the current index of the row. The movieTitle is the title of the movie.
You can now see the list of movies but you cant tap them yet since we didnt
declare the onRowTouch function yet. Below the onRowRender function, write the
following codes.
local function onRowTouch( e )
local phase = e.phase
local index = e.target.index
if (phase == "release") then
composer.gotoScene( "view", {effect = "slideLeft", time = 200, params = {id = index}} )
end
return true
end
This function will be called when the user taps the row. The e.phase is the
phase of the touch event and the index is the row index. Just like what we
discussed before, this function has the following phases:
tap the user taps the row.
press the user press the row (the finger is on the screen).
release the user releases the row (removes the finger from the
screen).
swipeLeft the user swipes the row from right to left.
swipeRight the user swipes the row from left to right.
In our case, the scene will go to Detail scene when the user releases its
touch from the row passing an optional table with property or parameter id as
custom data. We will use this custom data later to select the movie details
from the movie list.
Declare some reference names that will hold our objects, constant and non-
constant variables.
We have the appBar, title and the backBtn for basic App interface. The
movieTitle, movieDescription, and movieYear are the holder for movie details
which are text objects. The labelTitle, labelDescription, and labelYear are the
holder for the description labels.
The next identifiers are constant variables used for screen dimensions
reference. Lets create the interface. Just like the menu, we will create the
appBar and title in the same manner inside the create scene method. We will
also create a widget button to return us to the menu.
appBar = display.newRect( sceneGroup, centerX, 0, _W, 56 )
appBar.anchorY = 0
backBtn = widget.newButton( {
label = "Back",
fontSize = 18,
font = native.systemFont,
onRelease = function ( self, e )
composer.gotoScene( "menu", {effect = "slideRight", time = 200} )
end,
width = 32,
height = 32,
x = padding,
y = appBar.height * 0.5,
labelColor = {default={0.2, 0.2, 0.2}, over={0.8, 0.8, 0.8}},
})
backBtn.anchorX = 0
sceneGroup:insert(backBtn)
Run the project and you can now navigate from the menu to Detail Scene.
Lets display the title label. Write the following below the backBtn.
labelTitle = display.newText( sceneGroup, "Title", padding, appBar.contentBounds.yMax,
native.systemFont, 14 )
labelTitle.y = labelTitle.y + (labelTitle.height * 0.5) + padding
labelTitle.anchorX = 0
labelTitle:setFillColor( 0.1 )
This will display a text object below the appBar with font size of 14. Next
we will display the title of the movie.
movieTitle = display.newText( {
parent = sceneGroup,
text = movieList[id].title,
x = padding,
y = labelTitle.contentBounds.yMax,
font = native.systemFont,
fontSize = 20,
width = _W - (padding * 2)
}
)
movieTitle.y = movieTitle.y + (movieTitle.height * 0.5) + padding
movieTitle.anchorX = 0
movieTitle:setFillColor( 0.2 )
The display.newText function we used here is the new syntax for text objects,
it accepts a table with the following parameters.
1. parent (optional)
the parent group to insert the object.
2. text (required)
the text to display.
3. x, y (required)
the x and y coordinates for the object.
4. width, height (optional)
the width and height of the object.
5. font (optional)
the font style of the object which can be a constant, string or userdata.
1. The font family name (typeface name). You may obtain an array of
available font names via native.getFontNames().
2. Name of the font file in the Corona project's main resource
directory (alongside main.lua).
3. A font object returned by native.newFont().
4. A font constant such as native.systemFont or native.systemFontBold.
6. fontSize (optional)
the size of the text object in Corona content points.
7. align (optional)
This specifies the alignment of the text when the width is known,
meaning it either contains a newline or the width parameter is supplied.
Default value is "left". Valid values are "left", "center", or "right".
Note that align params is only available for the display.newText new syntax.
The event.params that we are talking about here is the params table passed
after the user taps a row from the menu (inside onRowTouch function). The
event.params.id is the data passed which have the value of index.
composer.gotoScene( "view", {effect = "slideLeft", time = 200, params = {id = index}} )
We use the id to get the descriptions from the movie list that is declared
inside our movies module. For example, the user taps the 3rd row and the
custom data passed will be 3. That data will be passed to id and we will use it
to access the movie description. This will result to the following.
title = "Batman",
description = "Fiction, Action",
year = "2016",
We can access the title, description and year by using the dot operator:
movieList[id].title
Try to run the project and tap the 3rd row. The title should display
Batman.
movieDescription = display.newText( {
parent = sceneGroup,
text = movieList[id].description,
x = padding,
y = labelDescription.contentBounds.yMax,
font = native.systemFont,
fontSize = 20,
width = _W - (padding * 2)
}
)
movieDescription.y = movieDescription.y + (movieDescription.height * 0.5) + padding
movieDescription.anchorX = 0
movieDescription:setFillColor( 0.2 )
Try to code the movieYear and labelYear by yourself the same manner we did
above and run the project.
If you notice, selecting a movie and going back to the menu, the next
selected movie wont display the correct details. This is because the Detail
Scene is already created so the displayed text objects are unchanged unless
you will destroy the scene and create the scene again. Lets do this by calling
composer.removeScene function inside the scene:show method at did phase of
menu scene. Go back to menu and write the following codes.
local prevScene = composer.getSceneName( "previous" )
if (prevScene) then
composer.removeScene( prevScene )
end
Lastly, we will remove the objects and nil out their handlers to free its
memory. Write the code inside the scene:destroy method of Detail Scene.
appBar:removeSelf( ); appBar = nil;
title:removeSelf( ); title = nil;
backBtn:removeSelf( ); backBtn = nil;
movieTitle:removeSelf( ); movieTitle = nil;
movieDescription:removeSelf( ); movieDescription = nil;
movieYear:removeSelf( ); movieYear = nil;
The scene:destroy method will be called when the user returns to the menu
scene.
CHAPTER 12: USING SQLITE3
SQLite3 is a local database that is used to store data in the device. Corona
supports SQLite databases on all platforms. In this chapter we will learn about
how to use SQLite database in our App.
This will create a table named test with columns id, content1 and
content2. The file will be created in the devices Documents Directory which
is a path for storing and retrieving files that need to persist between
application sessions. In the Corona Simulator, this will be in a sandboxed
folder on a per-application basis. You can view the directories/files via File
Show Project Sandbox.
To insert values, we will still use the same method.
-- Add rows with an auto index in 'id'. You don't need to specify a set of values because we're
populating all of them.
local testvalue = {}
testvalue[1] = "Hello"
testvalue[2] = "World"
testvalue[3] = "Lua"
db:exec( tablefill )
db:exec( tablefill2 )
db:exec( tablefill3 )
You can see the results to the terminal or build panel of Sublime Text. In
getting the current SQLite version use the function sqlite.version().
Declare needed handlers for text field, table view and submit button.
-- handlers
local field1
local tableView
local submitBtn
First lets create functions for database SQL commands like insert, delete
and retrieving data. Open a database file named data.db. It will created if
doesnt exist.
-- Open "data.db". If the file doesn't exist, it will be created
local path = system.pathForFile( "data.db", system.DocumentsDirectory )
local db = sqlite3.open( path )
We have a database named data.db which have a table list with columns id
and content. Lets create a function for inserting data to our database.
-- insert new row
local function insertData( value )
local db = sqlite3.open( path ) -- open connection
local sql_cmd = [[INSERT INTO list VALUES (NULL, ']]..value..[['); ]]
db:exec( sql_cmd ) -- execute sql command
db:close() -- close connection
end
Just like inserting data to the database, the SQL command is the only
difference in this function and the argument passed into it. In the SQL command
we will only delete the data from list which id is the current row tapped by the
user.
Next, is retrieving data from database.
-- retrieve data from database
local function getData( )
local db = sqlite3.open( path ) -- open connection
local data = {}
local counter = 1
for row in db:nrows("SELECT * FROM list") do
data[counter] = {}
data[counter].content = row.content
data[counter].id = row.id
counter = counter + 1
end
db:close() -- close connection
return data
end
This function will return a table of data that we retrieved from the database.
The method db:nrows(sql_command) returns a successive row from the database
based on the SQL SELECT command. We can pass the data to a table and use
the . dot operator to select the column of a certain data row. Example,
appData[1].content for the content of the first row.
Interface
We are done with the database functions. Next we will create the interface
for our App. We only need 3 objects in this App. The text field, table view and
a button.
field1 = native.newTextField( centerX, 100, _W-50, 80 )
field1.placeholder = "Enter any word"
field1.inputType = "default"
field1.size = 20
field1:resizeHeightToFitFont()
First object is the text field. We position it to the center of the screen and
100 pixels from the top. Dont forget to call the method
textField:resizeHeightToFitFont() to resize the text field to its font size. This will
be our source for data.
Next is the submit button where will be positioned below the text field.
submitBtn = widget.newButton(
{
label = "Submit",
onRelease = onRelease,
emboss = false,
shape = "roundedRect",
width = _W-50,
height = 40,
cornerRadius = 5,
labelColor = {default={0.2, 0.2, 0.2}, over={1, 1, 1}},
fillColor = { default={0, 0.9, 0.9}, over={0, 0.6, 0.5, 0.8} },
})
submitBtn.x = centerX
submitBtn.y = field1.contentBounds.yMax + submitBtn.height
Below the submit button is the table view. This will display the data fetched
from our database later.
The Process
The table view initially doesnt have data yet but once the database is
populated, we would want to display them immediately. Below the handler
declarations, insert the following:
local appData = {}
local dataCounter = 1
These variables will be used for the entire code. The appData will handle
the data retrieved from the database. The dataCounter will be the counter for
the number of data retrieved.
-- show list
appData = getData() -- retrieve data from database
local totalData = #appData -- total number of data retrieved
-- insert rows
for i=1, totalData do
tableView:insertRow({
rowHeight = 48,
rowColor = { default={0.2, 0.2, 0.2}, over={0.2, 0.2, 0.2, 0.5} },
})
end
Insert the above code to the bottom most part of the code. The second line
retrieves data from the database. The next line gets the total number of data
retrieved. The next few more lines is the rendering or inserting of rows to the
table view. Moving on, we will declare the needed functions for our code such
as the onRelease function of the button and onRowRender for the table view.
Insert the following code above the text field code.
-- onRelease function for submit button
local function onRelease( self, e )
insertData(field1.text) -- insert data to database
appData = getData() -- retrieve current data from database
-- insert rows
tableView:insertRow({
rowHeight = 48,
rowColor = { default={0.2, 0.2, 0.2}, over={0.2, 0.2, 0.2, 0.5} },
})
-- reset text field
field1.text = "" -- clear text field
native.setKeyboardFocus( nil ) -- remove softkeyboard from the screen
end
The code above inserts the data to our database using the value of the text
field. The appData gets the data from the database. The sixth line is the method
for inserting new row to the table view. The remaining codes resets the text
field. The native.setKeyboardFocus sets the focus of the soft keyboard for actual
devices. It accepts text field and text box handlers. If nil is passed then the
keyboard will be dismissed from the screen. If you run the project, the table
view inserts a new row but no content yet. We will work on that.
local function onRowRender( e )
-- cache variables
local row = e.row
local index = row.index
local contentWidth = row.width
local contentHeight = row.height
-- cache data from appData
local ID = appData[dataCounter].id
local content = appData[dataCounter].content
-- delete action
function delete:touch( e )
if (e.phase == "began") then
Its important to cache the variables since data may be different from one
row to another. The text object text displays the content from database and
delete displays an x to delete the row and data from the database. The touch
event listener calls for the function deleteData for the database and the method
tableView:deleteRow() method to delete an array or single row from the table
view and then decrement the total number of data which the dataCounter holds.
Outside the deletes touch method is the increment of the dataCounter, knowing
that the onRowRender is called not only once but multiple times every time the
App starts and when the user inserts new data to the database.
Run and test the project. You can do a lot of things from this Project for
example, to do list App, a simple registration App, Login-logout App and so
on.
ABOUT T HE AUTHOR
Aj Sotelo is a Mobile Game Developer since 2015 and have been using
Corona SDK for almost two years in his mobile development. He is a
freelance for almost 1 year and developed several Games and Apps for his
clients and able to developed one game for his own and able to publish it to
Google Play Store. He loves playing games, playing the guitar, learning new
things and travel different places.
Now, he is trying to walk through the path of being an online entrepreneur.
He will start his own blog soon for sharing his experience, thoughts and
knowledge about mobile development. If you have something to say to him
please leave him a message and help us improve. We will be waiting for your
feedbacks, comments and suggestions. Thank you and God bless.