Thursday 29 March 2012

C2dm Android Push Notification


Looking at all possible solution for C2dm Android Push Notification on various communities ,i would like to contribute best approach which i have been successfully able to implement .
1. I have used Titanium 1.7.5 and 1.8.0.1 earlier ,which don't work and give various errors,which are due to deprecated methods and absence of libraries used in C2dm,i would suggest either to add those libraries in you project by creating a lib folder ,else directly use 1.8.2(best SDK version) and create an empty lib folder.So execute command below in ur MAC Terminal,an alias will be created for ur SDK. alias titanium="Library/Application\ Support/Titanium/mobilesdk/osx/1.8.2/titanium.py". You can check if it is created by using following Command, cd Titanium This will give you Appcelerator Titanium Copyright (c) 2010-2011 by Appcelerator, Inc.
commands:
create - create a project run - run an existing project emulator - start the emulator (android) docgen - generate html docs for a module (android) fastdev - management for the Android fastdev server help - get help
2.Now create a module from your project,by using common below, (Your_root)$ titanium create --platform=android --type=module --name=c2dmmod --id=com.Yourcompany.c2dmmod --android=Documents/android-sdk-mac_x86.
3.Once your module is created in your root directory,u need to change build.properties based on path your machine uses,my machine uses following
titanium.platform=/Users/Yourpath/Library/Application Support/Titanium/mobilesdk/osx/1.8.2/android android.platform=/Users/Yourpath/Documents/android-sdk-mac_x86/platforms/android-8 google.apis=/Users/Yourpath/Documents/android-sdk-mac_x86/add-ons/addon-google_apis-google_inc_-8 android.ndk=/Users/Yourpath/Documents/android-ndk-r7b
Make sure to have ndk,addon-google_apis-google_inc_-8 on ur machine and give respective paths.
4.Download https://github.com/Kuraturpa/titanium-c2dm ,we just need src folder from here replace Source folder of your module with src folder of newly downloaded project from link above.
5.Now we are set with Module which has your build properties(as per your machine),src replaced,wince they have find law and google code which help us execute c2dm.
6.We have to build ant for newly created module,add an empty folder called lib in your module if it doesn't exists.
7.Now before running ant command get into your module directory ,in our case we have created a c2dm module called c2dmmod, so my terminal would look something like (Your_root)-Mac-mini-6:c2dmmod Yourroot$ ant
just get into module's directory and run ant.
8.Once you run ant if every thing is perfect you will get a message saying Build Successful message .Now you will find a new folder called dist(Distribution) has been created in to your module project,with a jar and a zip file of your project(This zip is what we are going to use in our Titanium Project).
9.Now get back into your project where you want to use C2dm and do following
a. Add zip of your Module project to this Titanium Project at Root level,at the same level as tiapp.xml. In our case for module create zip file will be com.findlaw.c2dmmod-android-0.1.zip.
b. In your tiapp.xml add,following
<android xmlns:android="http://schemas.android.com/apk/res/android">
        <manifest>
            <permission
                android:name="Your_Appid.permission.C2D_MESSAGE" android:protectionLevel="signature"/>
            <uses-permission android:name="com.yourcompany.newbuildc2dm.permission.C2D_MESSAGE"/>
            <uses-permission android:name="com.google.android.c2dm.permission.RECEIVE"/>
            <uses-permission android:name="android.permission.WAKE_LOCK"/>
            <uses-permission android:name="android.permission.VIBRATE"/>
            <uses-permission android:name="android.permission.INTERNET"/>
            <uses-permission android:name="android.permission.GET_ACCOUNTS"/>
            <uses-permission android:name="android.permission.USE_CREDENTIALS"/>
            <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
            <application>
                <service android:name="com.findlaw.c2dm.C2DMReceiver"/>
                <receiver
                    android:name="com.google.android.c2dm.C2DMBroadcastReceiver" android:permission="com.google.android.c2dm.permission.SEND">
                    <intent-filter>
                        <action android:name="com.google.android.c2dm.intent.RECEIVE"/>
                        <category android:name="Your_Appid"/>
                    </intent-filter>
                    <intent-filter>
                        <action android:name="android.intent.action.BOOT_COMPLETED"/>
                        <category android:name="android.intent.category.HOME"/>
                    </intent-filter>
                    <intent-filter>
                        <action android:name="com.google.android.c2dm.intent.REGISTRATION"/>
                        <category android:name="Your_Appid"/>
                    </intent-filter>
                </receiver>
            </application>
        </manifest>
    </android>
    <modules>
        <module platform="android" version="0.1">Your Module id</module>
    </modules>


