Friday, March 9, 2012

This Post Is Deprecated ...

Hi,

Once upon a time I was developing an application for platforms starting from 2.1 ( API level 7 ) and it happened that I needed the app to receive notifications from the server.

Actually, I achieved this using C2DM directly ( with no external libraries ) by following this tutorial, AND then I  achieved this  once again using Urban Airship's push library for Android.

The main advantage of using C2DM directly is that the documentation is very clear as always and by following the previously mentioned tutorial you can get every thing working in no time.

But, on the other hand, it requires platform 2.2 ( API level 8 ) at least and it takes a little bit more coding effort for both the client and server sides.

After all, I enjoyed it and I think that without using C2DM directly, I wouldn't be able to understand how Urban Airship works.

Why Urban Airship:
  • Allows the devices running platforms lower than 2.2 ( API level 8 ) to receive push notifications.
  • Handles many requests between the device and the server on behalf of the developer (e.g. the registration tying an APID (Android Push ID -  is the Urban Airship ID of a device to which a message can be pushed from the Urban Airship API ) to your application happens automatically ).

  • Broadcasts the messages to all the registered devices ( of course you can do it just by looping on all the registered devices, but eventually Urban Airship still does it for you ).

  • And of course because, it was a recommendation from a friend :)
The only thing that I didn't like about Urban Airship is that the documentation wasn't so clear as the one from Google that made me spend more time trying to figure out what's going on but once I did, it was a very easy task to do again and again.

Steps:
  1. Visit Urban Airship's website. Choose the pricing plan that suits your needs and sign up here.

  2. Sign up for C2DM here to authorize your Google account to become a C2DM sender ( to be able to push notifications ) and later we'll use the same Google account to generate a token for Urban Airship.

  3. Download the library from here.

  4. Create a new folder in your Android project and place the jar file inside it and then add the jar to your project libraries.


  5. Now, we need to get the authorization token by which C2DM authorizes my account ( you’ll give that token to Urban Airship so it can send messages on your behalf ).

    • Create a Java project and then create the following class:

    •  import java.io.BufferedReader;  
       import java.io.IOException;  
       import java.io.InputStreamReader;  
       import java.io.OutputStream;  
       import java.net.HttpURLConnection;  
       import java.net.URL;  
         
       public class AuthenticationUtil {  
            private AuthenticationUtil() {  
                 // Util class cannot get instanziated  
            }  
         
            public static String getToken(String email, String password)  
                      throws IOException {  
                 // Create the post data  
                 // Requires a field with the email and the password  
                 StringBuilder builder = new StringBuilder();  
                 builder.append("Email=").append(email);  
                 builder.append("&Passwd=").append(password);  
                 builder.append("&accountType=GOOGLE");  
                 builder.append("&source=MyLittleExample");  
                 builder.append("&service=ac2dm");  
         
                 // Setup the Http Post  
                 byte[] data = builder.toString().getBytes();  
                 URL url = new URL("https://www.google.com/accounts/ClientLogin");  
                 HttpURLConnection con = (HttpURLConnection) url.openConnection();  
                 con.setUseCaches(false);  
                 con.setDoOutput(true);  
                 con.setRequestMethod("POST");  
                 con.setRequestProperty("Content-Type",  
                           "application/x-www-form-urlencoded");  
                 con.setRequestProperty("Content-Length", Integer.toString(data.length));  
         
                 // Issue the HTTP POST request  
                 OutputStream output = con.getOutputStream();  
                 output.write(data);  
                 output.close();  
         
                 // Read the response  
                 BufferedReader reader = new BufferedReader(new InputStreamReader(  
                           con.getInputStream()));  
                 String line = null;  
                 String auth_key = null;  
                 while ((line = reader.readLine()) != null) {  
                      if (line.startsWith("Auth=")) {  
                           auth_key = line.substring(5);  
                      }  
                 }  
         
                 // Finally get the authentication token  
                 // To something useful with it  
                 return auth_key;  
            }  
       }  
      

    • Now, in the Java project, create the following class which will get the authentication token:

    •  import java.io.IOException;  
         
       import de.vogella.java.c2dm.server.secret.SecureStorage;  
       import de.vogella.java.c2dm.server.util.AuthenticationUtil;  
         
       public class GetAuthenticationToken {  
         
            public static void main(String[] args) throws IOException {  
                 String token = AuthenticationUtil.getToken(YOUR E-MAIL,  
                           YOUR PASSWORD);  
                 System.out.println(token);  
            }  
       }  
      

    • Run GetAuthenticationToken and get the token.

    • Hint: the previous snippets are from here.

  6. Back to your Urban Airship's account, from the SELECT AN APPLICATION tab, create a new app.


  7. Set your app up:

    • Enter the application name.

    • Set the Application mode to (Development), and later you can change it to (Production) after you finish testing the app.

    • check the check box in front of (Push Notifications Support), you can check the others (Rich Push Enabled and In-App Purchase and Subscriptions) too if you need and depending on the pricing plan that you've chosen.

    • Then you have to enter your project's package.

    • And - at last - enter the C2DM authorization token ( yes, the one that we used the previous two snippets to get ).

    • Press (Create your application) button.


  8. That's all the configuration thing, now, lets move to the app.

  9. Create a file inside the assets folder named airshipconfig.properties or you can copy it from the push example that you previously downloaded and then modify the values inside it.

  10.  developmentAppKey = Your Development App Key  
     developmentAppSecret = Your Development Secret  
     #productionAppKey = Your Production App Key  
     #productionAppSecret = Your Production Secret  
       
     #transport is "c2dm", "helium" or "hybrid".  
     #note: the helium and hybrid transports are premium features.  
     #for complete pricing information, see http://urbanairship.com/pricing/  
       
     transport = c2dm  
       
     c2dmSender = the email that you registered to C2DM with  
     inProduction = false  
    

  11. you can get your development key and secret from your app's page on Urban Airship.


  12. Create a class that extends BroadcastReceiver and lets call it IntentReceiver, we'll use this receiver to receive the messages and to handle it as follows:

  13.  public class IntentReceiver extends BroadcastReceiver {   
         
       private String msg;   
          
        @Override   
        public void onReceive(Context context, Intent intent) {   
              
           String action = intent.getAction();   
         
           // if a notification is received ...   
           if (action.equals(PushManager.ACTION_PUSH_RECEIVED)) {   
         
             // Do whatever you want ....   
         
           // if the notification is opened/clicked ...   
           } else if (action.equals(PushManager.ACTION_NOTIFICATION_OPENED)) {   
         
             // here you can get the extras from the intent.   
             // and then you can use it as you wish.   
             msg = intent.getStringExtra(PushManager.EXTRA_ALERT);   
                
             // for example, you can start an activity and send the msg as an extra.   
             Intent launch = new Intent(Intent.ACTION_MAIN);   
             launch.setClass(UAirship.shared().getApplicationContext(), MyActivity.class);   
             launch.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);   
             launch.putExtra("notification", msg);   
         
             UAirship.shared().getApplicationContext().startActivity(launch);   
         
             // save the APID in a shared preferences ...   
             //     it'll be sent to the server ...   
           } else if (action.equals(PushManager.ACTION_REGISTRATION_FINISHED)) {   
              
                         // to log the APID ...  
                         Log.i(logTag, "Registration complete. APID:"  
                              + intent.getStringExtra(PushManager.EXTRA_APID)  
                              + ". Valid: "  
                              + intent.getBooleanExtra(  
                                        PushManager.EXTRA_REGISTRATION_VALID, false));  
                       
             // if registration is successful ...   
             if(intent.getBooleanExtra(PushManager.EXTRA_REGISTRATION_VALID, false)){   
                
                // Do whatever you want ....   
             }   
             else{   
                   
                // register again ...   
             }   
           }   
        }   
      }   
    

  14. Create a class that extends Application and override its onCreate() method as follows:

  15.    
     public class MyApplication extends Application {    
          
       @Override    
       public void onCreate() {    
         
               // Take off with options defined in airshipconfig.properties...  
               UAirship.takeOff(this);    
                 
               // The push service is DISABLED BY DEFAULT...    
               PushManager.enablePush();    
                 
               // to make our receiver able to receive the broadcast intents...  
               PushManager.shared().setIntentReceiver(IntentReceiver.class);    
       }    
      }    
    

  16. One more thing to go, it's the manifest.xml:

  17.  <?xml version="1.0" encoding="utf-8"?>  
     <manifest xmlns:android="http://schemas.android.com/apk/res/android"  
        package="your.project.package"  
        android:versionCode="1"  
        android:versionName="1.0">  
       <uses-sdk android:minSdkVersion="7" />  
       
       <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />  
       <uses-permission android:name="android.permission.INTERNET" />  
       <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />  
       <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />  
          <uses-permission android:name="android.permission.READ_PHONE_STATE" />  
          <uses-permission android:name="android.permission.VIBRATE" />  
          <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />  
             
          <!-- REQUIRED for C2DM -->  
          <!-- Only this application can receive the messages and registration result -->  
          <permission android:name="your.project.package.permission.C2D_MESSAGE"  
               android:protectionLevel="signature" />  
       
          <uses-permission android:name="your.project.package.permission.C2D_MESSAGE" />  
       
          <!-- This app has permission to register and receive message -->  
          <uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />  
       
       <application android:label="@string/app_name"   
         android:icon="@drawable/launcher"  
               <!-- The Next line is very important -->  
         android:name="your.project.package.MyApplication" >  
           
         <activity android:name="your.project.package.MyActivity"  
                    android:label="@string/app_name" >  
              
           <intent-filter>  
             <action android:name="android.intent.action.MAIN" />  
             <category android:name="android.intent.category.LAUNCHER" />  
           </intent-filter>  
           
         </activity>  
           
         <!-- Urban Airshp -->  
           
              <!-- REQUIRED -->  
              <receiver android:name="com.urbanairship.CoreReceiver" />  
            
              <!-- REQUIRED for C2DM and Hybrid -->  
              <receiver android:name="com.urbanairship.push.c2dm.C2DMPushReceiver"  
                android:permission="com.google.android.c2dm.permission.SEND" >  
            
                <!-- Receive the actual message -->  
                <intent-filter >  
                  <action android:name="com.google.android.c2dm.intent.RECEIVE" />  
            
                  <category android:name="your.project.package" />  
                </intent-filter>  
                <!-- Receive the registration id -->  
                <intent-filter >  
                  <action android:name="com.google.android.c2dm.intent.REGISTRATION" />  
            
                  <category android:name="your.project.package" />  
                </intent-filter>  
              </receiver>  
            
              <service android:name="com.urbanairship.push.PushService" />  
                      
              <!-- OPTIONAL, if you want to receive push, push opened and registration completed intents   
                    Add the receiver that you've created -->  
              <receiver android:name="your.project.package.IntentReceiver" />  
       
         <!-- Urban Airshp -->  
           
       </application>  
       
     </manifest>  
    

  18. Congratulations, your app is ready to receive notifications. to test it, turn on the WiFi or your 3G and run the app, then get the APID from the Logcat.

  19. Open your app's profile on Urban Airship and choose push from the menu on the left side and then choose Test Push Notifications and of course choose Android.


  20. Once you fill in the fields and press Send it the notification will be sent to your device.

  21. You can install your app on many devices and send a broadcast message just by choosing Send Broadcast  from the menu on the left side. In this case you don't need to enter any specific APID because, Urban Airship API will send the notification to all the registered devices, and as I've mentioned earlier  tying an APID to your application happens automatically.
Notes:
  1. You can stop receiving notification by calling disablePush() as follows:

  2.  PushManager.disablePush();  
    

  3. When you test your app and decide to release it, create another profile for you app with Application Mode set to Production.

  4. It's highly recommended to read the Urban Airship's documentation as well.
That's it, don't hesitate to comment, to share your knowledge and to correct me.

5 comments:

  1. thanks for this great tutorial......

    ReplyDelete
  2. I really like your this step by step tutorial. Thanks for sharing. desktop notification software

    ReplyDelete
  3. Thanks a lot! You made a new blog entry to answer my question; I really appreciate your time and effort.Best Android Training in Velachery | android development course fees in chennai

    ReplyDelete
  4. I like this article. I'm read this article Android Notification using an urban C2DM method we have to update some coding for this article I'm using that's Android notifications C2DM code working now my application. Thank for the wonderful information.
    Selenium Training in Chennai | Best Selenium Training in Chennai | Hadoop Training with placement in Chennai | Best Android Training in Chennai

    ReplyDelete
  5. This comment has been removed by the author.

    ReplyDelete