/*
* Copyright(c) 2017 lizhaotailang
*
* 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 io.github.marktony.espresso.service;
import android.app.IntentService;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.media.RingtoneManager;
import android.os.IBinder;
import android.support.annotation.Nullable;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.NotificationCompat;
import android.support.v7.preference.PreferenceManager;
import android.util.Log;
import java.util.Calendar;
import java.util.List;
import io.github.marktony.espresso.R;
import io.github.marktony.espresso.appwidget.AppWidgetProvider;
import io.github.marktony.espresso.data.Package;
import io.github.marktony.espresso.mvp.packagedetails.PackageDetailsActivity;
import io.github.marktony.espresso.realm.RealmHelper;
import io.github.marktony.espresso.retrofit.RetrofitClient;
import io.github.marktony.espresso.retrofit.RetrofitService;
import io.github.marktony.espresso.util.NetworkUtil;
import io.github.marktony.espresso.util.PushUtil;
import io.github.marktony.espresso.util.SettingsUtil;
import io.reactivex.disposables.CompositeDisposable;
import io.reactivex.functions.Consumer;
import io.reactivex.schedulers.Schedulers;
import io.realm.Realm;
/**
* Created by lizhaotailang on 2017/3/8.
* Background service to build notifications and send them to user.
*/
public class ReminderService extends IntentService {
private SharedPreferences preference;
private CompositeDisposable compositeDisposable;
public static final String TAG = ReminderService.class.getSimpleName();
/**
* Creates an IntentService. Invoked by your subclass's constructor.
*/
public ReminderService() {
super(TAG);
}
@Override
public void onCreate() {
super.onCreate();
preference = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
compositeDisposable = new CompositeDisposable();
Log.d(TAG, "onCreate: ");
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
protected void onHandleIntent(@Nullable Intent intent) {
Log.d(TAG, "onHandleIntent: ");
boolean isDisturbMode = preference.getBoolean(SettingsUtil.KEY_DO_NOT_DISTURB_MODE, true);
// The alert mode is off
// or DO-NOT-DISTURB-MODE is off
// or time now is not in the DO-NOT-DISTURB-MODE range.
if (isDisturbMode && PushUtil.isInDisturbTime(this, Calendar.getInstance())) {
return;
}
Realm rlm = RealmHelper.newRealmInstance();
List<Package> results = rlm.copyFromRealm(
rlm.where(Package.class)
.notEqualTo("state", String.valueOf(Package.STATUS_DELIVERED))
.findAll());
for (int i = 0; i < results.size(); i++){
Package p = results.get(i);
// Avoid repeated pushing
if (p.isPushable()) {
Realm realm = RealmHelper.newRealmInstance();
p.setPushable(false);
pushNotification(i + 1001, setNotifications(i, p));
realm.beginTransaction();
realm.copyToRealmOrUpdate(p);
realm.commitTransaction();
realm.close();
} else if (NetworkUtil.networkConnected(getApplicationContext())) {
refreshPackage(i, results.get(i));
}
}
rlm.close();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d(TAG, "onStartCommand: ");
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
super.onDestroy();
compositeDisposable.clear();
Log.d(TAG, "onDestroy: ");
}
private static Notification buildNotification(Context context, String title, String subject, String longText, String time, int icon, int color,
PendingIntent contentIntent, PendingIntent deleteIntent) {
NotificationCompat.Builder builder = new NotificationCompat.Builder(context);
builder.setContentTitle(title);
builder.setContentText(subject);
builder.setPriority(NotificationCompat.PRIORITY_MAX);
builder.setStyle(new NotificationCompat.BigTextStyle(builder).bigText(longText));
builder.setSmallIcon(icon);
builder.setShowWhen(true);
builder.setWhen(System.currentTimeMillis());
builder.setContentIntent(contentIntent);
builder.setSubText(time);
builder.setAutoCancel(true);
builder.setColor(color);
return builder.build();
}
/**
* Set the details like title, subject, etc. of notifications.
* @param position Position.
* @param pkg The package.
* @return The notification.
*/
private Notification setNotifications(int position, Package pkg) {
if (pkg != null) {
Intent i = new Intent(getApplicationContext(), PackageDetailsActivity.class);
i.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
i.putExtra(PackageDetailsActivity.PACKAGE_ID, pkg.getNumber());
PendingIntent intent = PendingIntent.getActivity(getApplicationContext(), position, i, PendingIntent.FLAG_UPDATE_CURRENT);
String title = pkg.getName();
String subject;
int smallIcon = R.drawable.ic_local_shipping_teal_24dp;
if (Integer.parseInt(pkg.getState()) == Package.STATUS_DELIVERED) {
subject = getString(R.string.delivered);
smallIcon = R.drawable.ic_assignment_turned_in_teal_24dp;
} else {
if (Integer.parseInt(pkg.getState()) == Package.STATUS_ON_THE_WAY) {
subject = getString(R.string.on_the_way);
} else {
subject = getString(R.string.notification_new_message);
}
}
Notification notification = buildNotification(getApplicationContext(),
title,
subject,
pkg.getData().get(0).getContext(),
pkg.getData().get(0).getTime(),
smallIcon,
ContextCompat.getColor(getApplicationContext(), R.color.colorPrimary),
intent,
null);
notification.sound = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
notification.tickerText = title;
return notification;
}
return null;
}
/**
* Update the package by accessing network,
* then build and send the notifications.
* @param position Position.
* @param p The package.
*/
private void refreshPackage(final int position, final Package p) {
Log.d(TAG, "refreshPackage: ");
RetrofitClient.getInstance()
.create(RetrofitService.class)
.getPackageState(p.getCompany(), p.getNumber())
.subscribeOn(Schedulers.io())
.doOnNext(new Consumer<Package>() {
@Override
public void accept(Package aPackage) throws Exception {
if (aPackage != null && aPackage.getData().size() > p.getData().size()) {
Realm rlm = RealmHelper.newRealmInstance();
p.setReadable(true);
p.setPushable(false);
p.setData(aPackage.getData());
p.setState(aPackage.getState());
rlm.beginTransaction();
rlm.copyToRealmOrUpdate(p);
rlm.commitTransaction();
rlm.close();
// Send notification
pushNotification(position + 1000, setNotifications(position, p));
// Update the widget
sendBroadcast(AppWidgetProvider.getRefreshBroadcastIntent(getApplicationContext()));
}
}
})
.subscribe();
}
private void pushNotification(int i, Notification n) {
NotificationManager nm = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
nm.notify(i, n);
}
}