Who's using what for Push Notifications?

hi, Emmanuel, and welcome to the “Oh.My.God.Why.Is.Push.So.Darn.Hard” club :slight_smile: for Android. Yeah, we can definitely send pushes to Android devices as long as we use GCM directly or use a service that leverages GCM such as PushSwoosh. 

Interestingly, Urban Airship is now using GCM rather than their homegrown ‘Helium’ service (see below). This means that we ought to be able to use them for basic push needs. 

  • I just took another look at UA and see that they seem to support Scheduled Notifications. It would be worth testing for iOs and Android. UA is a solid push service that I know works using Corona for iOs at least. It has some more robust capability in that you can also have your clients subscribe to channels. 

What UA service should I be using for Google Android?

 

Since Helium is being sunset (see our FAQ)You should be using our Google Cloud Messaging (GCM) service.  All new customers default to GCM, and we are actively working with customers currently using our Helium platform for Android to help them migrate to GCM.

 

Are there any limitations to UA’s support of Google Cloud Messaging (GCM)?

 

Urban Airship provides full support for the GCM API.  You can use our service to send push notifications to any device running Android 2.2 or higher (97% of the market).  

Regarding UA, even though they use GCM you still have to require their .jar as far as I could tell.

This page has sample device registration with Curl for iOS but for Android they just say “Android APID registration should always happen from our client library. See our docs here for more information.”

I think we really ought to write a Parse or UA push plugin. I’ve emailed plugins@coronalabs.com to see what they think. Jon, maybe you and I can collaborate to get something working. We really need this.

Another plugin I’d like to see is Kiip! That’s a cool thing for ‘real rewards’. 

thanks, let’s keep trying

Jen

Thanks Jen for letting me join the “Oh.My.God.Why.Is.Push.So.Darn.Hard” club :wink:

If you have more information about Corona SDK + Push (Parse, UA …) for Android, let me know ! (Hope if there is a solution, it won’t be a “pro” feature only ;P).

I’m going to try when I have time to setup a server (PHP or Python) with Google App Engine for pushing.

Good luck for your projects !

So, after crying over to have a proper Android / IOS push service and reading all the posts at this topic, I think I found a solution to our pains :slight_smile:

I found Netmera and tried their REST API to register, send push notification to an Android device. Although I didn’t try the IOS part of thier service, but I’m guessing that that part would work.

The good thing about Netmera is their free plan has 1M push messages per month and you can access their REST API, meaning you can run your backend service and use Netmera to send notifications to both platforms. (they’re using GCM)

Also they have quite good list of extra services, in case you’d like to grow your membership.

Here is the working code, which I just editied the Urban Airship code I found somewhere :slight_smile: Also here’s the link for their REST API documentation for push

[lua]

local json = require(“json”)

– Here is the implementation of Push Notification in Corona SDK

local launchArgs = …

local APIKEY = “xxxxxxNetmera APIKeyxxxxxxxxx”

if launchArgs and launchArgs.notification then

    – The code below will only trigger if your app is dead and not active at all    

    – *********************************************************************************    

    native.showAlert( “launchArgs”, json.Encode( launchArgs.notification ), { “OK” } )

    --[[ notification table contains:    

    launchArgs.notification.type - “remote”    

    launchArgs.notification.name - “notification”    

    launchArgs.notification.sound - “sound file or ‘default’”    

    launchArgs.notification.alert - “message specified during push”    

    launchArgs.notification.badge - “5” – badge value that was sent    

    launchArgs.notification.applicationstate - “inactive”    --]]    

    native.showAlert( “Yep notification received”, launchArgs.notification.alert, { “OK” } )

end

– Function to handle Network Traffic Response from Urban Airship

local function netmeraNetworkListener( event )    

    if ( event.isError ) then        

    native.showAlert( “Network error!”, “Error has occured from Netmera”, {“OK”})    

    else        

    native.showAlert( “Netmera”, event.response, {“OK”})    

    end

end

– Function to register device for Netmera Services

