0

I've followed the tutorial on Vogella C2DM tutorial like most people trying to understand C2DM have, it's a great tutorial to get the code but it doesn't really help me understanding how to use it. I've set up my Android classes and my server (ported to php) but now I don't know how to proceed. My code looks like the following:

c2dm.php (server side)

 function googleAuthenticate($username, $password, $source="Company-AppName-Version", $service="ac2dm") {
    session_start();
    if( isset($_SESSION['google_auth_id']) && $_SESSION['google_auth_id'] != null)
        return $_SESSION['google_auth_id'];

    // get an authorization token
    $ch = curl_init();
    if(!ch){
        return false;
    }

    curl_setopt($ch, CURLOPT_URL, "https://www.google.com/accounts/ClientLogin");
    $post_fields = "accountType=" . urlencode('HOSTED_OR_GOOGLE')
        . "&Email=" . urlencode($username)
        . "&Passwd=" . urlencode($password)
        . "&source=" . urlencode($source)
        . "&service=" . 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);

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

    curl_close($ch);

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

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

    if (!$matches[2]) {
        return false;
    }

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

function sendMessageToPhone($authCode, $deviceRegistrationId, $msgType, $messageText) {

    $headers = array('Authorization: GoogleLogin auth=' . $authCode);
    $data = array(
        'registration_id' => $deviceRegistrationId,
        'collapse_key' => $msgType,
        'data.message' => $messageText //TODO Add more params with just simple data instead           
    );

    $ch = curl_init();

    curl_setopt($ch, CURLOPT_URL, "https://android.apis.google.com/c2dm/send");
    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);

    return $response;
}

C2DMRegistrationReceiver.java

@Override
public void onReceive(Context context, Intent intent) {
    String action = intent.getAction();
    Log.w("C2DM", "Registration Receiver called");
    if ("com.google.android.c2dm.intent.REGISTRATION".equals(action)) {
        Log.w("C2DM", "Received registration ID");
        final String registrationId = intent
                .getStringExtra("registration_id");
        String error = intent.getStringExtra("error");

        Log.d("C2DM", "dmControl: registrationId = " + registrationId
                + ", error = " + error);
        // TODO Send this to my application server
    }
}

public void sendRegistrationIdToServer(String deviceId, String registrationId) {

    Log.d("C2DM", "Sending registration ID to my application server");
    HttpClient client = new DefaultHttpClient();
    HttpPost post = new HttpPost("myserverpage");
    try {
        List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(1);
        // Get the deviceID
        nameValuePairs.add(new BasicNameValuePair("deviceid", deviceId));
        nameValuePairs.add(new BasicNameValuePair("registrationid", registrationId));

        post.setEntity(new UrlEncodedFormEntity(nameValuePairs));
        HttpResponse response = client.execute(post);
        BufferedReader rd = 
        new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
        String line = "";
        while ((line = rd.readLine()) != null) {
        Log.e("HttpResponse", line);
    }
    } catch (IOException e) {
        e.printStackTrace();
    }
}

C2DMMessageReceiver.java

@Override
public void onReceive(Context context, Intent intent) {
    String action = intent.getAction();
    Log.w("C2DM", "Message Receiver called");
    if ("com.google.android.c2dm.intent.RECEIVE".equals(action)) {
        Log.w("C2DM", "Received message");
        final String payload = intent.getStringExtra("payload");
        Log.d("C2DM", "dmControl: payload = " + payload);
        // Send this to my application server
    }
}

And in my MainActivity I have the

public void register() {
    Intent intent = new Intent("com.google.android.c2dm.intent.REGISTER");
    intent.putExtra("app",PendingIntent.getBroadcast(this, 0, new Intent(), 0));
    intent.putExtra("sender", "app-name@gmail.com");
    startService(intent);
}

I call the register() during the startup of my application and the in LogCat it says "Message Receiver called", and not "Registration Receiver called". I have of course changed the app-name@gmail.com to my own and so on but I don't know how to use the code now. Anyone who can help me?

Thanks in advance!