com.findlaw.c2dmmod in module being your module name.
c. Register for c2dm at http://code.google.com/android/c2dm/signup.html.
D. From downloaded example of https://github.com/Kuraturpa/titanium-c2dm,you can use same app.js file in your Titanium project,replace var senderId = 'Your registered Gmail id'; var c2dm = require('Your module name);
e. Change Class name and package name based on your project settings className: 'Your_Appid.YourActivity_name' (Your Activity name can be found at YourProject/Build/Android/Gen/Your module/Activity.java(Activity name would be based on your project id,just pick name of file with name as activity,don't copy .java just name is enough). packageName: 'Your App_id'(Can be seem in tiapp.xml).
10.Once you run this project as per steps above you will receive a Device id from Google,which we will use in our Server Call.This need to be passed to server 11.Once your done this ,we need to execute php service from Server end,following is code which you will need to execute,

<?php /* * * $username - your gmail email address you white listed with the c2dm service * $password - password for above gmail account. */
function googleAuthenticate($username, $password, $source="Company-AppName-Version", $service="ac2dm") {
@session_start(); 

if( isset($_SESSION['google_auth_id']) &amp;&amp; $_SESSION['google_auth_id'] != null)     
    return $_SESSION['google_auth_id'];  



// get an authorization token 

$ch = curl_init(); 

if(!$ch){ 

    return ''; 
} 




curl_setopt($ch, CURLOPT_URL, &quot;https://www.google.com/accounts/ClientLogin&quot;); 

$post_fields = &quot;accountType=&quot; . urlencode('HOSTED_OR_GOOGLE') 
    . &quot;&amp;Email=&quot; . urlencode($username) 
    . &quot;&amp;Passwd=&quot; . urlencode($password) 
    . &quot;&amp;source=&quot; . urlencode($source) 
    . &quot;&amp;service=&quot; . urlencode($service); 


curl_setopt($ch, CURLOPT_HEADER, true); 
curl_setopt($ch, CURLOPT_POST, true); 
curl_setopt($ch, CURLOPT_POSTFIELDS, $post_fields); 
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); 
curl_setopt($ch, CURLOPT_FRESH_CONNECT, true);     
curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_ANY); 
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); 

// for debugging the request 
//curl_setopt($ch, CURLINFO_HEADER_OUT, true); // for debugging the request 

$response = curl_exec($ch); 


//echo $response;   


//var_dump(curl_getinfo($ch)); //for debugging the request 
//var_dump($response); 

curl_close($ch); 

if (strpos($response, '200 OK') === false) { 

    echo &quot;200 Not Ok&quot;;
    return ''; 
} 

// find the auth code 
preg_match(&quot;/(Auth=)([\w|-]+)/&quot;, $response, $matches); 

if (!$matches[2]) { 
    echo &quot;No Match&quot;;
    return ''; 
} 

$_SESSION['google_auth_id'] = $matches[2]; 

 return $matches[2]; 

 //return true;
}
/* * * $authCode - the authcode returned when you ran the googleAuthenticate function * $deviceRegistrationId - registrationID returned by the device receiving the message * $$msgType - can be anything i.e. 'chat message' * $messageText - text to be sent */
function sendMessageToPhone($authCode, $deviceRegistrationId, $msgType, $messageText) {
    $headers = array('Authorization: GoogleLogin auth=' . $authCode); 
    $data = array( 
        'registration_id' =&gt; $deviceRegistrationId, 
        'collapse_key' =&gt; $msgType, 
        'data.message' =&gt; $messageText //TODO Add more params with just simple data instead            
    ); 

    $ch = curl_init(); 

    curl_setopt($ch, CURLOPT_URL, &quot;https://android.apis.google.com/c2dm/send&quot;); 

    if ($headers) 
        curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); 
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); 
    curl_setopt($ch, CURLOPT_POST, true); 
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); 
    curl_setopt($ch, CURLOPT_POSTFIELDS, $data); 


    $response = curl_exec($ch); 

    curl_close($ch); 

    echo $response; 

    //var_dump($response);
}
$msgType = 'chat message111'; $message = 'Friend Request111!';
$regID='Your Device regestration ID';
$auth = googleAuthenticate("Your Registered Email Id","Yourmessage","Your Titanium project's App ID"); sendMessageToPhone($auth, $regID, $msgType, $message);
  ?>

12.Once you run this from server you will get Notification on your device ,which while have message as sent,this will redirect you to your app when clicked.
13.I have checked all possible solutions,and finally been able to get Notifications following steps above. I would suggest to use 1.8.2 SDK,1.8.0.1 has many bugs hence i would't advice you that.
14.Thanks all communities which have inspired me to write this and given me a strong urge to share what we receive.