Monday, February 13, 2012

VB.NET Server side code to send C2DM messages for android?


VB.NET Server side code to send C2DM messages to the Google servers.
This code gets a Google "ClientLogin" and then sends a message to the Google C2DM servers. You will need a RegistryID from a Android phone app for this to work properly.
You will also need to get the "Google.GData.Client" client libs. The libs simplify your life because then you don't need to figure out SSL and stuff. More info here: http://code.google.com/apis/gdata/docs/auth/clientlogin.html
Imports Google.GData.Client

Module Module1

    Private Const C2DM_SEND_URL As String = "https://android.apis.google.com/c2dm/send"
    Private Const CLIENT_SEND_URL As String = "https://www.google.com/accounts/ClientLogin"

    Private googleAuthToken As String = Nothing

    'This is my Phone's ID for this app. It will be sent to the GServer so that google knows where to send the message
    Private RegID As String = "" '
    
    Sub Main()
        GetClientLogin()
        SendRequest()
    End Sub

    Private Sub GetClientLogin()

        Dim email As String = "youremail@gmail.com"
        Dim password As String = "password"
        
        Dim authFactory As New GDataGAuthRequestFactory("cl", "yourCompany-c2dmServerPOC-v1")
        Dim cred As New GDataCredentials(email, password)

        authFactory.AccountType = "GOOGLE"
        'This specifies that the token is going to point to the C2DM Service
        authFactory.Service = "ac2dm"

        ' This gets the Google ClientLogon token
        Try
            googleAuthToken = authFactory.QueryAuthToken(cred)
        Catch ex As Exception
            Console.WriteLine("Error when retrieving Google Token")
        End Try
        
    End Sub

    Private Sub SendRequest()

        'Build the POST Body
        Dim body As String = Nothing
        body += "collapse_key=nothing"
        body += "&data.burst_id=" + "12345"
        body += "&registration_id=" + RegID

        'Build the POST Header
        Dim webReq = DirectCast(WebRequest.Create(C2DM_SEND_URL), HttpWebRequest)
        webReq.ContentLength = body.Length
        webReq.Method = "POST"
        webReq.ContentType = "application/x-www-form-urlencoded"
        webReq.UserAgent = "C2DM-InfoBurst"
        webReq.Headers.Add("Authorization: GoogleLogin auth=" & googleAuthToken)

        'This is important because you have to 'ignore' the SSL check. We could build this out further 
        ServicePointManager.ServerCertificateValidationCallback = Function() True

        'This POSTs the call 
        Using webReqStream = New StreamWriter(webReq.GetRequestStream(), Encoding.ASCII)
            Dim data = body
            webReqStream.Write(data)
            webReqStream.Close()
        End Using

        'This gets the response
        Dim webResp As HttpWebResponse
        Dim ResponseStatus As String = ""
        Dim ResponseCode As String = ""
        Dim MessageId As String = ""
        Dim responseBody = ""

        Try
            'Gets the response in HttpWebResponse
            webResp = TryCast(webReq.GetResponse(), HttpWebResponse)

            'Gets the Response body
            responseBody = (New StreamReader(webResp.GetResponseStream())).ReadToEnd()

            If responseBody.StartsWith("id=") Then
                'Get the message ID
                MessageId = responseBody.Substring(3).Trim()
            Else
                'Handle the type of error
                If responseBody.StartsWith("Error=") Then
                    Dim wrErr = responseBody.Substring(responseBody.IndexOf("Error=") + 6)
                    Select Case wrErr.ToLower().Trim()
                        Case "quotaexceeded"
                            ResponseStatus = MessageTransportResponseStatus.QuotaExceeded
                            Exit Select
                        Case "devicequotaexceeded"
                            ResponseStatus = MessageTransportResponseStatus.DeviceQuotaExceeded
                            Exit Select
                        Case "invalidregistration"
                            ResponseStatus = MessageTransportResponseStatus.InvalidRegistration
                            Exit Select
                        Case "notregistered"
                            ResponseStatus = MessageTransportResponseStatus.NotRegistered
                            Exit Select
                        Case "messagetoobig"
                            ResponseStatus = MessageTransportResponseStatus.MessageTooBig
                            Exit Select
                        Case "missingcollapsekey"
                            ResponseStatus = MessageTransportResponseStatus.MissingCollapseKey
                            Exit Select
                        Case Else
                            ResponseStatus = MessageTransportResponseStatus.[Error]
                            Exit Select
                    End Select
                End If
            End If
        Catch ex As Exception
            If webResp.StatusCode = HttpStatusCode.Unauthorized Then
                '401 bad auth token
                ResponseCode = MessageTransportResponseCode.InvalidAuthToken
                ResponseStatus = MessageTransportResponseStatus.[Error]
            ElseIf webResp.StatusCode = HttpStatusCode.ServiceUnavailable Then
                'First try grabbing the retry-after header and parsing it.
                Dim retryAfter As New TimeSpan(0, 0, 120)

                Dim wrRetryAfter = webResp.GetResponseHeader("Retry-After")

                If Not String.IsNullOrEmpty(wrRetryAfter) Then
                    Dim wrRetryAfterDate As DateTime = DateTime.UtcNow

                    If DateTime.TryParse(wrRetryAfter, wrRetryAfterDate) Then
                        retryAfter = wrRetryAfterDate - DateTime.UtcNow
                    Else
                        Dim wrRetryAfterSeconds As Integer = 120
                        If Integer.TryParse(wrRetryAfter, wrRetryAfterSeconds) Then
                            retryAfter = New TimeSpan(0, 0, wrRetryAfterSeconds)
                        End If
                    End If
                End If

                '503 exponential backoff, get retry-after header
                ResponseCode = MessageTransportResponseCode.ServiceUnavailable
                ResponseStatus = MessageTransportResponseStatus.[Error]

            End If
        End Try
    End Sub


    Public Enum MessageTransportResponseCode
        Ok
        [Error]
        ServiceUnavailable
        InvalidAuthToken
    End Enum

    Public Enum MessageTransportResponseStatus
        Ok
        [Error]
        QuotaExceeded
        DeviceQuotaExceeded
        InvalidRegistration
        NotRegistered
        MessageTooBig
        MissingCollapseKey
    End Enum

End Module

No comments:

Post a Comment