Java tutorial
/* * NarwhalNotifierReceiver.java * * Defines the class that receives the alarm from the AlarmManager to check for new messages * * Copyright 2012 Shawn Busolits * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. You may obtain a * copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations * under the License. */ package com.quicklookbusy.narwhalNotifier; import java.text.DecimalFormat; import java.text.NumberFormat; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Arrays; import java.util.Date; import org.apache.http.NameValuePair; import org.apache.http.message.BasicNameValuePair; import org.json.JSONArray; import org.json.JSONObject; import org.json.JSONTokener; import android.app.Notification; import android.app.NotificationManager; import android.app.PendingIntent; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import android.content.SharedPreferences.Editor; import android.net.Uri; import android.support.v4.app.NotificationCompat; import android.util.Log; import busoLibs.asyncRequest.AsyncRequest; import busoLibs.asyncRequest.RequestCallback; /** * An extension of BroadcastReceiver used to check for unread messages * * @author Shawn Busolits * @version 1.0 */ public class NarwhalNotifierReceiver extends BroadcastReceiver { /** ID used to send message notifications */ public static final int NOTIFICATION_ID = 86949977; /** ID used to send modmail notifications */ public static final int MODMAIL_NOTIFICATION_ID = 86949978; /** ID used to send modqueue notifications */ public static final int MODQUEUE_NOTIFICATION_ID = 86949979; /** Holds state about whether the service is running */ volatile boolean runService; /** Used to send notifications to the user */ NotificationManager notificationManager; /** Tag for log messages */ String logTag = "NarwhalNotifierService"; /** Used to store state about the app */ SharedPreferences settings; /** Used to edit state about the app */ Editor settingsEditor; /** * Called by the AlarmManager. Checks if the user has any unread messages * * @param context * Context of the app * @param i * Intent of the caller */ @Override public void onReceive(Context context, Intent i) { log("Alarm went off!"); String ns = Context.NOTIFICATION_SERVICE; notificationManager = (NotificationManager) context.getSystemService(ns); settings = context.getSharedPreferences(NarwhalNotifier.PREFS_NAME, 0); settingsEditor = settings.edit(); /* * runService = true; RedditHitter hitter = new RedditHitter(); * hitter.start(); */ log("checkMessages is " + settings.getBoolean("checkMessages", false)); if (settings.getBoolean("checkMessages", false)) { checkMessages(context, false); } log("checkModmail is " + settings.getBoolean("checkModmail", false)); if (settings.getBoolean("checkModmail", false)) { checkMessages(context, true); } log("checkModqueue is " + settings.getBoolean("checkModqueue", false)); if (settings.getBoolean("checkModqueue", false)) { checkModqueue(context); } } /** * Checks if the user has any unread messages * * @param context * Context of the app */ private void checkMessages(Context context, boolean modmail) { String url = ""; if (modmail) { url = "http://www.reddit.com/message/moderator/unread/.json"; } else { url = "http://www.reddit.com/message/unread/.json"; } NameValuePair header = new BasicNameValuePair("Cookie", "reddit_session=" + settings.getString("cookie", "")); AsyncRequest req = new AsyncRequest(url, null, Arrays.asList(header), new MessageCallback(context, modmail), AsyncRequest.REQUEST_TYPE.GET); req.start(); } /** * Checks if there are any messages in the user's modqueues * * @param context * Context of the app */ private void checkModqueue(Context context) { String url = "http://www.reddit.com/r/mod/about/modqueue.json"; NameValuePair header = new BasicNameValuePair("Cookie", "reddit_session=" + settings.getString("cookie", "")); AsyncRequest req = new AsyncRequest(url, null, Arrays.asList(header), new ModqueueCallback(context), AsyncRequest.REQUEST_TYPE.GET); req.start(); } /** * Log to logcat * * @param s * String to write to logcat */ private void log(String s) { SimpleDateFormat df = new SimpleDateFormat("HH:mm:ss"); Date date = new Date(); Log.d(logTag, df.format(date) + ": " + s); } /** * Called with the result of querying reddit for messages, both normal and * moderator * * @author Shawn Busolits * @version 1.0 */ public class MessageCallback implements RequestCallback { /** Used for notifications */ Context context; /** Used to keep state */ boolean modmail; /** * Initializes the callback with the context * * @param context * Context of the app */ public MessageCallback(Context context, boolean modmail) { this.context = context; this.modmail = modmail; } /** * Reads the results and determines if a notification is required * * @param o * Object returned from AsyncRequest */ public void doOnResult(Object o) { String topTimeString = ""; String contentSuffix = ""; String intentURL = ""; String contentTitle = ""; String tickerText = ""; String type = ""; int notificationID = 0; int icon = 0; if (modmail) { topTimeString = "topModmailMessageTime"; contentSuffix = " new modmail messages. Click here to view them!"; intentURL = "http://www.reddit.com/message/moderator"; type = "modmail "; notificationID = MODMAIL_NOTIFICATION_ID; icon = R.drawable.mod_notification; } else { topTimeString = "topMessageTime"; contentSuffix = " new reddit messages. Click here to view them!"; intentURL = "http://www.reddit.com/message/unread"; notificationID = NOTIFICATION_ID; icon = R.drawable.notification; } // tickerText = contentTitle; try { String jsonString = (String) o; JSONTokener tokener = new JSONTokener(jsonString); JSONObject jsonResult = new JSONObject(tokener); JSONObject data = jsonResult.getJSONObject("data"); settingsEditor.putString("modhash", data.getString("modhash")); settingsEditor.commit(); JSONArray children = data.getJSONArray("children"); int numMessages = children.length(); if (numMessages == 0) { log("No new messages"); notificationManager.cancel(notificationID); } else { log("New messages!"); JSONObject topMessageData = children.getJSONObject(0).getJSONObject("data"); String createdString = topMessageData.getString("created"); NumberFormat nf = new DecimalFormat("###.##"); long topMessageTime = nf.parse(createdString).longValue(); if (topMessageTime > settings.getLong(topTimeString, 0)) { log("Notifying"); // Only notify on a new top message settingsEditor.putLong(topTimeString, topMessageTime); settingsEditor.commit(); // Taken from // http://developer.android.com/guide/topics/ui/notifiers/notifications.html long when = System.currentTimeMillis(); CharSequence contentText = ""; if (numMessages > 1) { contentTitle = numMessages + " new " + type + "messages"; tickerText = contentTitle; contentText = "You have " + numMessages + contentSuffix; } else { contentTitle = "1 new " + type + "message"; tickerText = contentTitle; String author = topMessageData.getString("author"); String body = topMessageData.getString("body"); String subreddit = topMessageData.getString("subreddit"); contentText = body + " - " + author + " via " + subreddit; } // Build list of messages for expanded notification ArrayList<String> expandedContentTexts = new ArrayList<String>(); for (int i = 0; i < children.length(); i++) { JSONObject child = children.getJSONObject(i).getJSONObject("data"); String author = child.getString("author"); String body = child.getString("body"); String subreddit = child.getString("subreddit"); String expandedContentText = body + " - " + author + " via " + subreddit; expandedContentTexts.add(expandedContentText); } Intent notificationIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(intentURL)); PendingIntent contentIntent = PendingIntent.getActivity(context, 0, notificationIntent, 0); NotificationCompat.Builder builder = new NotificationCompat.Builder(context); builder.setContentTitle(contentTitle).setTicker(tickerText).setContentText(contentText) .setSmallIcon(icon).setContentIntent(contentIntent).setWhen(when); NotificationCompat.InboxStyle inboxStyle = new NotificationCompat.InboxStyle(); inboxStyle.setBigContentTitle(contentTitle); for (String expandedContentText : expandedContentTexts) { inboxStyle.addLine(expandedContentText); } builder.setStyle(inboxStyle); Notification notification = builder.build(); notification.defaults |= Notification.DEFAULT_SOUND; notification.defaults |= Notification.DEFAULT_VIBRATE; notification.flags |= Notification.FLAG_AUTO_CANCEL; notificationManager.notify(notificationID, notification); } } } catch (Exception e) { log("Error getting messages: " + e.toString()); } } } /** * Called with the result of querying reddit for modqueue info * * @author Shawn Busolits * @version 1.0 */ public class ModqueueCallback implements RequestCallback { /** Used for notifications */ Context context; public ModqueueCallback(Context context) { this.context = context; } /** * Reads the results and updates settings editor with a list of full * modqueues * * @param o * Object returned from AsyncRequest */ public void doOnResult(Object o) { settingsEditor.putLong("prevTopModqueueTime", settings.getLong("currentTopModqueueTime", 0)); settingsEditor.commit(); try { String jsonString = (String) o; JSONTokener tokener = new JSONTokener(jsonString); JSONObject jsonResult = new JSONObject(tokener); JSONObject data = jsonResult.getJSONObject("data"); settingsEditor.putString("modhash", data.getString("modhash")); settingsEditor.commit(); JSONArray children = data.getJSONArray("children"); int numMessages = children.length(); if (numMessages == 0) { log("No new modqueues"); notificationManager.cancel(MODQUEUE_NOTIFICATION_ID); } else { log("New modqueues!"); JSONObject topMessageData = children.getJSONObject(0).getJSONObject("data"); String createdString = topMessageData.getString("created"); NumberFormat nf = new DecimalFormat("###.##"); long topMessageTime = nf.parse(createdString).longValue(); if (topMessageTime > settings.getLong("topModqueueTime", 0)) { log("Notifying"); // Only notify on a new top message settingsEditor.putLong("topModqueueTime", topMessageTime); settingsEditor.commit(); // Taken from // http://developer.android.com/guide/topics/ui/notifiers/notifications.html long when = System.currentTimeMillis(); CharSequence contentText = ""; String contentTitle = ""; String tickerText = ""; if (numMessages > 1) { contentTitle = numMessages + " new modqueue items"; tickerText = contentTitle; contentText = "You have " + numMessages + " new items in your modqueue"; } else { contentTitle = "1 new modqueue item"; tickerText = contentTitle; String author = topMessageData.getString("author"); String title = topMessageData.getString("title"); String subreddit = topMessageData.getString("subreddit"); contentText = title + " - " + author + " via " + subreddit; } // Build list of messages for expanded notification ArrayList<String> expandedContentTexts = new ArrayList<String>(); for (int i = 0; i < children.length(); i++) { JSONObject child = children.getJSONObject(i).getJSONObject("data"); String author = child.getString("author"); String title = child.getString("title"); String subreddit = child.getString("subreddit"); String expandedContentText = title + " - " + author + " via " + subreddit; expandedContentTexts.add(expandedContentText); } Intent notificationIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.reddit.com/r/mod/about/modqueue")); PendingIntent contentIntent = PendingIntent.getActivity(context, 0, notificationIntent, 0); NotificationCompat.Builder builder = new NotificationCompat.Builder(context); builder.setContentTitle(contentTitle).setTicker(tickerText).setContentText(contentText) .setSmallIcon(R.drawable.mod_notification).setContentIntent(contentIntent) .setWhen(when); NotificationCompat.InboxStyle inboxStyle = new NotificationCompat.InboxStyle(); inboxStyle.setBigContentTitle("New modqueue items"); for (String expandedContentText : expandedContentTexts) { inboxStyle.addLine(expandedContentText); } builder.setStyle(inboxStyle); Notification notification = builder.build(); notification.defaults |= Notification.DEFAULT_SOUND; notification.defaults |= Notification.DEFAULT_VIBRATE; notification.flags |= Notification.FLAG_AUTO_CANCEL; notificationManager.notify(MODQUEUE_NOTIFICATION_ID, notification); } } } catch (Exception e) { log("Error getting messages: " + e.toString()); } } } }