local function registerDevice(deviceToken)    

        local headers = {}

        headers[“X-netmera-api-key”] = APIKEY

        headers[“Content-Type”] = “application/json”

        commands_json =

            {

             [“registrationId”] = deviceToken,

             [“platform”] = “ANDROID”,

             [“tags”] = {“tag1”, “tag2”},                

            }        

        postData = json.encode(commands_json)

        print("postData: " … postData)

        data = “”

        local params = {}

        params.headers = headers

        params.body = postData

        network.request( “http://api.netmera.com/push/1.1/registration” ,“POST”, netmeraNetworkListener,  params)

end

– notification listener

local function onNotification( event )    

    if event.type == “remoteRegistration” then        

    registerDevice(event.token)    

    elseif event.type == “remote” then    

    – The code below will only trigger if your app is alive and kicking

    – *********************************************************************************    

    native.showAlert( “remote”, json.encode( event ), { “OK” } )    

    --[[ notification table contains:    

    launchArgs.notification.type - “remote”    

    launchArgs.notification.name - “notification”    

    launchArgs.notification.sound - “sound file or ‘default’”    

    launchArgs.notification.alert - “message specified during push”    

    launchArgs.notification.badge - “5” – badge value that was sent    

    launchArgs.notification.applicationstate - “inactive”    --]]    

    native.showAlert( “Yep notification received”, event.alert , { “OK” } )   

    end

end

    

Runtime:addEventListener( “notification”, onNotification )

[/lua]

Well after some tests and help from Netmera guys, I finally figured out how to use alert and custom fields with netmera :slight_smile:

The code I posted previously is working fine, but I was trying to send some custom data through their REST API and was hitting the wall. We figured out at last and here are some headlines and an example curl request.

  1. Because Alert and Custom fields are not explicitly defined by Google, normally what you send in title or message part of a push alert from Netmera doesn’t include these fields. So you receive the notification but both alert and custom fields will be empty. So this is the first step towards working notifications.

  2. Netmera provides a customjson field that you can put anything in it. So putting a JSON into the custom field with alert and custom fields lets us to receive whatever we’d like to get in Corona.

  3. But of course we’d like to send a json in our custom field, so we need to take care of " with escape character, , here is a sample custom field:

“custom”:{“test”:1}

Btw the alert field shoudl be something like this;

“alert”:“testing alert”

And finally here are some examples;

This is the data part of a Netmera notification REST call;

{“title”: “NOT IMPORTANT FOR CORONA”,“notificationMsg”: “NOT IMPORTANT FOR CORONA”,“registrationId”: “THIS IS THE REGID OF A SPECIFIC DEVICE TO SEND NOTIFICATION”,“customJson”:{“alert”:“THIS IS WHAT YOU GET IN event.alert IN CORONA”, “custom”:"{“boolean”: true,“number”: 123.456,“string”: “some string”,“array”: [true,false, 0, 1, “”, “This is a test.”],“table”: { “x”: 1, “y”: 2 }}"}}

Finally a complete curl commad:

curl -X POST -H “X-netmera-api-key:xxxxNETMERAAPIKEYxxxx” -H “Content-Type:application/json” -d ‘{“title”: “NOT IMPORTANT FOR CORONA”,“notificationMsg”: “NOT IMPORTANT FOR CORONA”,“registrationId”: “THIS IS THE REGID OF A SPECIFIC DEVICE TO SEND NOTIFICATION”,“customJson”:{“alert”:“THIS IS WHAT YOU GET IN event.alert IN CORONA”, “custom”:"{“boolean”: true,“number”: 123.456,“string”: “some string”,“array”: [true,false, 0, 1, “”, “This is a test.”],“table”: { “x”: 1, “y”: 2 }}"}}’ http://api.netmera.com/push/1.1/notification

Couldn’t try the iOS part yet but I’m assuming that part will not be a problem. Ping me if you need help, I’ll try my best. 

Cheers,

Ulas

Ohh also, most probably I’ll be working with Netmera guys to prepare a module that will include some additional functionality. They have some cool notification analytics stuff within their SDK, and they told me maybe we can implement some of them as a LUA module so, also Basic and Pro users can use them.

Glad you got it working for you! :slight_smile: Nice work. 

Nice! I will probably switch to Netmera then.

I had a soo much trouble trying to get push to work on android. I ended up putting together a rails app, set up on heroku, that I post the android’ s device Id to. From there I post to gcm and the push goes through. This way I can use rails to send notification to specific users. The corona app just registers the device Id upon launch. I still can’t read launchargs but that’s another thread.

I’m doing the same but with Tornado (Python). When I send ID to server I register if its and android or an ios device. If iOS I use UA. Just sucks to have to use 2 different methods on the server.

I actually just recently made a little bit of progress using Parse’s cloud code. It is sort of like using Heroku in that you write locally and then post it up to your servers. You then call the cloud code via the regular network request. The cloud code can call GCM. I have it working for one element in my app, and I’m hoping I can make it work for Android push… I’ll let you know! Thanks for the input!

I would love to hear more on this. I recently started using Parse for IOS and implemented their REST API on my small web app that my client will see to send their push messages so its all happy happy. Now I need to deliver on Android. I’m ok to use a totally separate service if it comes to that. Anything that works for Android with the ease of Parse on IOS?

Thanks!!!

Hang tight, ksan, I’m working on it. I love Parse and use it for almost everything I need server-side so if I can make the cloud code solution work I’ll post here. :slight_smile:

This is great!!! Thanks much for persevering with this effort. Cheers!!!

Just read this thread once again. So if I understand this right, PushWoosh works on both platforms without much fuss but the downside is the monthly $ that needs to be paid for remote API right? With Parse if you stay under the threshold its all free which is great! 

Yes that pretty much sums it up.

Soldier on Jen! :slight_smile:

I’m using GCM and that is not how you get the installation ID. It is passed through to the app when it is installed using something like this:

[lua]

function onNotification(event)
    print(" – main - onNotification(event)")
    
    if event.type == “remoteRegistration” then
        mojoData.PTOKEN = event.token    – Save off the installation token (push id)
–        native.showAlert( “remoteRegistration”, event.token, { “OK” } )
        print(" – saved token info: “, event.token)  
    elseif event.type == “remote” then
–        native.showAlert( “localNet Notification”, Json.encode( event ), { “OK” } )
        print(” – localNet Notification", Json.encode( event ) )               
        if( event.applicationState == “active” ) then
            native.setProperty(“applicationIconBadgeNumber”, 0)             – clear out list of notifications from notification center…
 
            native.showAlert( “localNet Notification”, Json.encode( event.alert ), { “OK” } )           
        end        
    end
    
    return true
end

– Tried adding the listener in systemListener(), but no go, so initializing right in main, like corona docs show – works here :confused:

Runtime:addEventListener( “notification”, onNotification ) 

[/lua]

Argh… The website never likes my code blocks :/  Using Decoda editor, and mebbe it doesn’t use cr/lf or something :confused:

hi, mpappas, I actually got a little hung up on this last night and today. Are you able to get your Android’s installation id using the onNotification listener? Somehow, I’m not able to. Would you be able to share your config and settings file with Android permissions? I thought I had this working a while ago but on my Samsung II it’s not. The sample GooglePushNotification app doesn’t register either. 

thanks,

Jen

Yes, the installation id (called a token in the docs) comes through just fine. I believe it not only comes to my app on installation, but that the corona sdk send it every launch of my app (I have some code that checks if it was already sent to the server, so I think that’s why I added it way back when). Anyways:

Dunno if they will appear correctly, but here they are:

Config:

[lua]

application =
{
    content =
    {
            width = 640,
            height = 960,
            scale = “letterbox”,
            fps = 60,            
    },
        
    notification =
    {
        iphone =
        {
            types =
            {
                “badge”, “sound”, “alert”
            }
        },
         google =
        {
            projectNumber = “261275118095”,
        },        
    },
        
}

[/lua]

build.settings:

[lua]

settings =
{

     android =
     {
        largeHeap = true,
     
         permissions =
        {
        { name = “.permission.C2D_MESSAGE”, protectionLevel = “signature” },
        },     
        usesPermissions =
        {
             “android.permission.INTERNET”,
             “android.permission.ACCESS_FINE_LOCATION”,
             “android.permission.ACCESS_COARSE_LOCATION”,
             “android.permission.ACCESS_LOCATION_EXTRA_COMMANDS”,
             “android.permission.WRITE_EXTERNAL_STORAGE”,
             “com.android.vending.BILLING”,                
             “android.permission.CAMERA”,  
             “android.permission.CALL_PHONE”,
             “android.permission.RECEIVE_BOOT_COMPLETED”,          
             “android.permission.GET_ACCOUNTS”,
             “com.google.android.c2dm.permission.RECEIVE”,
             “.permission.C2D_MESSAGE”,
             “android.permission.RECORD_AUDIO”,       
        },
        usesFeatures =
        {
            { name = “android.hardware.camera”, required = false },
            { name = “android.hardware.camera.front”, required = false },                 
            { name = “android.hardware.telephony”, required = false },                                        
        },        
    },
    
    iphone =
    {    
        components = {},
        
        plist =
        {
            UIPrerenderedIcon = true,
            UIApplicationExitsOnSuspend = false,

            CFBundleIconFile = “Icon.png”,
            CFBundleIconFiles = {
                    “Icon.png” ,
                    “Icon@2x.png” ,
                    “Icon-72.png”,
            },
            
            FacebookAppID = “423650107852131”,            
            CFBundleURLTypes =
            {
                {
                CFBundleURLSchemes =
                    {
                    “fb424050273855136”,
                    }
                }
            },
        },
    },            
}
 

[/lua]