it.mb.whatshare.SendToGCMActivity.java Source code

Java tutorial

Introduction

Here is the source code for it.mb.whatshare.SendToGCMActivity.java

Source

/**
 * SendToGCMActivity.java Created on 25 Mar 2013 Copyright 2013 Michele Bonazza
 * <emmepuntobi@gmail.com>
 * 
 * his file is part of WhatsHare.
 * 
 * WhatsHare is free software: you can redistribute it and/or modify it under
 * the terms of the GNU General Public License as published by the Free Software
 * Foundation, either version 3 of the License, or (at your option) any later
 * version.
 * 
 * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License along with
 * WhatsHare. If not, see <http://www.gnu.org/licenses/>.
 */
package it.mb.whatshare;

import it.mb.whatshare.MainActivity.PairedDevice;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.OptionalDataException;
import java.io.UnsupportedEncodingException;
import java.util.Locale;
import java.util.Scanner;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.BasicResponseHandler;
import org.apache.http.impl.client.DefaultHttpClient;
import org.json.JSONException;
import org.json.JSONObject;

import android.annotation.TargetApi;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.NotificationCompat;
import android.util.Pair;

import com.google.analytics.tracking.android.EasyTracker;
import com.google.analytics.tracking.android.GoogleAnalytics;
import com.google.analytics.tracking.android.Tracker;

/**
 * Activity called when sharing content from this device to be sent to the
 * Android device where Whatsapp is installed through GCM.
 * 
 * @author Michele Bonazza
 */
public class SendToGCMActivity extends FragmentActivity {

    private class CallGCM extends AsyncTask<String, Void, Void> {

        /*
         * (non-Javadoc)
         * 
         * @see android.os.AsyncTask#doInBackground(Params[])
         */
        @Override
        protected Void doInBackground(String... params) {
            String text = params[0];
            String type = params[1];
            String assignedID = PairOutboundActivity.getAssignedID(SendToGCMActivity.this);
            HttpPost post = new HttpPost(GCM_URL);
            try {
                Utils.debug(String.format(
                        "{\"registration_ids\": [\"%s\"], \"data\": {\"message\": \"%s\", \"sender\": \"%s\", \"type\": \"%s\"}}",
                        outboundDevice.name, JSONObject.quote(text), JSONObject.quote(assignedID), type));
                post.setEntity(new StringEntity(String.format(
                        "{\"delay_while_idle\": false, \"registration_ids\": [\"%s\"], \"data\": {\"message\": %s, \"sender\": %s, \"type\": \"%s\"}}",
                        outboundDevice.name, JSONObject.quote(text), JSONObject.quote(assignedID), type)));
                post.setHeader("Content-Type", "application/json");
                post.setHeader("Authorization",
                        "key=" + SendToGCMActivity.this.getResources().getString(R.string.android_shortener_key));
                String response = new DefaultHttpClient().execute(post, new BasicResponseHandler());
                Utils.debug("response is %s", response);
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            } catch (ClientProtocolException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return null;
        }

    }

    private static final String GCM_URL = "https://android.googleapis.com/gcm/send";
    private static final Pattern FLIPBOARD_PATTERN = Pattern.compile("\\w+\\:(.+)");
    private static AtomicInteger notificationCounter = new AtomicInteger();
    private String registrationID = "";
    private int registrationError = -1;
    private PairedDevice outboundDevice;
    private Tracker tracker;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        tracker = GoogleAnalytics.getInstance(this).getDefaultTracker();
        if ("".equals(registrationID)) {
            if (!Utils.isConnectedToTheInternet(this)) {
                Dialogs.noInternetConnection(this, R.string.no_internet_sending, true);
            } else {
                GCMIntentService.registerWithGCM(this);
                new AsyncTask<Void, Void, Void>() {

                    private ProgressDialog dialog;

                    /*
                     * (non-Javadoc)
                     * 
                     * @see android.os.AsyncTask#onPreExecute()
                     */
                    @Override
                    protected void onPreExecute() {
                        dialog = ProgressDialog.show(SendToGCMActivity.this,
                                getResources().getString(R.string.please_wait),
                                getResources().getString(R.string.wait_registration));
                    }

                    @Override
                    protected Void doInBackground(Void... params) {
                        try {
                            registrationID = GCMIntentService.getRegistrationID();
                        } catch (CantRegisterWithGCMException e) {
                            registrationError = e.getMessageID();
                        }
                        return null;
                    }

                    /*
                     * (non-Javadoc)
                     * 
                     * @see android.os.AsyncTask#onPostExecute(java.lang.Object)
                     */
                    @Override
                    protected void onPostExecute(Void result) {
                        super.onPostExecute(result);
                        dialog.dismiss();
                        if (registrationError != -1) {
                            Dialogs.onRegistrationError(registrationError, SendToGCMActivity.this, true);
                        } else {
                            onNewIntent(getIntent());
                        }
                    }
                }.execute();
            }
        }
    }

    /*
     * (non-Javadoc)
     * 
     * @see android.app.Activity#onStart()
     */
    @Override
    protected void onStart() {
        super.onStart();
        EasyTracker.getInstance().activityStart(this);
    }

    /*
     * (non-Javadoc)
     * 
     * @see android.app.Activity#onStop()
     */
    @Override
    protected void onStop() {
        super.onStop();
        EasyTracker.getInstance().activityStop(this);
    }

