package com.erakk.lnreader.service;
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.AsyncTask;
import android.os.Binder;
import android.os.Build;
import android.os.IBinder;
import android.preference.PreferenceManager;
import android.support.v4.app.NotificationCompat;
import android.util.Log;
import android.widget.Toast;
import com.erakk.lnreader.Constants;
import com.erakk.lnreader.LNReaderApplication;
import com.erakk.lnreader.R;
import com.erakk.lnreader.UI.activity.DisplayLightNovelContentActivity;
import com.erakk.lnreader.UI.activity.MainActivity;
import com.erakk.lnreader.UI.fragment.UpdateInfoFragment;
import com.erakk.lnreader.UIHelper;
import com.erakk.lnreader.callback.CallbackEventData;
import com.erakk.lnreader.callback.IExtendedCallbackNotifier;
import com.erakk.lnreader.dao.NovelsDao;
import com.erakk.lnreader.helper.Util;
import com.erakk.lnreader.model.PageModel;
import com.erakk.lnreader.model.UpdateInfoModel;
import com.erakk.lnreader.model.UpdateTypeEnum;
import com.erakk.lnreader.task.AsyncTaskResult;
import com.erakk.lnreader.task.GetUpdatedChaptersTask;
import java.util.ArrayList;
import java.util.Date;
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;
private IExtendedCallbackNotifier<AsyncTaskResult<?>> notifier;
private GetUpdatedChaptersTask task;
@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
UpdateScheduleReceiver.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();
task = new GetUpdatedChaptersTask(this, GetAutoDownloadUpdatedChapterPreferences(), notifier);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB)
task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
else
task.execute();
}
}
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 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.onProgressCallback(new CallbackEventData(getString(R.string.svc_update_status, date, status), Constants.PREF_RUN_UPDATES));
}
private boolean getConsolidateNotificationPref() {
return PreferenceManager.getDefaultSharedPreferences(this).getBoolean(Constants.PREF_CONSOLIDATE_NOTIFICATION, true);
}
@SuppressWarnings("deprecation")
private boolean shouldRun(boolean forced) {
if (forced) {
Log.i(TAG, "Forced run");
return true;
} else {
// check wifi only preferences
if (UIHelper.isAutoUpdateOnlyUseWifi(this) && !Util.isWifiConnected()) {
Log.i(TAG, "Wifi is not connected!");
return false;
} else {
Log.i(TAG, "Wifi available.");
}
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();
lastUpdate += GetUpdateInterval(updatesIntervalStr);
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 static long GetUpdateInterval(String updatesIntervalStr) {
long interval = 0;
if (updatesIntervalStr.equalsIgnoreCase("1")) {
interval = 6 * 60 * 60 * 1000;
} else if (updatesIntervalStr.equalsIgnoreCase("2")) {
interval = 12 * 60 * 60 * 1000;
} else if (updatesIntervalStr.equalsIgnoreCase("3")) {
interval = 24 * 60 * 60 * 1000;
} else if (updatesIntervalStr.equalsIgnoreCase("4")) {
interval = 2 * 24 * 60 * 60 * 1000;
} else if (updatesIntervalStr.equalsIgnoreCase("5")) {
interval = 7 * 24 * 60 * 60 * 1000;
}
return interval;
}
public void cancelUpdate() {
if (task != null) {
task.cancel(true);
}
}
public void setRunning(boolean isRunning) {
UpdateService.isRunning = isRunning;
}
public void setForce(boolean isForced) {
this.force = isForced;
}
public boolean isForced() {
return force;
}
public void setOnCallbackNotifier(IExtendedCallbackNotifier<AsyncTaskResult<?>> notifier) {
this.notifier = notifier;
if (task != null)
task.setCallbackNotifier(notifier);
}
public void sendNotification(ArrayList<PageModel> updatedChapters) {
NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
if (updatedChapters != null && updatedChapters.size() > 0) {
Log.d(TAG, "sendNotification");
// 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(UpdateTypeEnum.NewNovel);
} else if (pageModel.getType().equalsIgnoreCase(PageModel.TYPE_TOS)) {
updateInfo.setUpdateTitle("Updated TOS");
updateInfo.setUpdateType(UpdateTypeEnum.UpdateTos);
} else {
if (pageModel.isUpdated()) {
updateInfo.setUpdateType(UpdateTypeEnum.Updated);
++updateCount;
} else {
updateInfo.setUpdateType(UpdateTypeEnum.New);
++newCount;
}
String novelTitle = "";
try {
novelTitle = pageModel.getBook(true).getParent().getPageModel().getTitle() + ": ";
} catch (Exception ex) {
Log.e(TAG, "Error when getting Novel title", ex);
}
novelTitle = novelTitle + pageModel.getTitle() + " (" + pageModel.getBook(true).getTitle() + ")";
if (pageModel.isExternal()) {
// double check
if (pageModel.getPage().startsWith("http://") || pageModel.getPage().startsWith("https://")) {
novelTitle += " - EXTERNAL LINK";
updateInfo.setExternal(true);
}
}
updateInfo.setUpdateTitle(novelTitle);
}
updateInfo.setUpdateDate(pageModel.getLastUpdate());
updateInfo.setUpdatePage(pageModel.getPage());
updateInfo.setUpdatePageModel(pageModel);
// insert to db
NovelsDao.getInstance().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());
NotificationCompat.Builder mBuilder = getNotificationTemplate(first);
first = false;
prepareNotification(notifId, updateInfoModel, mBuilder);
mNotificationManager.notify(notifId, mBuilder.build());
}
}
}
updateStatus("OK");
Toast.makeText(this, "Update Service completed", Toast.LENGTH_SHORT).show();
LNReaderApplication.getInstance().updateDownload(TAG, 100, getString(R.string.svc_update_complete));
if (notifier != null)
notifier.onProgressCallback(new CallbackEventData(getString(R.string.svc_update_complete), 100, Constants.PREF_RUN_UPDATES));
}
private void prepareNotification(final int notifId, UpdateInfoModel chapter, NotificationCompat.Builder mBuilder) {
CharSequence contentTitle = chapter.getUpdateType().toString();
CharSequence contentText = chapter.getUpdateTitle();
Intent notificationIntent = new Intent(this, DisplayLightNovelContentActivity.class);
notificationIntent.putExtra(Constants.EXTRA_PAGE, chapter.getUpdatePage());
int pendingFlag = PendingIntent.FLAG_CANCEL_CURRENT;
PendingIntent contentIntent = PendingIntent.getActivity(this, notifId, notificationIntent, pendingFlag);
mBuilder.setContentTitle(contentTitle)
.setContentText(contentText)
.setContentIntent(contentIntent);
}
private void createConsolidatedNotification(NotificationManager mNotificationManager, int updateCount, int newCount, int newNovel) {
Log.d(TAG, "set consolidated Notification");
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, MainActivity.class);
notificationIntent.putExtra(Constants.EXTRA_INITIAL_FRAGMENT, UpdateInfoFragment.class.toString());
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);
NotificationCompat.Builder mBuilder = getNotificationTemplate(true);
mBuilder.setContentTitle(contentTitle)
.setContentText(contentText)
.setContentIntent(contentIntent);
mNotificationManager.notify(Constants.CONSOLIDATED_NOTIFIER_ID, mBuilder.build());
}
private NotificationCompat.Builder getNotificationTemplate(boolean firstNotification) {
int icon = android.R.drawable.arrow_up_float; // Just a placeholder
CharSequence tickerText = "New Chapters Update";
boolean persist = !PreferenceManager.getDefaultSharedPreferences(this).getBoolean(Constants.PREF_PERSIST_NOTIFICATION, false);
int def = 0;
if (firstNotification) {
if (PreferenceManager.getDefaultSharedPreferences(this).getBoolean(Constants.PREF_UPDATE_RING, false)) {
def |= Notification.DEFAULT_SOUND;
}
if (PreferenceManager.getDefaultSharedPreferences(this).getBoolean(Constants.PREF_UPDATE_VIBRATE, false)) {
def |= Notification.DEFAULT_VIBRATE;
}
}
NotificationCompat.Builder mBuilder =
new NotificationCompat.Builder(this)
.setSmallIcon(icon)
.setWhen(System.currentTimeMillis())
.setTicker(tickerText)
.setDefaults(def)
.setAutoCancel(persist);
return mBuilder;
}
}