简体   繁体   中英

Hard to understand Android C2DM

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!

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.

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>

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM