Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android C2DM Push Notification

I am developing one application and in that application I need to implement push notifications. Can anyone suggest how I should go about implementing push notifications? If I could be provided with a good tutorial, that would be great!

Thanks.

like image 369
Chirag Avatar asked Jun 08 '11 08:06

Chirag


2 Answers

// Call when your application start

public void StartRegistrationNotification()
    {

        Intent registrationIntent = new Intent("com.google.android.c2dm.intent.REGISTER");
        registrationIntent.putExtra("app", PendingIntent.getBroadcast(this, 0, new Intent(), 0));
        registrationIntent.putExtra("sender", "[email protected]");
        this.startService(registrationIntent);  

}

// change in Manifest File

<receiver android:name="com.ReceiverC2DM"
        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="yourpackagename" />
        </intent-filter>
        <!-- Receive the registration id -->
        <intent-filter>
            <action android:name="com.google.android.c2dm.intent.REGISTRATION" />
            <category android:name="yourpackagename" />
        </intent-filter>
    </receiver>
    <permission android:name="yourpackagename.permission.C2D_MESSAGE"
    android:protectionLevel="signature" />
<uses-permission android:name="yourpackagename.permission.C2D_MESSAGE" />
<!-- This app has permission to register and receive message -->
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />

// ReceiverC2DM.java .....

public class ReceiverC2DM extends BroadcastReceiver {

    private static String KEY = "c2dmPref";
    private static String REGISTRATION_KEY = "registrationKey";
    private Context context;

    // wakelock
    private static final String WAKELOCK_KEY = "C2DM_FAX";
    private static PowerManager.WakeLock mWakeLock;

    @Override
    public void onReceive(Context context, Intent intent) {
        this.context = context;

        runIntentInService(context, intent);

        if (intent.getAction().equals("com.google.android.c2dm.intent.REGISTRATION")) {
            handleRegistration(context, intent);
        } else if (intent.getAction().equals("com.google.android.c2dm.intent.RECEIVE")) {
            handleMessage(context, intent);
        }
     }

    private void handleRegistration(Context context, Intent intent) {
        String registration = intent.getStringExtra("registration_id");
        Log.e("registration :","registration :"+registration);

        if (intent.getStringExtra("error") != null) {
            // Registration failed, should try again later.
            Log.d("c2dm", "registration failed");
            String error = intent.getStringExtra("error");
            if(error == "SERVICE_NOT_AVAILABLE"){
                Log.d("c2dm", "SERVICE_NOT_AVAILABLE");
            }else if(error == "ACCOUNT_MISSING"){
                Log.d("c2dm", "ACCOUNT_MISSING");
            }else if(error == "AUTHENTICATION_FAILED"){
                Log.d("c2dm", "AUTHENTICATION_FAILED");
            }else if(error == "TOO_MANY_REGISTRATIONS"){
                Log.d("c2dm", "TOO_MANY_REGISTRATIONS");
            }else if(error == "INVALID_SENDER"){
                Log.d("c2dm", "INVALID_SENDER");
            }else if(error == "PHONE_REGISTRATION_ERROR"){
                Log.d("c2dm", "PHONE_REGISTRATION_ERROR");
            }
        } else if (intent.getStringExtra("unregistered") != null) {
            // unregistration done, new messages from the authorized sender will be rejected
            Log.d("c2dm", "unregistered");

        } else if (registration != null) {
            Log.d("c2dm", registration);
            Editor editor =
                context.getSharedPreferences(KEY, Context.MODE_PRIVATE).edit();
            editor.putString(REGISTRATION_KEY, registration);
            editor.commit();
           // Send the registration ID to the 3rd party site that is sending the messages.
           // This should be done in a separate thread.
           // When done, remember that all registration is done.
        }
    }


    private void handleMessage(Context context, Intent intent)
    {

     String message = intent.getExtras().getString("payload");
     String key = intent.getExtras().getString("collapse_key");
     Log.e("","accountName : " +accountName);
     Log.e("","message : " +message);    
          Intent startActivity = new Intent(); 
            startActivity.setClass(context, NotificationAlert.class); 
            startActivity.setAction(NotificationAlert.class.getName()); 
            startActivity.setFlags( 
                    Intent.FLAG_ACTIVITY_NEW_TASK 
                    | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);      
            startActivity.putExtra("Title", "Hello");
            startActivity.putExtra("Message", message);
            context.startActivity(startActivity);   

        //Do whatever you want with the message         
    }

    static void runIntentInService(Context context, Intent intent) {
        if (mWakeLock == null) {
                // This is called from BroadcastReceiver, there is no init.
                PowerManager pm = 
                        (PowerManager) context.getSystemService(Context.POWER_SERVICE);
                mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, 
                                WAKELOCK_KEY);
        }
        mWakeLock.acquire();
    }

// Server Side ... New Test App

ServerSimulator.java

private SharedPreferences prefManager;
private final static String AUTH = "authentication";

private static final String UPDATE_CLIENT_AUTH = "Update-Client-Auth";

public static final String PARAM_REGISTRATION_ID = "registration_id";

public static final String PARAM_DELAY_WHILE_IDLE = "delay_while_idle";

public static final String PARAM_COLLAPSE_KEY = "collapse_key";

private static final String UTF8 = "UTF-8";

// Registration is currently hardcoded
private final static String YOUR_REGISTRATION_STRING = "put registration key";

private SharedPreferences prefs;

/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    prefManager = PreferenceManager.getDefaultSharedPreferences(this);
}




