Android Tutorial Android push notification (C2DM) framework and tutorial

Discussion in 'Tutorials & Examples' started by Erel, Jul 31, 2011.

  1. Erel

    Erel Administrator Staff Member Licensed User

    Google has stopped providing the C2DM service. A newer service (GCM) is now available: http://www.basic4ppc.com/forum/basi...push-notification-gcm-framework-tutorial.html

    [/B]Google provides a service named Android Cloud to Device Messaging Framework (C2DM) which allows developers to send data to their applications running on Android devices. Unlike most solutions which involve polling some server, this service is a "push" service (similar to SMS messages).

    Developers should implement three components in order to use this service.
    Client code - The client code which is responsible for registering the specific device and application with Google service and is responsible for handling new messages that arrive.

    Web server - When the device registers with Google service it receives a registration id that allows you, the account holder, to send messages to your application running on the user device. The device needs to send this id to a web server that you can access.

    Messages sending tool - This is a command line tool that is responsible for fetching the user id from the web server and then sending the message to the device. This is done by sending a request to Google servers.

    The attached framework includes these components.
    At this point it is recommended to read the formal documentation about C2DM to better understand the flow: Android Cloud to Device Messaging Framework - Google Projects for Android

    Configuration and installation instructions

    First you should sign up with a Google account in the above link.
    Once your account is activated (from my experience it took several hours) you can start sending messages.
    During signup you will need to enter account mail address (sender id) and the application package name.

    Client code
    In order to get it working, we will modify the device example application. Later you can integrate this code in your own application.
    Two variables should be set in the Main activity, under Sub Process_Globals to match the package name and sender id you previously registered.
    The application package name should also be set to the same package name (Project - Package Name).
    Code:
    'both these fields should be set to match your application package and SenderId.    
        Package = ""
        SenderId = 
    ""
    You should now edit AndroidManifest.xml which is located under Objects folder and replace all occurrences of anywheresoftware.b4a.samples.push with your package name.
    With the new manifest editor you should instead add the code posted here (and make sure that "do not overwrite manifest file" is NOT selected): http://www.basic4ppc.com/forum/basi...tion-c2dm-framework-tutorial-5.html#post80463

    Sending messages desktop tool
    Open config.txt and update the two fields:
    Code:
    sender_mail_id=
    sender_mail_password=
    You should enter the same mail address and the password for this account.

    You are now ready to test it!
    Run the B4A project, enter a name in the text field and press on the Register button. You should see a toast message saying Registration successful. Messages are also printed to the logs. It can take several seconds.
    This means two things. Your device has registered with Google servers and also that the registration id was sent to the developer web service (currently configured with the service hosted here) with the specified name.
    The name will be used to reference the device. Note that each device must have a unique name.

    Now go to the command line tool folder and open a command window (this can be done by pressing Shift together with right clicking on the folder icon).
    The sending messages tool is a java app. For your convenience a batch file is included to run this tool. Note that this app can run from Linux or Mac as well.

    The sending tool expects several arguments:
    Code:
    send <device name> <message text> [<collapse_key> [<delay while sleeping>]]
    Device name is the name that you previously chose in the client app.
    Message text is the text that will be sent. Remember to wrap it with quotes if it contains spaces.
    The last two arguments are optional. See the formal documentation for more information about them.
    Instead of 'send' command, you can use 'SendTextFile'. It is the same as send, however the second argument is the path to a text file that will be sent.
    Another command is 'GetAll'. It will display all the registered device names (this command is not available in the web service hosted here.

    The command line tool can be automated. It returns an exit code of 0 if the operation succeeded and 1 otherwise.

    Try sending a message to your device. It should arrive to the device almost immediately.

    [​IMG]

    Handling of messages is done in Sub MessageArrived in PushService module.

    Web server configuration
    The device application and the sending messages tool are preconfigured to use the web server hosted here. This server should only be used during development.
    The web server is built from a PHP script which communicates with a MySQL database.
    In order to host it yourself, you should upload it to a server that supports PHP and create a database and user that is able to access the database.
    The script creates the table on the first run.
    You will need to edit the PHP script and set the database name / user / password.
    There are additional two passwords in this script: devicepassword and serverpassword. The device password should match the DeviceBoardPassword field in the device application and the serverpassword should match the server_password field in the sending messages tool configuration. Both these passwords should only contain letters and numbers.
    You should also change the board url value in the desktop tool and device app to match the location of your hosted php file.

    C2DM limitations
    - Only Android 2.2 and above are supported.
    - Message length should not exceed 1024 bytes. This means that if you need to send more data then the push message should only be used to notify the device that it should connect to some server and grab the data.

    Tips
    - If the push notification is a critical component in your application then you should set the android:minSdkVersion field in the manifest file to 8 so older devices will not be able to download the application.
     

    Attached Files:

  2. hackhack

    hackhack Active Member Licensed User

    Although It may not be related to this, I'd love to be able to understand how it can be a "push" - how would an Android device magically know there is something? Surely it must check at intervals to see if there is something.
     
  3. Erel

    Erel Administrator Staff Member Licensed User

  4. petri2000

    petri2000 Member Licensed User

    C2DM sign up delay.

    C2DM, this seems exactly what we need for our app. I have signed up about 8 days ago with 1 account and 3 days ago with another one to get access to the services, I guess it was a google automated email that said "you will have access within the next day or so". Do, anybody know how to speed up the process? Are there any specific criterias that I would met for getting an account? I know it has nothing to do with B4A business, but I am looking for clues if there is someone with some info to get an account. As this is something we would really need! I have been trying to find answers else where... But nothing, this is my last resort.....

    Cheers,
    Petri

    PS. Yes, I am looking into xtify as well but would prefeer google DS.
     
  5. Erel

    Erel Administrator Staff Member Licensed User

    When I registered it took about 2 hours for my account to be active. I don't have a clue why it takes longer now.
     
  6. myriaddev

    myriaddev Active Member Licensed User

    SUCCESS: xxxxxxxx

    WOW! It worked (my first server app)! What does "success: xxxxx"
    mean ? That the message arrived at the Device ? That the message
    was sent only ? That the message was read ? What does the number
    mean ?
    Thank you Erel,
    Jerry
     
  7. Erel

    Erel Administrator Staff Member Licensed User

  8. talalilo

    talalilo New Member

    code sample

    @myriaddev
    Kindly give me your example to test with, as every time i got 401 unauthorized error
     
  9. Erel

    Erel Administrator Staff Member Licensed User

    For some reason you appear as an unlicensed user in the forum. Please contact support@basic4ppc.com in order to fix it.
     
  10. jnbarban

    jnbarban Member Licensed User

    Hello,

    When i tried to send a message, i got this result :

    Code:
    java.lang.RuntimeException: java.io.IOException: Server returned HTTP response
     code: 
    401 for URL: https://android.apis.google.com/c2dm/send
            at anywheresoftware.b4a.c2dm.C2DM.sendMessageTo(C2DM.java:
    66)
            at anywheresoftware.b4a.c2dm.C2DM.sendMessageTo(C2DM.java:
    63)
            at anywheresoftware.b4a.c2dm.C2DM.main(C2DM.java:
    228)
    this is a ClientLogin Auth token problem but i don't understand what i must do.

    Do you know ?
     
  11. Erel

    Erel Administrator Staff Member Licensed User

    Make sure that you entered the correct values in config.txt. Were you able to register the device successfully?
    There should be a file named oauth.txt in the folder of the desktop tool. Delete it and see if it is recreated.
     
  12. mitobobo

    mitobobo Member Licensed User

    Hello,

    I'm sorry in advance for my English:sign0013:

    I modified the Package = "" and SenderId = "" in the client code, and replaced all the occurrences of anywheresoftware.b4a.samples.push with my package name(com.sl.comando) in the Manifest. Then I uploaded the app to my device(HTC Desire), but it crashs while opening: "Unexpected Push Example application termination (process com.sl.comando). Try again". Any idea why I get that?

    Thank you very much in advance for your help.
     
  13. Erel

    Erel Administrator Staff Member Licensed User

    The first step is to check the unfiltered logs (Logs tab in the right side of the IDE).
     
  14. mitobobo

    mitobobo Member Licensed User

    Oh, I get this:

    Code:
    Starting: Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10000000 pkg=com.sl.comando cmp=com.sl.comando/.main } from pid 12842
    Start proc com.sl.comando for activity com.sl.comando/.main: pid=12958 uid=10072 gids={3003}
    Shutting down VM
    threadid=1: thread exiting with uncaught exception (group=0x40240560)
    FATAL EXCEPTION: main
    java.lang.RuntimeException: Unable to instantiate activity ComponentInfo{com.sl.comando/com.sl.comando.main}: java.lang.ClassNotFoundException: com.sl.comando.main in loader dalvik.system.PathClassLoader[/data/app/com.sl.comando-1.apk]
       at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1680)
       at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1784)
       at android.app.ActivityThread.access$1500(ActivityThread.java:123)
       at android.app.ActivityThread$H.handleMessage(ActivityThread.java:939)
       at android.os.Handler.dispatchMessage(Handler.java:99)
       at android.os.Looper.loop(Looper.java:130)
       at android.app.ActivityThread.main(ActivityThread.java:3835)
       at java.lang.reflect.Method.invokeNative(Native Method)
       at java.lang.reflect.Method.invoke(Method.java:507)
       at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:847)
       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:605)
       at dalvik.system.NativeStart.main(Native Method)
    Caused by: java.lang.ClassNotFoundException: com.sl.comando.main in loader dalvik.system.PathClassLoader[/data/app/com.sl.comando-1.apk]
       at dalvik.system.PathClassLoader.findClass(PathClassLoader.java:240)
       at java.lang.ClassLoader.loadClass(ClassLoader.java:551)
       at java.lang.ClassLoader.loadClass(ClassLoader.java:511)
       at android.app.Instrumentation.newActivity(Instrumentation.java:1021)
       at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1672)
       ... 11 more
      Force finishing activity com.sl.comando/.main
    Activity pause timeout for HistoryRecord{40c7a158 com.sl.comando/.main}
    ** Activity (main) Resume **
    Thank you very much again
     
  15. Erel

    Erel Administrator Staff Member Licensed User

    Your manifest file is not configured properly. Can you post its content?
     
  16. mitobobo

    mitobobo Member Licensed User

    Code:
    <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android=
    "http://schemas.android.com/apk/res/android"
          package=
    "com.sl.comando"
          android:versionCode=
    "1"
          android:versionName=
    ""
         android:installLocation=
    "internalOnly">
          <uses-sdk android:minSdkVersion=
    "4" />
          <supports-screens
              android:largeScreens=
    "true"
              android:normalScreens=
    "true"
              android:smallScreens=
    "true"
              android:anyDensity=
    "true"/>
        <
    application android:icon="@drawable/icon" android:label="Push Example">
           
            <
    activity android:windowSoftInputMode="stateHidden" android:launchMode="singleTop" android:name=".main"
                      android:
    label="Push Example" android:screenOrientation="unspecified">
                <
    intent-filter>
                    <action android:name=
    "android.intent.action.MAIN" />
                    <category android:name=
    "android.intent.category.LAUNCHER" />
                </
    intent-filter>
            </
    activity>
            <
    service android:name="pushservice"></service>
          <receiver android:name=
    "pushservice$pushservice_BR" android:permission="com.google.android.c2dm.permission.SEND">
           <
    intent-filter>
                  <action android:name=
    "com.google.android.c2dm.intent.RECEIVE" />
                  <category android:name=
    "com.sl.comando" />
              </
    intent-filter>
              <!-- Receive the registration 
    id -->
              <
    intent-filter>
                  <action android:name=
    "com.google.android.c2dm.intent.REGISTRATION" />
                  <category android:name=
    "com.sl.comando" />
              </
    intent-filter>

          </receiver>

        </
    application>
       <uses-permission android:name=
    "android.permission.INTERNET"/>
       <permission android:name=
    "com.sl.comando.permission.C2D_MESSAGE" android:protectionLevel="signature" />
       <uses-permission android:name=
    "com.sl.comando.permission.C2D_MESSAGE" />
       <uses-permission android:name=
    "com.google.android.c2dm.permission.RECEIVE" />


    </manifest>
    Thank you very much.
     
  17. Erel

    Erel Administrator Staff Member Licensed User

    Did you also change the package name under Project - Package Name?
     
  18. mitobobo

    mitobobo Member Licensed User

    Oh, I'm very sorry, I didn't. It works now:sign0060:

    Thank you so much again:)
     
  19. pinoy_ako

    pinoy_ako Member Licensed User

    why when i compile the device sample, i got this error:
     
  20. Erel

    Erel Administrator Staff Member Licensed User

    Remove line 38:
    Code:
    Dim r As Reflector
    It was left by mistake.
     
Loading...