Android Tutorial Android push notification (C2DM) framework and tutorial

bvdijk

Member
Licensed User
Longtime User
Registratio not taking place

1) Google Account Set Up >24 hours ago

2) Modified 'Device Example'
- Package = "my.package"
- SenderId = "[email protected]"

3) Changed manifest (5 occurences, did a CTRL+H replace for 'anywheresoftware.b4a.samples.push' in 'my.package')

4) Changed config.txt for desktop tool
- [email protected]
- sender_mail_password=mypassword

5) Compile errors:

- (Main, line 38) Dim r as Reflector (in the previous post this was already mentioned and it could be commented out)

More errors about 'Reflector', so I downloaded 'Reflection 1.9 library (copied the jar + xml to the add. libs dir)


6) Saved changes, restarted B4A and Enabled reference to Reflection lib

7) Unchecked 'Do Not Overwrite Manifest File' (It was complaining about this during compilation)

8) Now it's running

- So I entered a random name for my device and pressed Register

Nothing happens...

What I'm a missing, doing wrong?

Thank for your help!
 

bvdijk

Member
Licensed User
Longtime User
You should leave it checked. If it is not checked then AndroidManifest.xml is recreated by the compiler.
You will need to redo the changes and keep it checked.

Thanks for your quick response. I deleted everything, unzipped it all again and made the same changes. Seems I've got a path issue, since the compiler stops with:

Compiling code. 0.12
Using existing AndroidManifest.xml.
(Project - Do Not Overwrite Manifest option is checked)
AndroidManifest-Example.xml file will be created instead.
Generating R file. 0.20
Compiling generated Java code. Error
javac 1.6.0_26
javac: file not found: gen\anywheresoftware\b4a\samples\push\R.java
Usage: javac <options> <source files>
use -help for a list of possible options
 

Erel

B4X founder
Staff member
Licensed User
Longtime User
You didn't change the Package name (under Project):
SS-2011-12-14_16.44.53.png
 

bvdijk

Member
Licensed User
Longtime User
You didn't change the Package name (under Project):
SS-2011-12-14_16.44.53.png

Just found that my self too, browsing through some former posts... :BangHead:

Just compiled it, let me see...

'Registration completed succesfully'

:sign0142:
 
Last edited:

bvdijk

Member
Licensed User
Longtime User
Important, disable 2-step authentication!

One more thing, I got the following error due to 2-step authentication. Disabling this made everything work!

java -cp b4a_c2dm.jar anywheresoftware.
b4a.c2dm.C2DM send mydevice "testmessage"
java.lang.RuntimeException: error getting authentication code: java.io.IOExcepti
on: Server returned HTTP response code: 403 for URL: https://www.google.com/acco
unts/ClientLogin?service=ac2dm&[email protected]&Passwd=mypassword
at anywheresoftware.b4a.c2dm.C2DM.findOAuth(C2DM.java:133)
at anywheresoftware.b4a.c2dm.C2DM.sendMessageTo(C2DM.java:52)
at anywheresoftware.b4a.c2dm.C2DM.main(C2DM.java:228)
 

myriaddev

Active Member
Licensed User
Longtime User
Need to automate Desktop "sending"

Hi again. Have everything working on my website's server,
but now need to automate the sending msgs/commands to
different Devices. Can you share java code, and or show
how to do it from B4a, or some other means. Also show
GetDevices command using PHP. I would be happy to
buy also b4ppc...

Great product!
Jerry
 

salmander

Active Member
Licensed User
Longtime User
Hello All,
I am successful in running the demo app..and I am getting the toastMessages from the desktop to the device. How can I use this with my existing project? Is there any library like feature I can use?
 

salmander

Active Member
Licensed User
Longtime User
Ok it was working fine until it was on b4a server. I moved the script to my host, changing the database username, dbpassword and database name. In the app, I changed the boardURL to my script address. When I register the app, I get registration successful toast but I am getting this message on the command line. "error getting authentication code"

anyone help please?

Ok its working now. :)
 
Last edited:

salmander

Active Member
Licensed User
Longtime User
I have been following this tutorial for two days now. And I am kind of struggling to understand how I can implement C2DM functionality into my existing project. Can anyone help me please with this? can this not be made into a library like feature for B4A?

Thank you in advance.
 

salmander

Active Member
Licensed User
Longtime User
Not sure which answer are you looking for. Which problem are you encountering?
Hi Erel, thanks for the reply. I want to implement C2DM functionality into my Project. So I have created a new service module in my project and copy pasted the code from this tutorial's service module into my service module. Now, what do I do in my manifest file?
 

salmander

Active Member
Licensed User
Longtime User
As mentioned in the first post:

You should then choose Project - Do not overwrite manifest file.
this is my projects manifest file. I have changed the manifest file and have ticked, Do not overwrite manifest file.
B4X:
<?xml version="1.0" encoding="utf-8"?>
<manifest
   xmlns:android="http://schemas.android.com/apk/res/android"
   package="com.home.test.push"
   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"/>
   <uses-permission android:name="android.permission.READ_PHONE_STATE"/>
   <uses-permission android:name="android.permission.INTERNET"/>
   <uses-permission android:name="android.permission.VIBRATE"/>
    <permission android:name="com.home.test.push.permission.C2D_MESSAGE" android:protectionLevel="signature" />
   <uses-permission android:name="com.home.test.push.permission.C2D_MESSAGE" />
   <uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
   <application
      android:icon="@drawable/icon"
      android:label="PushTest">
      <activity
         android:windowSoftInputMode="stateHidden"
         android:launchMode="singleTop"
         android:name=".main"
         android:label="PushTest"
         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=".push">
      </service>
      <receiver android:name=".push$push_BR" android:permission="com.google.android.c2dm.permission.SEND">
       <intent-filter>
              <action android:name="com.google.android.c2dm.intent.RECEIVE" />
              <category android:name="com.home.test.push" />
          </intent-filter>
          <!-- Receive the registration id -->
          <intent-filter>
              <action android:name="com.google.android.c2dm.intent.REGISTRATION" />
              <category android:name="com.home.test.push" />
          </intent-filter>
      </receiver>
   </application>
</manifest>
 
Last edited:

salmander

Active Member
Licensed User
Longtime User
this is my projects manifest file. I have changed the manifest file and have ticked, Do not overwrite manifest file.
B4X:
<?xml version="1.0" encoding="utf-8"?>
<manifest
   xmlns:android="http://schemas.android.com/apk/res/android"
   package="com.home.test.push"
   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"/>
   <uses-permission android:name="android.permission.READ_PHONE_STATE"/>
   <uses-permission android:name="android.permission.INTERNET"/>
   <uses-permission android:name="android.permission.VIBRATE"/>
    <permission android:name="com.home.test.push.permission.C2D_MESSAGE" android:protectionLevel="signature" />
   <uses-permission android:name="com.home.test.push.permission.C2D_MESSAGE" />
   <uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
   <application
      android:icon="@drawable/icon"
      android:label="PushTest">
      <activity
         android:windowSoftInputMode="stateHidden"
         android:launchMode="singleTop"
         android:name=".main"
         android:label="PushTest"
         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=".push">
      </service>
      <receiver android:name=".push$push_BR" android:permission="com.google.android.c2dm.permission.SEND">
       <intent-filter>
              <action android:name="com.google.android.c2dm.intent.RECEIVE" />
              <category android:name="com.home.test.push" />
          </intent-filter>
          <!-- Receive the registration id -->
          <intent-filter>
              <action android:name="com.google.android.c2dm.intent.REGISTRATION" />
              <category android:name="com.home.test.push" />
          </intent-filter>
      </receiver>
   </application>
</manifest>

This is my Main Activity
B4X:
'Activity module
Sub Process_Globals
   'These global variables will be declared once when the application starts.
   'These variables can be accessed from all modules.
   
   Dim Package, DeviceBoardPassword, BoardUrl, SenderId, DeviceName As String
   DeviceBoardPassword = "abcd"
   BoardUrl = "http://ssahmed.co.uk/c2dm/c2dm_board.php"

   
   'both these fields should be set to match your application package and SenderId.   
   Package = "com.home.test.push"
   SenderId = "[email protected]"
   Dim reg As String
   

End Sub

Sub Globals
   'These global variables will be redeclared each time the activity is created.
   'These variables can only be accessed from this module.
   Dim p As PhoneId

   Dim ListView1 As ListView
   Dim Label1 As Label
End Sub

Sub Activity_Create(FirstTime As Boolean)
   Activity.LoadLayout("Main")
   reg = p.GetDeviceId
   Log("The device ID is: " & reg)
   'ToastMessageShow("Starting Service", False)
   Register(reg)
End Sub

Sub Activity_Resume

End Sub

Sub Activity_Pause (UserClosed As Boolean)

End Sub


Sub Register(Name As String)
   Dim i As Intent
   i.Initialize("", "")
   i.SetComponent(Package & "/.push")
   i.PutExtra("MyRequest", "Register")
   DeviceName = Name
   ToastMessageShow("Register,Main: " & Name, False)
   Log("Service name: " & i)
   StartService(i)
End Sub

Sub Unregister(Name As String)
   Dim i As Intent
   i.Initialize("", "")
   i.SetComponent(Package & "/.push")
   i.PutExtra("MyRequest", "Unregister")
   DeviceName = Name
   ToastMessageShow("Un-Register,Main: " & Name, False)
   StartService(i)
