FAQ Wednesday #5

Share on Facebook0Share on Google+0Tweet about this on TwitterShare on LinkedIn0

Corona FAQIt’s Wednesday and time for another FAQ session. Here are five frequently asked questions (FAQ).

Question 1

Now that you added the Lua File System (LFS), how can I use it to get a list of files in the /Documents directory?


The Lua File System was added starting with Corona build 2012.805. You can read the tutorial here.

The LFS now makes it possible to create, delete, and access subdirectories. The key to all of this is creating a string containing the path to the directory. In iOS and Android, there are three main directories: Resource, Temporary, and Documents and they are accessed using Corona constants. These userdata constants need to be converted to a string so they can be used with the LFS. system.pathForFile converts the userdata constant into a string, You specify the file or directory name along with the base directory, and it returns a full path to the file/directory.

local path = system.pathForFile( "data", system.DocumentsDirectory )

The above code return a string something like this: “/var/mobile/Applications//Documents/data”

Here is how you would use it with LFS to print out a list of files.

local lfs = require "lfs"

-- Print the files in the path
local function printDir( path )
print( "nFiles in path: " .. tostring( path ) )

local pathType = ""

-- Check to see if path exists
if path and lfs.attributes( path ) then
pathType = lfs.attributes( path ).mode

if pathType == "directory" then
for file in lfs.dir( path ) do
local str

-- Skip the current and up-one directories
if "." ~= file and ".." ~= file then
str = file

local fileAtr = lfs.attributes( path .. "/" .. file )
if fileAtr then
str = str .. " --> (" .. fileAtr.mode .. ")"
str = str .. " --> (none)"

print( str )
str = "Path is not a directory!"
print( str )

And this is how you would call it to print the files found in the /Documents directory and the /Documents/data subdirectory (if it exists).

path = system.pathForFile( nil, system.DocumentsDirectory)
printDir( path )
path = system.pathForFile( data, system.DocumentsDirectory)
printDir( path )

The above code can be easily modified to return a table of file names instead of printing them.

Question 2

I’m getting a warning and an error when I tried to access files in the Resource directory. Is this a bug?


Whenever you use system.pathForFile and the base directory is system.ResourceDirectory, Corona tries to verify that a file exists and generates a warning message along with returning a nil value for the path. This doesn’t work if the filename parameter is really a directory name. The trick is to do the following.

local path = system.pathForFile( nil, system.ResourceDirectory )

This will not generate any warning message and returns a string pointing to the Resource directory. If you need to create a path to a subdirectory under the Resource directory, you can append it as shown in the following code.

path = system.pathForFile( nil, system.ResourceDirectory)
printDir( path )
path = system.pathForFile( nil, system.ResourceDirectory) .."/".."data"
printDir( path )

Note: system.ResourceDirectory will not work on Android devices because the Resource directory is not really part of the file system.

Also be aware that the Resource directory is a read-only directory and cannot be written to.

Question 3

Setting Multitouch for a single touch app.


This is not really a question but more of a tip. Enable multitouch in your app, even if your app doesn’t require multitouch. Corona defaults to multitouch off. This means if you have a touch listener, you will only receive one touch event at a time. If the user is touching the screen and then tries to tap a button or move an object with another finger, nothing will happen because there is already a touch active. This is common with apps in landscape mode where the user may be resting their fingers on the screen to hold the device.

The solution is to add the following at the beginning of your code.

system.activate( "multitouch" )

This will generate touch events for each finger touching the screen. Unless they are touching an area with an active “touch” listener, this should not cause any problems with your existing code and make your app more “user friendly.”

Question 4

How can I clear the “badge” number on the app icon in iOS?


Local Notification will set the badge number on the app’s icon when the notification fires (indicating that there is something pending), but how do you clear it? The answer is native.setProperty API.

native.setProperty( "ApplicationBadgeIconNumber", 0 )

The above will remove the badge number from the app’s icon.

Here is an example of the Local Notification code that clears the badge.

display.newText( "Setting Local Notification ...", 10, 30 )

-- Options for iOS
local options = {
alert = "Wake up!",
badge = 1,
sound = "alarm.caf",
custom = { foo = "bar" }

-- schedule using UTC (Coordinated Universal Time) time + 60 seconds
local utcTime = os.date( "!*t", os.time() + 60 )
local notification = system.scheduleNotification( utcTime, options )

-- Local Notification listener
local notificationListener = function( event )
display.newText( "Notification Received " .. event.badge, 10, 70 )
native.setProperty( "applicationIconBadgeNumber", 0 )

Runtime:addEventListener( "notification", notificationListener )

Note: Our documentation for “badge” talks about the value incrementing or decrementing the badge number. This was taken from Apple’s documentation and really means that you can increment or decrement the badge number in your code. The badge number you specify in your code is what’s displayed on the icon. Setting the badge number to 0, clears (removes) the badge.

Remember, Local (and Push) Notifications are only available on iOS at this time.

Question 5

I have a game and I don’t want the device to go to sleep if the user doesn’t touch the screen. Is that possible?


Yes, and the solution is one of the “system” APIs that works on both iOS and Android (but not in the simulators).

system.setIdleTimer( false ) -- disable device sleep mode

Setting the idle timer to false keeps the device from going to sleep. Setting it to true enables (or re-enables) sleep mode. The default mode if you don’t call this API is true. Be aware that disabling sleep mode can run down the device’s batteries in a hurry so you need to use this feature with caution.

That’s it for today’s questions. I hope you enjoyed it and even learned a few things.

Share on Facebook0Share on Google+0Tweet about this on TwitterShare on LinkedIn0

This entry has 5 replies

  1. J. A. Whye says:

    Cool tip about multi-touch — now I have reason to turn it on! 😉


  2. Mo says:

    +1 for multitouch! I was only using it during game play. But I may make it game wide..

    About the ” system.setIdleTimer( false ) ” Would you suggest set it up for the all game (in main.lua) and then turn it off at exit OR use it only for game screen when something is really happening and you do not want the screen to shutdown during the action?

    LOVE the FAQ! Unfortunately I will need to wait another week now:)

    Thanks Tom.


  3. STu says:

    Is there a path for android that works in regards to Question 2?

    • Alex Poon says:

      Do you have any solution for android?

  4. J. A. Whye says:

    The first part of Question 4 has incorrect information. The code should read like this:

    native.setProperty( “applicationIconBadgeNumber”, 0 )

    It’s correct in the second section of example code, but that first single snippet (which is what I grabbed to use, with poor results) is incorrect.