Java tutorial
/** * 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; } }