Local/Push Notifications

This guide discusses how to implement local and push notifications.

Overview

Corona SDK supports two types of notifications: local and push. The purpose of both notification types is to notify the user about something — a message or an upcoming appointment, for example — when the application isn't running in the foreground. The essential difference between local notifications and push notifications is simple:

Note

Notifications are only supported on iOS and Android, not on macOS desktop, Windows desktop, Windows Phone, Apple TV, or Android TV.

Usage Notes

To use push notifications, remember the following points:

  1. The app has to support a registration process and it must support incoming messages.

  2. You must configure your app and devices so that Apple and/or Google recognizes them. Apple/Google will send the actual messages out to devices.

  3. If using iOS/Apple, your app cannot send push requests directly to their servers.

  4. We recommend that you use a third-party service to send push requests to Apple or Google, who in turn sends them onward to devices. That service can be a company like OneSignal, PushWoosh, or Urban Airship that specializes in push notifications.

  5. Another option to handle push notifications on iOS is EasyAPNS. This is a PHP/MySQL setup that registers devices in your own database and allows you to send push notifications from your own server. Please visit www.easyapns.com for more information.

App Interaction

How an app reacts to notifications depends on its state:

Project Settings

To use the notifications plugin, add an entry into the plugins table of build.settings. When added, the build server will integrate the plugin during the build phase.

settings =
{
    plugins =
    {
        ["plugin.notifications"] =
        {
            publisherId = "com.coronalabs"
        },
    },      
}

Then, within the code module which uses notifications functions, simply require() the library as follows:

local notifications = require( "plugin.notifications" )

iOS Setup

Much of the iOS configuration for push notifications is done within the Apple Developer portal. Please refer to the guide for details.

In addition, you must include a notification table in the config.lua file (guide) to enable various features for push notifications. This tells the system which of the alert types you plan to use.

application = 
{
    content =
    {
        width = 320,
        height = 480,
        scale = "letterbox",
        xAlign = "center",
        yAlign = "center"
    },

    notification = 
    {
        iphone =
        {
            types = { "badge", "sound", "alert" }
        }
    }
}
Important

For iOS, the app must explicitly register for push notifications via the notifications.registerForPushNotifications() API. This will show the popup which asks the user if they want to enable push notifications.

Android Setup

Android also requires some additional configuration for push notifications. In the config.lua file (guide), add a notification table as follows. When you register with the Google GCM service, you'll get the projectNumber value needed for the google table.

application = 
{
    content =
    {
        width = 320,
        height = 480,
        scale = "letterbox",
        xAlign = "center",
        yAlign = "center"
    },
          
    notification = 
    {
        google =
        {
            projectNumber = "3982849975315"
        },
    }
}

In addition, you must include the following permissions in the build.settings file (guide). Failure to include these entries will cause your push notifications to fail.

settings
{
    android =
    {
        permissions =
        {
            { name = ".permission.C2D_MESSAGE", protectionLevel = "signature" },
        },
        usesPermissions =
        {
            "android.permission.INTERNET",
            "android.permission.GET_ACCOUNTS",
            "android.permission.RECEIVE_BOOT_COMPLETED",
            "com.google.android.c2dm.permission.RECEIVE",
            ".permission.C2D_MESSAGE",
        },
    },
}

Android Icons

You can set custom notification icons in a Corona project by adding the following files to the root of the project directory, just like custom application icons. Note that different Android OS versions support different notification icon themes. You must support all of them or the app may get rejected in the review process. Please see Google's official documentation for details on icon sizes and themes.

File Size (w×h)
IconNotificationDefault-ldpi-v11.png 18 × 18
IconNotificationDefault-mdpi-v11.png 24 × 24
IconNotificationDefault-hdpi-v11.png 36 × 36
IconNotificationDefault-xhdpi-v11.png 48 × 48
IconNotificationDefault-xxhdpi-v11.png 72 × 72
IconNotificationDefault-xxxhdpi-v11.png 96 × 96
IconNotificationDefault-ldpi-v9.png 18 × 18
IconNotificationDefault-mdpi-v9.png 24 × 24
IconNotificationDefault-hdpi-v9.png 36 × 36
IconNotificationDefault-xhdpi-v9.png 48 × 48
IconNotificationDefault-ldpi.png 18 × 18
IconNotificationDefault-mdpi.png 24 × 24
IconNotificationDefault-hdpi.png 36 × 36
IconNotificationDefault-xhdpi.png 48 × 48
Note
  • The -v11 set is for Android 3.0 or higher. These icons are expected to be white.
  • The -v9 set is for Android 2.3. These icons are expected to be grey.
Important

If you're a Corona Enterprise developer, please refer to the Enterprise and Android Icons notes below.

Managing Local Notifications

To schedule a local notification, use the notifications.scheduleNotification() function and specify the time of the future event in one of two formats:

The UTC option should be a time table as returned by os.date("!*t"). Note that a common pitfall is to forget the exclamation point and pass "*t" instead of "!*t" — this will return the time structure in local time (your timezone) instead of UTC.

You should also pass an options table containing any the following parameters:

Important

To cancel a local notification before it triggers, use the notifications.cancelNotification() function and pass the ID returned by notifications.scheduleNotification().

Handling Notification Events

In accordance with the Corona event/listener model, if your app is running in either the foreground or background and a notification arrives, you'll receive a notification event. It's your responsibility to initialize the system and set up a listener function to handle these events. Please review the following framework and then read the detailed subsections below.

