package com.florianmski.tracktoid.services; import android.app.IntentService; import android.app.NotificationManager; import android.app.PendingIntent; import android.content.Context; import android.content.Intent; import android.support.v4.app.NotificationCompat; import com.florianmski.tracktoid.R; import com.florianmski.tracktoid.TraktoidConstants; import com.florianmski.tracktoid.TraktoidTheme; import com.florianmski.tracktoid.data.database.columns.SyncColumns; import com.florianmski.tracktoid.rx.observables.TraktObservable; import com.florianmski.tracktoid.trakt.TraktManager; import com.florianmski.tracktoid.utils.CVHelper; import com.florianmski.tracktoid.utils.DateHelper; import com.florianmski.tracktoid.utils.DbHelper; import com.uwetrottmann.trakt.v2.exceptions.CheckinInProgressException; import com.uwetrottmann.trakt.v2.exceptions.OAuthUnauthorizedException; import java.util.concurrent.TimeUnit; import retrofit.client.Response; import rx.Observable; import rx.Subscriber; import rx.Subscription; import rx.functions.Action0; import rx.functions.Func1; import timber.log.Timber; public class CheckinService extends IntentService { private final static int NOTIFICATION_ID = 1337; private final static String BUNDLE_CHECKIN = "checkin"; private final static String BUNDLE_DURATION = "duration"; private final static int BUNDLE_STOP_CHECKIN = 0; private final static int BUNDLE_CHECKIN_EPISODE = 1; private final static int BUNDLE_CHECKIN_MOVIE = 2; private static Subscription subscription; private NotificationManager notificationManager; private NotificationCompat.Builder notificationBuilder; public CheckinService() { super("CheckinService"); } @Override protected void onHandleIntent(Intent intent) { int checkin = intent.getExtras().getInt(BUNDLE_CHECKIN); notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); if(checkin == BUNDLE_STOP_CHECKIN) { if(subscription != null) subscription.unsubscribe(); } else { final int id = intent.getExtras().getInt(TraktoidConstants.BUNDLE_ID); final String title = intent.getExtras().getString(TraktoidConstants.BUNDLE_TITLE); final int duration = intent.getExtras().getInt(BUNDLE_DURATION); Intent i = new Intent(this, CheckinService.class); i.putExtra(BUNDLE_CHECKIN, BUNDLE_STOP_CHECKIN); PendingIntent pendingIntent = PendingIntent.getService(this, 0, i, 0); notificationBuilder = new NotificationCompat.Builder(this) .setContentTitle(String.format("Watching %s", title)) .setColor(TraktoidTheme.DEFAULT.getColorDark(this)) .setSmallIcon(R.drawable.ic_check_white_24dp) .setOngoing(true) .addAction(new NotificationCompat.Action(R.drawable.ic_clear_white_24dp, "Cancel", pendingIntent)); startTimer(checkin, id, duration); } } private void startTimer(final int checkin, final int id, int duration) { subscription = Observable .interval((duration * 60) / 100, TimeUnit.SECONDS) .takeWhile(new Func1<Long, Boolean>() { @Override public Boolean call(Long tick) { return tick < 100; } }) .doOnSubscribe(new Action0() { @Override public void call() { updateProgress(0); } }) .doOnUnsubscribe(new Action0() { @Override public void call() { cancelCheckin(); } }) .subscribe(new Subscriber<Long>() { @Override public void onCompleted() { cancelNotification(); // mark as seen in db CVHelper cv = new CVHelper() .put(SyncColumns.WATCHED, true) .put(SyncColumns.LAST_WATCHED_AT, DateHelper.now()); if(checkin == BUNDLE_CHECKIN_MOVIE) DbHelper.updateMovie(CheckinService.this, cv.get(), String.valueOf(id)); else if(checkin == BUNDLE_CHECKIN_EPISODE) DbHelper.updateEpisode(CheckinService.this, cv.get(), String.valueOf(id)); } @Override public void onError(Throwable e) { cancelNotification(); Timber.i("Error during checkin", e); } @Override public void onNext(Long ticks) { updateProgress(ticks.intValue()+1); } }); } private void cancelNotification() { notificationManager.cancel(NOTIFICATION_ID); subscription = null; } private void cancelCheckin() { Observable.create(new TraktObservable<Response>() { @Override public Response fire() throws OAuthUnauthorizedException, CheckinInProgressException { return TraktManager.getInstance().checkin().deleteActiveCheckin(); } }).doOnCompleted(new Action0() { @Override public void call() { cancelNotification(); } }).subscribe(); } private void updateProgress(int progress) { notificationBuilder .setProgress(100, progress, false) .setContentText(String.format("%d%%", progress)); updateNotification(); } private void updateNotification() { notificationManager.notify(NOTIFICATION_ID, notificationBuilder.build()); } public static void checkinEpisode(Context context, int id, String title, int duration) { checkin(context, BUNDLE_CHECKIN_EPISODE, id, title, duration); } public static void checkinMovie(Context context, int id, String title, int duration) { checkin(context, BUNDLE_CHECKIN_MOVIE, id, title, duration); } private static void checkin(Context context, int checkin, int id, String title, int duration) { Intent i = new Intent(context, CheckinService.class); i.putExtra(BUNDLE_CHECKIN, checkin); i.putExtra(TraktoidConstants.BUNDLE_ID, id); i.putExtra(TraktoidConstants.BUNDLE_TITLE, title); i.putExtra(BUNDLE_DURATION, duration); context.startService(i); } public static void stopCheckin(Context context) { Intent i = new Intent(context, CheckinService.class); i.putExtra(BUNDLE_CHECKIN, BUNDLE_STOP_CHECKIN); context.startService(i); } public static boolean isCheckinInProgress() { return subscription != null; } @Override public void onTaskRemoved(Intent rootIntent) { super.onTaskRemoved(rootIntent); // clean notification if app is killed NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); notificationManager.cancel(NOTIFICATION_ID); } }