/** * Copyright (C) 2013 - 2015 the enviroCar community * <p> * This file is part of the enviroCar app. * <p> * The enviroCar app is free software: you can redistribute it and/or * modify it under the terms of the GNU General Public License as published * by the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * <p> * The enviroCar app is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General * Public License for more details. * <p> * You should have received a copy of the GNU General Public License along * with the enviroCar app. If not, see http://www.gnu.org/licenses/. */ package org.envirocar.app.services; 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.graphics.Bitmap; import android.graphics.BitmapFactory; import android.os.IBinder; import android.support.annotation.Nullable; import android.support.v4.app.NotificationCompat; import android.support.v4.app.TaskStackBuilder; import android.widget.RemoteViews; import org.envirocar.app.BaseMainActivity; import org.envirocar.app.R; import org.envirocar.app.handler.TrackRecordingHandler; import org.envirocar.app.handler.TrackUploadHandler; import org.envirocar.core.entity.Track; import org.envirocar.core.injection.Injector; import org.envirocar.core.logging.Logger; import org.envirocar.storage.EnviroCarDB; import java.util.List; import javax.inject.Inject; import rx.Observable; import rx.Subscriber; import rx.android.schedulers.AndroidSchedulers; import rx.schedulers.Schedulers; /** * TODO JavaDoc * * @author dewall */ public class TrackUploadService extends Service { private static final Logger LOG = Logger.getLogger(TrackUploadService.class); private static final int NOTIFICATION_ID = 52; @Inject protected TrackRecordingHandler trackRecordingHandler; @Inject protected EnviroCarDB enviroCarDB; @Inject protected TrackUploadHandler trackUploadHandler; @Override public void onCreate() { LOG.debug("onCreate()"); super.onCreate(); // Inject the OBDServiceHandler; ((Injector) getApplicationContext()).injectObjects(this); } @Override public int onStartCommand(Intent intent, int flags, int startId) { LOG.info("onStartCommand()"); // TODO change it to clean u List<Track> localTrackList = enviroCarDB.getAllLocalTracks().first().toBlocking().first(); if (localTrackList.size() > 0) { LOG.info(String.format("%s local tracks to upload", localTrackList.size())); // setNotification("yeae", "oiad"); uploadAllLocalTracks(); } else { LOG.info("No local tracks to upload"); // setNotification("yeae", "oiad"); try { finalize(); } catch (Throwable throwable) { throwable.printStackTrace(); } } return START_NOT_STICKY; } @Override public void onDestroy() { super.onDestroy(); } @Nullable @Override public IBinder onBind(Intent intent) { return null; } private void uploadAllLocalTracks() { Observable.defer(() -> enviroCarDB.getAllLocalTracks()) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .first() .concatMap(tracks -> getUploadWithNotificationObservable(tracks)) .subscribe(new Subscriber<Track>() { @Override public void onStart() { LOG.info("onStart()"); } @Override public void onCompleted() { LOG.info("onCompleted()"); } @Override public void onError(Throwable e) { LOG.warn(e.getMessage(), e); } @Override public void onNext(Track track) { LOG.info("Track has been successfully uploaded -> " + track.getRemoteID()); } }); } private Observable<Track> getUploadWithNotificationObservable(final List<Track> tracks) { return Observable.create(new Observable.OnSubscribe<Track>() { private RemoteViews smallView; private RemoteViews bigView; private Notification foregroundNotification; private NotificationManager notificationManager; private int numberOfTracks = tracks.size(); private int numberOfSuccesses = 0; private int numberOfFailures = 0; @Override public void call(Subscriber<? super Track> subscriber) { subscriber.add(trackUploadHandler.uploadTracksObservable(tracks, false) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(new Subscriber<Track>() { @Override public void onStart() { subscriber.onStart(); foregroundNotification = new NotificationCompat .Builder(getApplicationContext()) .setSmallIcon(R.drawable.ic_cloud_upload_white_24dp) .setContentTitle( getString(R.string.notification_automatic_track_upload_title)) .setPriority(Integer.MAX_VALUE) .build(); smallView = new RemoteViews(getPackageName(), R.layout.service_track_upload_handler_notification_small); bigView = new RemoteViews(getPackageName(), R.layout.service_track_upload_handler_notification); foregroundNotification.bigContentView = bigView; setSmallViewText( getString(R.string .notification_automatic_track_upload_title), getString(R.string. notification_slide_down)); setBigViewText( getString(R.string. notification_automatic_track_upload_title), getString(R.string. notification_automatic_track_upload_success_sub) ); notificationManager = (NotificationManager) getSystemService(Context .NOTIFICATION_SERVICE); updateProgress(); } @Override public void onCompleted() { LOG.info("getUploadWithNotificationObservable.onCompleted()"); subscriber.onCompleted(); setSmallViewText( getString(R.string. notification_automatic_track_upload_success), getString(R.string. notification_automatic_track_upload_success_sub, numberOfSuccesses, numberOfTracks)); foregroundNotification = new NotificationCompat .Builder(getApplicationContext()) .setSmallIcon(R.drawable.ic_cloud_upload_white_24dp) .setContentTitle( getString(R.string.notification_automatic_track_upload_title)) .setContent(smallView) .build(); notificationManager.notify(100, foregroundNotification); } @Override public void onError(Throwable e) { subscriber.onError(e); setSmallViewText( getString(R.string. notification_automatic_track_upload_error), getString(R.string. notification_automatic_track_upload_error_sub)); foregroundNotification = new NotificationCompat .Builder(getApplicationContext()) .setSmallIcon(R.drawable.ic_error_outline_white_24dp) .setContentTitle("Track Upload Error") .setContent(smallView) .build(); notificationManager.notify(100, foregroundNotification); } @Override public void onNext(Track track) { if (track == null) { LOG.info("track had to less measurements"); numberOfFailures++; } else { subscriber.onNext(track); numberOfSuccesses++; } updateProgress(); } private void updateProgress() { int totalNumber = numberOfFailures + numberOfSuccesses; bigView.setProgressBar( R.id.service_track_upload_handler_notification_progressbar, numberOfTracks, numberOfFailures + numberOfSuccesses, false); bigView.setTextViewText( R.id.service_track_upload_handler_notification_total, String.format("%s / %s", totalNumber, numberOfTracks)); bigView.setTextViewText( R.id.service_track_upload_handler_notification_percentage, "" + ((numberOfFailures + numberOfSuccesses) / numberOfTracks) * 100); notificationManager.notify(100, foregroundNotification); } private void setSmallViewText(String title, String content) { smallView.setTextViewText( R.id.service_track_upload_handler_notification_small_title, title); smallView.setTextViewText( R.id.service_track_upload_handler_notification_small_content, content); } private void setBigViewText(String title, String content) { bigView.setTextViewText( R.id.service_track_upload_handler_notification_text, title); bigView.setTextViewText( R.id.service_track_upload_handler_notification_sub_text, content); } })); } }); } private void setNotification(String title, String notification) { RemoteViews bigView = new RemoteViews(getPackageName(), R.layout .service_track_upload_handler_notification); RemoteViews smallView = new RemoteViews(getPackageName(), R.layout .service_track_upload_handler_notification_small); Bitmap bm = BitmapFactory.decodeResource(getResources(), R.drawable.home_icon); Notification forgroundNotification = new NotificationCompat.Builder(this) .setSmallIcon(R.drawable.ic_cloud_upload_white_24dp) .setContentTitle(title) .setContent(smallView) // .setAutoCancel(false) .setPriority(Integer.MAX_VALUE) // .setOngoing(true) // .setLargeIcon(bm) .build(); forgroundNotification.bigContentView = bigView; Intent intent = new Intent(getBaseContext(), BaseMainActivity.class); TaskStackBuilder stackBuilder = TaskStackBuilder.create(this); stackBuilder.addParentStack(BaseMainActivity.class); stackBuilder.addNextIntent(intent); PendingIntent resultIntent = stackBuilder.getPendingIntent(0, PendingIntent .FLAG_UPDATE_CURRENT); NotificationManager notificationManager = (NotificationManager) getSystemService(Context .NOTIFICATION_SERVICE); notificationManager.notify(100, forgroundNotification); } }