local function notificationListener( event )

    if ( event.type == "remote" ) then
        --handle the push notification

    elseif ( event.type == "local" ) then
        --handle the local notification
    end
end

--The notification Runtime listener should be handled from within "main.lua"
Runtime:addEventListener( "notification", notificationListener )

Notification Data

A notification event returns a table of information which you can use to manage the specific notification. This table includes the following:

  • event.alert — string value consisting of the message to display.
  • event.applicationState — string value of either "active" or "inactive".
  • event.badge — number representing the badge count (iOS only).
  • event.custom — if this table exists, there may be data from the push service that helps your app react to the data. This is known as deep linking.
  • event.name — string value of "notification".
  • event.sound — string value representing a sound file, i.e. "alarm.caf".
  • event.type — string value of "local" for local notifications or "remote" for push notifications.

Launch Arguments

When the operating system, as the result of an incoming notification, starts your app from an inactive (not running) state, the app receives the data as part of launchArgs instead of triggering a notification event. You can use your notificationListener function to process the launch arguments.

local launchArgs = ...

if ( launchArgs and launchArgs.notification ) then
    notificationListener( launchArgs.notification )
end
Important

This launchArgs processing must be in main.lua since it's the code which receives the data.

Notification Badges

Notification badges (iOS only) are easily recognized by a small circle/number overlaying the app icon. They are available only on iOS. If a notification passes a badge value, a badge equal to that value will appear over the app icon.

It's your responsibility to read and set the badge number depending on its previous value. This is accomplished with the native.getProperty() and native.setProperty() functions.

In almost every case, when the user opens/handles the notification, you should decrement the badge number by 1 or clear it entirely.

-- Decrement the badge number by 1
local function notificationListener( event )

    if ( event.type == "local" ) then
        -- Handle the local notification
        local badge_num = native.getProperty( "applicationIconBadgeNumber" )
        badge_num = badge_num - 1
        native.setProperty( "applicationIconBadgeNumber", badge_num )

    elseif ( event.type == "remote" ) then
        -- Handle the push notification
        if ( event.badge and event.badge > 0 ) then 
            native.setProperty( "applicationIconBadgeNumber", event.badge - 1 )
        end
    end
end

-- Or clear the badge entirely
native.setProperty( "applicationIconBadgeNumber", 0 )

Notification Sounds

By default, the device will play a sound when a notification comes in. You can specify a custom sound file in your project to play instead of the default sound. For instance, if you have the file notification.wav inside your app bundle, you can specify the string "notification.wav" as part of the push bundle (if the sending service supports it) and the operating system will play that custom sound instead of the default. In this case, the event.sound entry in the event listener will equal this string.

Remote Registration

For push notifications, your app must register with the push provider's servers (Apple and Google). Corona handles the registration process for you in the background. Because you'll typically use a service to send push requests to the Apple and Google servers, that service needs to know about your app and device. Once registered, Corona will trigger the "remoteRegistration" notification event.

To accommodate this, add an additional condition to your notification listener:

local function notificationListener( event )

    if ( event.type == "remote" ) then
        --handle the push notification

    elseif ( event.type == "remoteRegistration" ) then 
        --code to register your device with the service
    end
end

--The notification Runtime listener should be handled from within "main.lua"
Runtime:addEventListener( "notification", notificationListener )
Note

The code required to register your device varies depending on the service. Please consult your preferred provider's documentation or seek assistance in the Corona Forums.

Enterprise Usage

iOS Delegates

If you're implementing notifications via Corona Enterprise for iOS, the following must be added to build.settings:

settings = 
{
    iphone =
    {
        plist =
        {
            CoronaDelegates = { "CoronaNotificationsDelegate" }
        },
    },
}

Android Icons

When developing natively for Android, Google wants all icons in the project's res directory. This is important because Google's Android build process generates code, creating a R.java file containing unique integer IDs to every resource that your project and its libraries contain. The IDs are needed to access these resources, including the notification icons.

First, you should become familiar with how Android handles resources by reading Google's official documentation.

When developing with Corona Enterprise, you need to override Corona's notification icon resources with your own. Before proceeding, inspect the Corona library's resource directory:

./CoronaEnterprise/Corona/android/lib/Corona/res

In this directory, every drawable directory contains a file named corona_statusbar_icon_default.png. This is the image file to override. Note that this action should be an "override" and not a replacement. You should not modify the contents of the Corona library directory!

To override these notification image files with your own, you need to set up the Android project with the same drawable directories under your res directory. Add each IconNotification*.png icon to its respective drawable directory by resolution and version (see Android Icons above). You also must rename these files to corona_statusbar_icon_default.png.

If your Enterprise project is Android Studio-based, you'll need to make a small change to the build.gradle (Module: app)'s copyCoronaResources task to ignore the notification icons provided in the Corona library project. Do this by replacing the from fileTree(...) line with the following:

from fileTree(dir: "$coronaEnterpriseAndroidLibDir/res", exclude: '**/corona_statusbar_icon_default.png')

For Ant-based projects, this works as follows: when you do an Android build, it builds the app's libraries first, then it builds the app. If the Android build process finds resources files named identically between your app and its libraries, the app's resource files always take precedence and will be used instead of the library's resources. This is why most third-party libraries prefix their resource file names using the library's name to help avoid conflicts.