package com.andrewshu.android.reddit.mail; import java.io.IOException; import java.io.InputStream; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.client.HttpClient; import org.apache.http.client.methods.HttpGet; import org.codehaus.jackson.JsonFactory; import org.codehaus.jackson.JsonParseException; import org.codehaus.jackson.JsonParser; import org.codehaus.jackson.JsonToken; import android.content.Context; import android.content.SharedPreferences; import android.preference.PreferenceManager; import android.util.Log; import com.andrewshu.android.reddit.common.Common; import com.andrewshu.android.reddit.common.Constants; import com.andrewshu.android.reddit.common.util.Util; import com.andrewshu.android.reddit.user.MeTask; import com.andrewshu.android.reddit.user.UserInfo; public class PeekEnvelopeTask extends MeTask { private static final String TAG = "PeekEnvelopeTask"; protected Context mContext; protected String mMailNotificationStyle; protected final JsonFactory jsonFactory = new JsonFactory(); public PeekEnvelopeTask(Context context, HttpClient client, String mailNotificationStyle) { super(client); mContext = context; mMailNotificationStyle = mailNotificationStyle; } @Override protected Integer onLoggedIn(UserInfo me) { HttpEntity entity = null; InputStream in = null; try { if (!me.isHas_mail() && !me.isHas_mod_mail()) return 0; HttpGet request = new HttpGet(Constants.REDDIT_BASE_URL + "/message/inbox/.json?mark=false"); HttpResponse response = mClient.execute(request); entity = response.getEntity(); in = entity.getContent(); Integer count = processInboxJSON(in); return count; } catch (Exception e) { if (Constants.LOGGING) Log.e(TAG, "PeekEnvelopeTask failed", e); } finally { try { entity.consumeContent(); } catch (Exception ignore) {} try { in.close(); } catch (Exception ignore) {} } return null; } @Override protected void onPreExecute() { if (Constants.PREF_MAIL_NOTIFICATION_STYLE_OFF.equals(mMailNotificationStyle)) this.cancel(true); SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(mContext); long lastCheck = prefs.getLong(Constants.LAST_MAIL_CHECK_TIME_MILLIS_KEY, 0); long nowMillis = System.currentTimeMillis(); if (nowMillis - lastCheck < Constants.MESSAGE_CHECK_MINIMUM_INTERVAL_MILLIS) { if (Constants.LOGGING) Log.i(TAG, "Skipping message check; last check was " + (nowMillis - lastCheck) + " millis ago"); resetAlarm(); this.cancel(true); } else { SharedPreferences.Editor editor = prefs.edit(); editor.putLong(Constants.LAST_MAIL_CHECK_TIME_MILLIS_KEY, nowMillis); editor.commit(); } } @Override public void onPostExecute(Object countObject) { Integer count = (Integer) countObject; resetAlarm(); // null means error. Don't do anything. if (count == null) return; if (count > 0) { Common.newMailNotification(mContext, mMailNotificationStyle, count); } else { Common.cancelMailNotification(mContext); } } private void resetAlarm() { SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(mContext); EnvelopeService.resetAlarm(mContext, Util.getMillisFromMailNotificationPref( prefs.getString(Constants.PREF_MAIL_NOTIFICATION_SERVICE, Constants.PREF_MAIL_NOTIFICATION_SERVICE_OFF))); } /** * Gets the author, title, body of the first inbox entry. */ private Integer processInboxJSON(InputStream in) throws IOException, JsonParseException, IllegalStateException { String genericListingError = "Not a valid listing"; Integer count = 0; JsonParser jp = jsonFactory.createJsonParser(in); /* The comments JSON file is a JSON array with 2 elements. First element is a thread JSON object, * equivalent to the thread object you get from a subreddit .json file. * Second element is a similar JSON object, but the "children" array is an array of comments * instead of threads. */ if (jp.nextToken() != JsonToken.START_OBJECT) { Log.w(TAG, "Non-JSON-object in inbox (not logged in?)"); return 0; } while (!Constants.JSON_CHILDREN.equals(jp.getCurrentName())) { // Don't care jp.nextToken(); } jp.nextToken(); if (jp.getCurrentToken() != JsonToken.START_ARRAY) throw new IllegalStateException(genericListingError); while (jp.nextToken() != JsonToken.END_ARRAY) { if (JsonToken.FIELD_NAME != jp.getCurrentToken()) continue; String namefield = jp.getCurrentName(); // Should validate each field but I'm lazy jp.nextToken(); // move to value if (Constants.JSON_NEW.equals(namefield)) { if ("true".equals(jp.getText())) count++; else // Stop parsing on first old message break; } } // Finished parsing first child return count; } }