package com.dotcool.reader.service; import java.util.ArrayList; import java.util.Date; import android.annotation.TargetApi; import android.app.Notification; import android.app.NotificationManager; import android.app.PendingIntent; import android.app.Service; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import android.os.Binder; import android.os.IBinder; import android.preference.PreferenceManager; import android.util.Log; import android.widget.Toast; import com.dotcool.reader.Constants; import com.dotcool.reader.LNReaderApplication; import com.dotcool.reader.callback.CallbackEventData; import com.dotcool.reader.callback.ICallbackNotifier; import com.dotcool.reader.dao.NovelsDao; import com.dotcool.reader.model.PageModel; import com.dotcool.reader.model.UpdateInfoModel; import com.dotcool.reader.model.UpdateType; import com.dotcool.view.MainTabActivity; public class UpdateService extends Service { private final IBinder mBinder = new MyBinder(); public boolean force = false; public final static String TAG = UpdateService.class.toString(); private static boolean isRunning; public ICallbackNotifier notifier; @Override public int onStartCommand(Intent intent, int flags, int startId) { Log.d(TAG, "onStartCommand"); execute(); return Service.START_NOT_STICKY; } @Override public IBinder onBind(Intent arg0) { Log.d(TAG, "onBind"); return mBinder; } @Override public void onCreate() { // Display a notification about us starting. We put an icon in the status bar. Log.d(TAG, "onCreate"); execute(); } @TargetApi(11) public void execute() { if (!shouldRun(force)) { // Reschedule for next run MyScheduleReceiver.reschedule(this); isRunning = false; return; } if (!isRunning) { SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(this); SharedPreferences.Editor editor = sharedPrefs.edit(); editor.putString(Constants.PREF_RUN_UPDATES, "Running..."); editor.putString(Constants.PREF_RUN_UPDATES_STATUS, ""); editor.commit(); // GetUpdatedChaptersTask task = new GetUpdatedChaptersTask(this, GetAutoDownloadUpdatedChapterPreferences(), notifier); // if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) // task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); // else // task.execute(); // add on Download List LNReaderApplication.getInstance().addDownload(TAG, "Update Service"); } } private boolean GetAutoDownloadUpdatedChapterPreferences() { return PreferenceManager.getDefaultSharedPreferences(this).getBoolean(Constants.PREF_AUTO_DOWNLOAD_UPDATED_CHAPTER, false); } public class MyBinder extends Binder { public UpdateService getService() { Log.d(TAG, "getService"); return UpdateService.this; } } public void sendNotification(ArrayList<PageModel> updatedChapters) { NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); if (updatedChapters != null && updatedChapters.size() > 0) { Log.d(TAG, "sendNotification"); // remove previous update history. // NovelsDao.getInstance(this).deleteAllUpdateHistory(); // create UpdateInfoModel list int updateCount = 0; int newCount = 0; int newNovel = 0; ArrayList<UpdateInfoModel> updatesInfo = new ArrayList<UpdateInfoModel>(); for (PageModel pageModel : updatedChapters) { UpdateInfoModel updateInfo = new UpdateInfoModel(); if (pageModel.getType().equalsIgnoreCase(PageModel.TYPE_NOVEL)) { ++newNovel; updateInfo.setUpdateTitle("New Novel: " + pageModel.getTitle()); updateInfo.setUpdateType(UpdateType.NewNovel); } else if (pageModel.getType().equalsIgnoreCase(PageModel.TYPE_TOS)) { updateInfo.setUpdateTitle("Updated TOS"); updateInfo.setUpdateType(UpdateType.UpdateTos); } else { if (pageModel.isUpdated()) { updateInfo.setUpdateType(UpdateType.Updated); ++updateCount; } else { updateInfo.setUpdateType(UpdateType.New); ++newCount; } String novelTitle = ""; try { novelTitle = pageModel.getBook().getParent().getPageModel().getTitle() + ": "; } catch (Exception ex) { Log.e(TAG, "Error when getting Novel title", ex); } updateInfo.setUpdateTitle(novelTitle + pageModel.getTitle() + " (" + pageModel.getBook().getTitle() + ")"); } updateInfo.setUpdateDate(pageModel.getLastUpdate()); updateInfo.setUpdatePage(pageModel.getPage()); updateInfo.setUpdatePageModel(pageModel); // insert to db NovelsDao.getInstance(this).insertUpdateHistory(updateInfo); updatesInfo.add(updateInfo); } if (getConsolidateNotificationPref()) { createConsolidatedNotification(mNotificationManager, updateCount, newCount, newNovel); } else { int id = Constants.NOTIFIER_ID; boolean first = true; for (UpdateInfoModel updateInfoModel : updatesInfo) { final int notifId = ++id; Log.d(TAG, "set Notification for: " + updateInfoModel.getUpdatePage()); Notification notification = getNotificationTemplate(first); first = false; prepareNotification(notifId, updateInfoModel, notification); mNotificationManager.notify(notifId, notification); } } } updateStatus("OK"); Toast.makeText(this, "Update Service completed", Toast.LENGTH_SHORT).show(); LNReaderApplication.getInstance().updateDownload(TAG, 100, "Update Service completed"); // remove from download list LNReaderApplication.getInstance().removeDownload(TAG); } @SuppressWarnings("deprecation") public void createConsolidatedNotification(NotificationManager mNotificationManager, int updateCount, int newCount, int newNovel) { Log.d(TAG, "set consolidated Notification"); Notification notification = getNotificationTemplate(true); CharSequence contentTitle = "BakaReader EX Updates"; String contentText = "Found"; if (updateCount > 0) { contentText += " " + updateCount + " updated chapter(s)"; } if (newCount > 0) { if (updateCount > 0) contentText += " and "; contentText += " " + newCount + " new chapter(s)"; } if (newNovel > 0) { if (updateCount > 0 || newCount > 0) contentText += " and "; contentText += " " + newNovel + " new novel(s)"; } contentText += "."; Intent notificationIntent = new Intent(this, MainTabActivity.class); notificationIntent.putExtra(Constants.EXTRA_CALLER_ACTIVITY, UpdateService.class.toString()); int pendingFlag = PendingIntent.FLAG_CANCEL_CURRENT; PendingIntent contentIntent = PendingIntent.getActivity(this, Constants.CONSOLIDATED_NOTIFIER_ID, notificationIntent, pendingFlag); notification.setLatestEventInfo(this, contentTitle, contentText, contentIntent); mNotificationManager.notify(Constants.CONSOLIDATED_NOTIFIER_ID, notification); } @SuppressWarnings("deprecation") public void prepareNotification(final int notifId, UpdateInfoModel chapter, Notification notification) { CharSequence contentTitle = chapter.getUpdateType().toString(); CharSequence contentText = chapter.getUpdateTitle(); Intent notificationIntent = new Intent(this, MainTabActivity.class); notificationIntent.putExtra(Constants.EXTRA_PAGE, chapter.getUpdatePage()); int pendingFlag = PendingIntent.FLAG_CANCEL_CURRENT; PendingIntent contentIntent = PendingIntent.getActivity(this, notifId, notificationIntent, pendingFlag); notification.setLatestEventInfo(this, contentTitle, contentText, contentIntent); } @SuppressWarnings("deprecation") public Notification getNotificationTemplate(boolean firstNotification) { int icon = android.R.drawable.arrow_up_float; // Just a placeholder CharSequence tickerText = "New Chapters Update"; long when = System.currentTimeMillis(); Notification notification = new Notification(icon, tickerText, when); if (!PreferenceManager.getDefaultSharedPreferences(this).getBoolean(Constants.PREF_PERSIST_NOTIFICATION, false)) { notification.flags = Notification.FLAG_AUTO_CANCEL; } notification.defaults = 0; if (firstNotification) { if (PreferenceManager.getDefaultSharedPreferences(this).getBoolean(Constants.PREF_UPDATE_RING, false)) { notification.defaults |= Notification.DEFAULT_SOUND; } if (PreferenceManager.getDefaultSharedPreferences(this).getBoolean(Constants.PREF_UPDATE_VIBRATE, false)) { notification.defaults |= Notification.DEFAULT_VIBRATE; } } return notification; } public void updateStatus(String status) { SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(this); SharedPreferences.Editor editor = sharedPrefs.edit(); String date = new Date().toString(); editor.putString(Constants.PREF_RUN_UPDATES, date); editor.putString(Constants.PREF_RUN_UPDATES_STATUS, status); editor.commit(); if (notifier != null) notifier.onCallback(new CallbackEventData("Last Run: " + date + "\nStatus: " + status)); } private boolean getConsolidateNotificationPref() { return PreferenceManager.getDefaultSharedPreferences(this).getBoolean(Constants.PREF_CONSOLIDATE_NOTIFICATION, true); } private boolean shouldRun(boolean forced) { if (forced) { Log.i(TAG, "Forced run"); return true; } SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this); String updatesIntervalStr = preferences.getString(Constants.PREF_UPDATE_INTERVAL, "0"); if (!updatesIntervalStr.equalsIgnoreCase("0")) { long lastUpdate = preferences.getLong(Constants.PREF_LAST_UPDATE, 0); Date nowDate = new Date(); long now = nowDate.getTime(); if (updatesIntervalStr.equalsIgnoreCase("1")) { lastUpdate += 15 * 60 * 1000; } else if (updatesIntervalStr.equalsIgnoreCase("2")) { lastUpdate += 30 * 60 * 1000; } else if (updatesIntervalStr.equalsIgnoreCase("3")) { lastUpdate += 60 * 60 * 1000; } else if (updatesIntervalStr.equalsIgnoreCase("4")) { lastUpdate += 12 * 60 * 60 * 1000; } else if (updatesIntervalStr.equalsIgnoreCase("5")) { lastUpdate += 24 * 60 * 60 * 1000; } Date lastUpdateDate = new Date(lastUpdate); if (lastUpdate <= now) { Log.e(TAG, "Updating: " + lastUpdateDate.toLocaleString() + " <= " + nowDate.toLocaleString()); return true; } Log.i(TAG, "Next Update: " + lastUpdateDate.toLocaleString() + ", Now: " + nowDate.toLocaleString()); return false; } else { Log.i(TAG, "Update Interval set to Never."); return false; } } public void setRunning(boolean isRunning) { UpdateService.isRunning = isRunning; } public void setForce(boolean isForced) { this.force = isForced; } public boolean isForced() { return force; } }