    /*
     * (non-Javadoc)
     * 
     * @see android.app.Activity#onNewIntent(android.content.Intent)
     */
    @Override
    protected void onNewIntent(final Intent intent) {
        tracker = GoogleAnalytics.getInstance(this).getDefaultTracker();
        if (intent.hasExtra(Intent.EXTRA_TEXT)) {
            if (!Utils.isConnectedToTheInternet(this)) {
                Dialogs.noInternetConnection(this, R.string.no_internet_sending, true);
            } else {
                // send to paired device if any
                try {
                    if (outboundDevice == null) {
                        Pair<PairedDevice, String> paired = loadOutboundPairing(this);
                        if (paired != null)
                            outboundDevice = paired.first;
                    }
                    if (outboundDevice != null) {
                        // share with other device
                        shareViaGCM(intent);
                        finish();
                        return;
                    }
                } catch (OptionalDataException e) {
                    e.printStackTrace();
                } catch (ClassNotFoundException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                // can't load paired device from file
                tracker.sendEvent("intent", "send_to_gcm", "no_paired_device", 0L);
                Dialogs.noPairedDevice(this);
            }
        } else {
            // user clicked on the notification
            notificationCounter.set(0);
            finish();
        }
    }

    /**
     * Loads the ID and name of the paired device in use to share content when
     * Whatsapp is not installed on this device.
     * 
     * @param activity
     *            the calling activity
     * @return the device loaded from file if any is configured,
     *         <code>null</code> otherwise
     * @throws OptionalDataException
     * @throws ClassNotFoundException
     * @throws IOException
     */
    static Pair<PairedDevice, String> loadOutboundPairing(Context activity)
            throws OptionalDataException, ClassNotFoundException, IOException {
        FileInputStream fis = activity.openFileInput("pairing");
        Scanner scanner = new Scanner(fis).useDelimiter("\\Z");
        JSONObject json;
        try {
            json = new JSONObject(scanner.next());
            String name = json.getString("name");
            String type = json.getString("type");
            String assignedID = json.getString("assignedID");
            return new Pair<PairedDevice, String>(new PairedDevice(assignedID, name, type), assignedID);
        } catch (JSONException e) {
            e.printStackTrace();
        }
        return null;
    }

    private void shareViaGCM(Intent intent) {
        String subject = intent.getExtras().getString(Intent.EXTRA_SUBJECT);
        String text = intent.getExtras().getString(Intent.EXTRA_TEXT);
        String type = intent.getExtras().getString(MainActivity.INTENT_TYPE_EXTRA);
        if (type == null)
            type = MainActivity.SHARE_VIA_WHATSAPP_EXTRA;
        if (mustIncludeSubject(subject, text)) {
            text = subject + " - " + text;
        }
        int sharedWhat = text.contains("http://") ? R.string.link : R.string.selection;
        Utils.debug("sharing with %s this: '%s'", outboundDevice.type, text);
        new CallGCM().execute(text, type);
        tracker.sendEvent("gcm", "share", sharedWhat == R.string.link ? "link" : "text", 0L);
        showNotification(sharedWhat, MainActivity.SHARE_VIA_WHATSAPP_EXTRA.equals(type));
    }

    @SuppressWarnings("deprecation")
    private void showNotification(int sharedWhat, boolean sharedViaWhatsapp) {
        String title = getString(R.string.whatshare);
        Intent onNotificationDiscarded = new Intent(this, SendToGCMActivity.class);
        PendingIntent notificationIntent = PendingIntent.getActivity(this, 0, onNotificationDiscarded, 0);
        Notification notification = null;
        int notificationIcon = sharedViaWhatsapp ? R.drawable.notification_icon
                : R.drawable.whatshare_logo_notification;
        int notificationNumber = notificationCounter.incrementAndGet();
        String content = getString(R.string.share_success, getString(sharedWhat), outboundDevice.type);
        // @formatter:off
        NotificationCompat.Builder builder = new NotificationCompat.Builder(this).setSmallIcon(notificationIcon, 0)
                .setContentTitle(title).setContentText(content).setTicker(content)
                .setContentIntent(notificationIntent)
                .setDeleteIntent(PendingIntent.getActivity(this, 0, onNotificationDiscarded, 0))
                .setNumber(notificationNumber);
        // @formatter:on
        if (Build.VERSION.SDK_INT > 15) {
            notification = buildForJellyBean(builder);
        } else {
            notification = builder.getNotification();
        }
        notification.flags |= Notification.FLAG_AUTO_CANCEL;
        NotificationManager nm = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
        // cancel previous notification to clean up garbage in the status bar
        nm.cancel(notificationNumber - 1);
        nm.notify(notificationNumber, notification);
    }

    @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
    private Notification buildForJellyBean(NotificationCompat.Builder builder) {
        builder.setPriority(Notification.PRIORITY_MAX);
        return builder.build();
    }

    private boolean mustIncludeSubject(String subject, String text) {
        if (subject == null)
            return false;
        subject = subject.trim().toLowerCase(Locale.getDefault());
        text = text.trim().toLowerCase(Locale.getDefault());
        if (subject.length() == 0 || subject.equals(text)) {
            return false;
        }
        // test for flipboard
        Matcher matcher = FLIPBOARD_PATTERN.matcher(subject);
        if (matcher.matches() && matcher.groupCount() == 1) {
            String testIncluded = matcher.group(1).trim();
            Utils.debug("testing if '%s' contains '%s'", text, testIncluded);
            return !text.contains(testIncluded);
        }
        return true;
    }
}