End Sub

And this is my "Push" service code
B4X:
'Service module
Sub Process_Globals
   'These global variables will be declared once when the application starts.
   'These variables can be accessed from all modules.
   Dim hc As HttpClient
   Dim hcInit As Boolean
   hcInit = False
   Dim RegisterTask, UnregisterTask As Int
   RegisterTask = 1
   UnregisterTask = 2

End Sub
Sub Service_Create

End Sub

Sub Service_Start (StartingIntent As Intent)
   ToastMessageShow("Service started", False)
   Log("servicestarted")
   If StartingIntent.HasExtra("MyRequest") Then
      Select StartingIntent.GetExtra("MyRequest")
         Case "Register"
            RegisterDevice(False)
         Case "Unregister"
            RegisterDevice(True)
      End Select
   Else
      Select StartingIntent.Action
         Case "com.google.android.c2dm.intent.REGISTRATION"
            HandleRegistrationResult(StartingIntent)
         Case "com.google.android.c2dm.intent.RECEIVE"
            MessageArrived(StartingIntent)
      End Select
   End If
End Sub

Sub Service_Destroy

End Sub

Sub MessageArrived (Intent As Intent)
   Dim From, CollapseKey, Data As String
   If Intent.HasExtra("from") Then From = Intent.GetExtra("from")
   If Intent.HasExtra("data") Then Data = Intent.GetExtra("data")
   If Intent.HasExtra("collapse_key") Then CollapseKey = Intent.GetExtra("collapse_key")

   'Here you should handle the new message:
   Log("New message arrived: " & Data)
   ToastMessageShow("New message: " & Data, True)
   'Msgbox(Data, "New Message")
   Dim n As Notification
   n.Initialize
   'n.AutoCancel = True
   n.SetInfo("New Message", Data, "")
   'n.Vibrate = False
   n.Notify(1)

End Sub

Sub RegisterDevice (Unregister As Boolean)
   Dim i As Intent
   If Unregister Then      
      i.Initialize("com.google.android.c2dm.intent.UNREGISTER", "")
   Else
      i.Initialize("com.google.android.c2dm.intent.REGISTER", "")
      i.PutExtra("sender", Main.SenderId)
   End If
   Dim r As Reflector
   Dim i2 As Intent
   i2 = r.CreateObject("android.content.Intent")
   Dim pi As Object
   pi = r.RunStaticMethod("android.app.PendingIntent", "getBroadcast", _
      Array As Object(r.GetContext, 0, i2, 0), _
      Array As String("android.content.Context", "java.lang.int", "android.content.Intent", "java.lang.int"))
   i.PutExtra("app", pi)
   StartService(i)
End Sub
Sub HandleRegistrationResult(Intent As Intent)
   If Intent.HasExtra("error") Then
      Log("Error: " & Intent.GetExtra("error"))
      ToastMessageShow("Error: " & Intent.GetExtra("error"), True)
   Else If Intent.HasExtra("unregistered") Then
      If hcInit = False Then hc.Initialize("hc")
      Dim req As HttpRequest
      req.InitializeGet(Main.BoardUrl & "?device_password=" & Main.DeviceBoardPassword & _
         "&name=" & Main.DeviceName & "&id=") 'Empty id is sent here. This will cause the board to delete this name.
      hc.Execute(req, UnregisterTask)
   Else If Intent.HasExtra("registration_id") Then
      If hcInit = False Then hc.Initialize("hc")
      Dim rid As String
      rid = Intent.GetExtra("registration_id")
      Dim req As HttpRequest
      req.InitializeGet(Main.BoardUrl & "?device_password=" & Main.DeviceBoardPassword & _
         "&name=" & Main.DeviceName & "&id=" & rid)
      hc.Execute(req, RegisterTask)
   End If
End Sub
Sub hc_ResponseSuccess (Response As HttpResponse, TaskId As Int)
   Select TaskId
      Case RegisterTask
         ToastMessageShow("Registration completed successfully.", False)
      Case UnregisterTask
         ToastMessageShow("Unregistration completed successfully.", False)
   End Select
   Response.Release
End Sub
Sub hc_ResponseError (Response As HttpResponse, Reason As String, StatusCode As Int, TaskId As Int)
   Dim errorMsg As String
   errorMsg = "Code=" & StatusCode & ", " & Reason
   If Response <> Null Then
      errorMsg = errorMsg & ", " & Response.GetString("UTF8")
      Response.Release
   End If
   ToastMessageShow(errorMsg, True)
   Log(errorMsg)
End Sub
What am I missing? Service is not even starting.
 
Top