/******************************************************************************* * Copyright 2011, 2012, 2013 fanfou.com, Xiaoke, Zhang * * 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.fanfou.app.opensource.service; import java.util.Calendar; import java.util.List; import android.app.AlarmManager; import android.app.PendingIntent; import android.content.Context; import android.content.Intent; import android.database.Cursor; import android.net.Uri; import android.util.Log; import com.fanfou.app.opensource.AppContext; import com.fanfou.app.opensource.R; import com.fanfou.app.opensource.api.ApiClient; import com.fanfou.app.opensource.api.ApiException; import com.fanfou.app.opensource.api.ApiParser; import com.fanfou.app.opensource.api.bean.DirectMessage; import com.fanfou.app.opensource.api.bean.Status; import com.fanfou.app.opensource.db.Contents.BasicColumns; import com.fanfou.app.opensource.db.Contents.DirectMessageInfo; import com.fanfou.app.opensource.db.Contents.StatusInfo; import com.fanfou.app.opensource.db.FanFouProvider; import com.fanfou.app.opensource.util.CommonHelper; import com.fanfou.app.opensource.util.DateTimeHelper; import com.fanfou.app.opensource.util.IntentHelper; import com.fanfou.app.opensource.util.OptionHelper; /** * @author mcxiaoke * @version 1.0 2011.09.20 * @version 1.1 2011.11.02 * @version 1.2 2011.11.03 * @version 1.3 2011.11.04 * @version 2.0 2011.11.18 * @version 2.1 2011.11.23 * @version 2.2 2011.11.25 * @version 2.5 2011.12.02 * @version 2.6 2011.12.09 * @version 2.7 2011.12.19 * @version 2.8 2011.12.23 * @version 2.9 2011.12.26 * @version 3.0 2011.12.27 * @version 3.1 2011.12.30 * @version 3.2 2012.01.16 * */ public class NotificationService extends WakefulIntentService { private static final String TAG = NotificationService.class.getSimpleName(); public static final int NOTIFICATION_TYPE_HOME = Constants.TYPE_STATUSES_HOME_TIMELINE; public static final int NOTIFICATION_TYPE_MENTION = Constants.TYPE_STATUSES_MENTIONS; // @消息 public static final int NOTIFICATION_TYPE_DM = Constants.TYPE_DIRECT_MESSAGES_INBOX; // 私信 private static final int DEFAULT_COUNT = Constants.DEFAULT_TIMELINE_COUNT; private static final int MAX_COUNT = Constants.MAX_TIMELINE_COUNT; private static final int DEFAULT_PAGE = 0; private final static PendingIntent getPendingIntent(final Context context) { final Intent intent = new Intent(context, NotificationService.class); final PendingIntent pi = PendingIntent.getService(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT); return pi; } public static void set(final Context context) { final boolean need = OptionHelper.readBoolean(context, R.string.option_notification, true); if (!need) { return; } final int interval = OptionHelper.parseInt(context, R.string.option_notification_interval, "5"); final Calendar c = Calendar.getInstance(); c.add(Calendar.MINUTE, interval); final AlarmManager am = (AlarmManager) context .getSystemService(Context.ALARM_SERVICE); am.set(AlarmManager.RTC_WAKEUP, c.getTimeInMillis(), NotificationService.getPendingIntent(context)); if (AppContext.DEBUG) { Log.d(NotificationService.TAG, "set interval=" + interval + " next time=" + DateTimeHelper.formatDate(c.getTime())); } } public static void set(final Context context, final boolean set) { if (set) { NotificationService.set(context); } else { NotificationService.unset(context); } } public static void setIfNot(final Context context) { final boolean set = OptionHelper.readBoolean(context, R.string.option_set_notification, false); if (AppContext.DEBUG) { Log.d(NotificationService.TAG, "setIfNot flag=" + set); } if (!set) { OptionHelper.saveBoolean(context, R.string.option_set_notification, true); NotificationService.set(context); } } public static void unset(final Context context) { final AlarmManager am = (AlarmManager) context .getSystemService(Context.ALARM_SERVICE); am.cancel(NotificationService.getPendingIntent(context)); if (AppContext.DEBUG) { Log.d(NotificationService.TAG, "unset"); } } private ApiClient mApi; public NotificationService() { super("NotificationService"); } private void broadcast(final Intent intent) { intent.setPackage(getPackageName()); sendOrderedBroadcast(intent, null); if (AppContext.DEBUG) { Log.d(NotificationService.TAG, "broadcast() "); IntentHelper.logIntent(NotificationService.TAG, intent); } } @Override protected void doWakefulWork(final Intent intent) { final boolean dm = OptionHelper.readBoolean(this, R.string.option_notification_dm, true); final boolean mention = OptionHelper.readBoolean(this, R.string.option_notification_mention, true); final boolean home = OptionHelper.readBoolean(this, R.string.option_notification_home, false); int count = NotificationService.DEFAULT_COUNT; if (AppContext.isWifi()) { count = NotificationService.MAX_COUNT; } if (dm) { handleDm(count); } if (mention) { handleMention(count); } if (home) { handleHome(count); } NotificationService.set(this); } private void handleDm(final int count) { final Cursor mc = initCursor(Constants.TYPE_DIRECT_MESSAGES_INBOX); List<DirectMessage> dms = null; try { dms = this.mApi.directMessagesInbox(count, NotificationService.DEFAULT_PAGE, CommonHelper.getDmSinceId(mc), null, Constants.MODE); } catch (final ApiException e) { if (AppContext.DEBUG) { Log.e(NotificationService.TAG, " code=" + e.statusCode + " message=" + e.getMessage()); } } catch (final Exception e) { if (AppContext.DEBUG) { Log.e(NotificationService.TAG, e.getMessage()); } } mc.close(); if (dms != null) { final int size = dms.size(); if (size > 0) { if (AppContext.DEBUG) { Log.d(NotificationService.TAG, "handleDm() size=" + size); } if (size == 1) { final DirectMessage dm = dms.get(0); getContentResolver().insert(DirectMessageInfo.CONTENT_URI, dm.toContentValues()); notifyDmOne(NotificationService.NOTIFICATION_TYPE_DM, dms.get(0)); } else { getContentResolver().bulkInsert( DirectMessageInfo.CONTENT_URI, ApiParser.toContentValuesArray(dms)); notifyDmList(NotificationService.NOTIFICATION_TYPE_DM, size); } getContentResolver().notifyChange( DirectMessageInfo.CONTENT_URI, null, false); } } } private void handleHome(final int count) { final Cursor mc = initCursor(Constants.TYPE_STATUSES_HOME_TIMELINE); List<Status> ss = null; try { ss = this.mApi.homeTimeline(count, NotificationService.DEFAULT_PAGE, CommonHelper.getSinceId(mc), null, Constants.FORMAT, Constants.MODE); } catch (final ApiException e) { if (AppContext.DEBUG) { Log.e(NotificationService.TAG, " code=" + e.statusCode + " message=" + e.getMessage()); } } catch (final Exception e) { if (AppContext.DEBUG) { Log.e(NotificationService.TAG, e.getMessage()); } } mc.close(); if (ss != null) { final int size = ss.size(); if (size > 0) { if (AppContext.DEBUG) { Log.d(NotificationService.TAG, "handleHome() size=" + size); } if (size == 1) { final Status s = ss.get(0); getContentResolver().insert(StatusInfo.CONTENT_URI, s.toContentValues()); notifyStatusOne(NotificationService.NOTIFICATION_TYPE_HOME, ss.get(0)); } else { getContentResolver().bulkInsert(StatusInfo.CONTENT_URI, ApiParser.toContentValuesArray(ss)); notifyStatusList( NotificationService.NOTIFICATION_TYPE_HOME, size); } getContentResolver().notifyChange(StatusInfo.CONTENT_URI, null, false); } } } private void handleMention(final int count) { final Cursor mc = initCursor(Constants.TYPE_STATUSES_MENTIONS); List<Status> ss = null; try { ss = this.mApi.mentions(count, NotificationService.DEFAULT_PAGE, CommonHelper.getSinceId(mc), null, Constants.FORMAT, Constants.MODE); } catch (final ApiException e) { if (AppContext.DEBUG) { Log.e(NotificationService.TAG, " code=" + e.statusCode + " message=" + e.getMessage()); } } catch (final Exception e) { if (AppContext.DEBUG) { Log.e(NotificationService.TAG, e.getMessage()); } } mc.close(); if (ss != null) { final int size = ss.size(); if (size > 0) { if (AppContext.DEBUG) { Log.d(NotificationService.TAG, "handleMention() size=" + size); } if (size == 1) { final Status s = ss.get(0); getContentResolver().insert(StatusInfo.CONTENT_URI, s.toContentValues()); notifyStatusOne( NotificationService.NOTIFICATION_TYPE_MENTION, s); } else { getContentResolver().bulkInsert(StatusInfo.CONTENT_URI, ApiParser.toContentValuesArray(ss)); notifyStatusList( NotificationService.NOTIFICATION_TYPE_MENTION, size); } getContentResolver().notifyChange(StatusInfo.CONTENT_URI, null, false); } } } private Cursor initCursor(final int type) { final String where = BasicColumns.TYPE + " =? "; final String[] whereArgs = new String[] { String.valueOf(type) }; Uri uri = StatusInfo.CONTENT_URI; String[] columns = StatusInfo.COLUMNS; final String orderBy = FanFouProvider.ORDERBY_DATE_DESC; if (type == Constants.TYPE_DIRECT_MESSAGES_INBOX) { uri = DirectMessageInfo.CONTENT_URI; columns = DirectMessageInfo.COLUMNS; } return getContentResolver().query(uri, columns, where, whereArgs, orderBy); } private void notifyDmList(final int type, final int count) { sendMessageNotification(type, count, null); } private void notifyDmOne(final int type, final DirectMessage dm) { sendMessageNotification(type, 1, dm); } private void notifyStatusList(final int type, final int count) { sendStatusNotification(type, count, null); } private void notifyStatusOne(final int type, final Status status) { sendStatusNotification(type, 1, status); } @Override public void onCreate() { super.onCreate(); this.mApi = AppContext.getApiClient(); } private void sendMessageNotification(final int type, final int count, final DirectMessage dm) { if (AppContext.DEBUG) { Log.d(NotificationService.TAG, "sendMessageNotification type=" + type + " count=" + count + " dm=" + dm); } final Intent intent = new Intent(); intent.putExtra(Constants.EXTRA_TYPE, type); intent.putExtra(Constants.EXTRA_COUNT, count); intent.putExtra(Constants.EXTRA_DATA, dm); intent.setAction(Constants.ACTION_NOTIFICATION); broadcast(intent); } private void sendStatusNotification(final int type, final int count, final Status status) { if (AppContext.DEBUG) { Log.d(NotificationService.TAG, "sendStatusNotification type=" + type + " count=" + count + " status=" + (status == null ? "null" : status) + " active=" + AppContext.active); } final Intent intent = new Intent(); intent.putExtra(Constants.EXTRA_TYPE, type); intent.putExtra(Constants.EXTRA_COUNT, count); intent.putExtra(Constants.EXTRA_DATA, status); intent.setAction(Constants.ACTION_NOTIFICATION); broadcast(intent); } }