simtaxman
  • 613
  • 2
  • 11
  • 18
  • With Android C2DM the manifest code is just as important as the source, there is so many declarations that can be left out and causing it to not work properly. – Warpzit May 03 '12 at 09:54

3 Answers3

2

The tutorial on Vogella is pretty simple and straightforward. If you would have followed it step by step you wouldn't have such a hard time understanding.

Your logger says Message Receiver Called because that is what you log with your C2DMMessageReceiver. If you have another receiver for registering, make sure you declare it in your manifest and post the code here.

I suggest using the same receiver class. For example, here is a simple onReceive method:

if (action != null){
        // This is for registration
        if (action.equals("com.google.android.c2dm.intent.REGISTRATION")){
            Log.d(LOG_TAG, "Received registration ID");

            final String registrationId = intent.getStringExtra("registration_id");
            String error = intent.getStringExtra("error");

            Log.d(LOG_TAG, "dmControl: registrationId = " + registrationId + ", error = " + error);

            // Create a notification with the received registration id

            // Also save it in the preference to be able to show it later

            // Get the device id in order to send it to the server
            String deviceId = Secure.getString(context.getContentResolver(), Secure.ANDROID_ID);
            // .. send it to the server
        }
        // This is for receiving messages
        else if (action.equals("com.google.android.c2dm.intent.RECEIVE")){
            String payload = intent.getStringExtra("payload");
            Log.d(LOG_TAG, "Message received: " + payload);
            // .. create a notification with the new message
        }

I have added comments where you can put more actions (like creating notifications, sending your registration ID to your third party server, etc). Examples of how to do these above things are also found in Lars Vogel's tutorial.

Raul Rene
  • 10,014
  • 9
  • 53
  • 75
  • Thank you very much! I will check into it in a couple of minutes and get back to you about how it went! – simtaxman May 03 '12 at 09:42
  • I seem to be getting a hold of it now, I'm just going to implement it with my code and so on but thanks for the help! – simtaxman May 03 '12 at 09:58
  • 1
    When I send the message from the server, using php, how do I format it so I have my message and a key? Because now everything works but the message I receive is "null". – simtaxman May 03 '12 at 13:41
  • I am not really able to help you with that, as I don't really know a lot of PHP. I've found this: http://stackoverflow.com/q/6198695/1300817 . Hope it helps. – Raul Rene May 03 '12 at 13:44
  • Okey I solved it, just had to change from intent.getStringExtra("payload") to intent.getStringExtra("message") since it's data.message on the server. Thanks again! – simtaxman May 03 '12 at 13:48
0

in my case i am using single receiver for both:

if (action.equals("com.google.android.c2dm.intent.REGISTRATION")) {
String registrationId = intent.getStringExtra("registration_id");
//do somting
} else if (intent.getAction().equals("com.google.android.c2dm.intent.RECEIVE")) {
Bundle extras = intent.getExtras();
String message = extras.getString("message");
}// end if

}

and in manifest

 <receiver
  android:name=".receiverName"
 android:permission="com.google.android.c2dm.permission.SEND" >
  <intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />

<category android:name="packageName" />
</intent-filter>
<intent-filter>
<action android:name="com.google.android.c2dm.intent.REGISTRATION" />

 <category android:name="packageName" />
</intent-filter>
Zaz Gmy
  • 4,236
  • 3
  • 19
  • 30
  • Okey, and I forgot but my manifest have the correct permissions too. But how do I go from Registering -> Sending a message -> Receiving it in my application? That is my problem, the whole understanding of how to use it. – simtaxman May 03 '12 at 09:40
0

I will just explain what I have understood.

  1. First, register in android c2dm site with your android app package name say com.example.app under a gmail id that you own.

  2. Develop an android app should be capable of sending the device registration id to server as request. Server should store those ID's in db.

  3. Once you are ready to push some message to all devices from the server, you just need to have a fresh auth_token for a gmail id that you have registered in c2dm and device ids which you have stored in db.

Vogella tutorial has the sample code for getting regid for a device and auth_token. I have tried it and used it with modifications for my app.

balavj
  • 63
  • 9