public void getAuthentification(View view) {
    SharedPreferences prefs = PreferenceManager
            .getDefaultSharedPreferences(this);

    HttpClient client = new DefaultHttpClient();
    HttpPost post = new HttpPost(
            "https://www.google.com/accounts/ClientLogin");

    try {

        List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(1);
        nameValuePairs.add(new BasicNameValuePair("Email", "[email protected]"));
        nameValuePairs.add(new BasicNameValuePair("Passwd","....."));
        nameValuePairs.add(new BasicNameValuePair("accountType", "GOOGLE"));
        nameValuePairs.add(new BasicNameValuePair("source",
                "Google-cURL-Example"));
        nameValuePairs.add(new BasicNameValuePair("service", "ac2dm"));

        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);
            if (line.startsWith("Auth=")) {
                Editor edit = prefManager.edit();
                edit.putString(AUTH, line.substring(5));
                edit.commit();
                String s = prefManager.getString(AUTH, "n/a");
                Toast.makeText(this, s, Toast.LENGTH_LONG).show();
            }

        }
    } catch (IOException e) {
        e.printStackTrace();
    }
}

public void showAuthentification(View view) {
    String s = prefManager.getString(AUTH, "n/a");
    Toast.makeText(this, s, Toast.LENGTH_LONG).show();
}

public void sendMessage(View view) {
    try {
        Log.e("Tag", "Started");
        String auth_key = prefManager.getString(AUTH, "n/a");
        // Send a sync message to this Android device.
        StringBuilder postDataBuilder = new StringBuilder();
        postDataBuilder.append(PARAM_REGISTRATION_ID).append("=")
                .append(YOUR_REGISTRATION_STRING);

        // if (delayWhileIdle) {
        // postDataBuilder.append("&").append(PARAM_DELAY_WHILE_IDLE)
        // .append("=1");
        // }
        postDataBuilder.append("&").append(PARAM_COLLAPSE_KEY).append("=")
                .append("0");

        postDataBuilder.append("&").append("data.payload").append("=")
                .append(URLEncoder.encode("Fax Sent ... Test Push Notification ....", UTF8));

        Log.e("postDataBuilder ","postDataBuilder :" + postDataBuilder.toString());

        byte[] postData = postDataBuilder.toString().getBytes(UTF8);

        // Hit the dm URL.

        URL url = new URL("https://android.clients.google.com/c2dm/send");

        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        conn.setDoOutput(true);
        conn.setUseCaches(false);
        conn.setRequestMethod("POST");
        conn.setRequestProperty("Content-Type",
                "application/x-www-form-urlencoded;charset=UTF-8");
        conn.setRequestProperty("Content-Length",
                Integer.toString(postData.length));
        conn.setRequestProperty("Authorization", "GoogleLogin auth="
                + auth_key);

        OutputStream out = conn.getOutputStream();
        out.write(postData);
        out.close();

        int responseCode = conn.getResponseCode();

        Log.e("Tag", String.valueOf(responseCode));
        // Validate the response code

        if (responseCode == 401 || responseCode == 403) {
            // The token is too old - return false to retry later, will
            // fetch the token
            // from DB. This happens if the password is changed or token
            // expires. Either admin
            // is updating the token, or Update-Client-Auth was received by
            // another server,
            // and next retry will get the good one from database.
            Log.e("C2DM", "Unauthorized - need token");
        }

        // Check for updated token header
        String updatedAuthToken = conn.getHeaderField(UPDATE_CLIENT_AUTH);
        if (updatedAuthToken != null && !auth_key.equals(updatedAuthToken)) {
            Log.i("C2DM",
                    "Got updated auth token from datamessaging servers: "
                            + updatedAuthToken);
            Editor edit = prefManager.edit();
            edit.putString(AUTH, updatedAuthToken);
        }

        String responseLine = new BufferedReader(new InputStreamReader(
                conn.getInputStream())).readLine();

        // NOTE: You *MUST* use exponential backoff if you receive a 503
        // response code.
        // Since App Engine's task queue mechanism automatically does this
        // for tasks that
        // return non-success error codes, this is not explicitly
        // implemented here.
        // If we weren't using App Engine, we'd need to manually implement
        // this.
        if (responseLine == null || responseLine.equals("")) {
            Log.i("C2DM", "Got " + responseCode
                    + " response from Google AC2DM endpoint.");
            throw new IOException(
                    "Got empty response from Google AC2DM endpoint.");
        }

        String[] responseParts = responseLine.split("=", 2);
        if (responseParts.length != 2) {
            Log.e("C2DM", "Invalid message from google: " + responseCode
                    + " " + responseLine);
            throw new IOException("Invalid response from Google "
                    + responseCode + " " + responseLine);
        }

        if (responseParts[0].equals("id")) {
            Log.i("Tag", "Successfully sent data message to device: "
                    + responseLine);
        }

        if (responseParts[0].equals("Error")) {
            String err = responseParts[1];
            Log.w("C2DM",
                    "Got error response from Google datamessaging endpoint: "
                            + err);
            // No retry.
            throw new IOException(err);
        }
    } catch (Exception e) {
        throw new RuntimeException(e);
    }
}   
like image 158
SBJ Avatar answered Nov 01 '22 11:11

SBJ


C2DM is deprecated and has been replaced by Google Cloud Messaging for Android (GCM). Google's statement:

Important: C2DM has been officially deprecated as of June 26, 2012. This means that C2DM has stopped accepting new users and quota requests. No new features will be added to C2DM. However, apps using C2DM will continue to work. Existing C2DM developers are encouraged to migrate to the new version of C2DM, called Google Cloud Messaging for Android (GCM). See the C2DM-to-GCM Migration document for more information. Developers must use GCM for new development.

There is a demo app tutorial for GCM and also for migration from C2DM.

like image 21
Anton Kaiser Avatar answered Nov 01 '22 12:11

Anton Kaiser