PersistenNotificationPlugin, services
This commit is contained in:
parent
45afd5ec34
commit
4dbf199685
22 changed files with 593 additions and 739 deletions
|
@ -230,6 +230,7 @@ dependencies {
|
|||
|
||||
implementation fileTree(include: ['*.jar'], dir: 'libs')
|
||||
implementation 'com.google.android.gms:play-services-wearable:17.0.0'
|
||||
implementation "com.google.android.gms:play-services-location:17.0.0"
|
||||
implementation 'com.google.firebase:firebase-core:17.2.1'
|
||||
implementation 'com.google.firebase:firebase-auth:19.2.0'
|
||||
implementation 'com.google.firebase:firebase-database:19.2.0'
|
||||
|
|
|
@ -307,7 +307,7 @@ public class MainActivity extends NoSplashAppCompatActivity {
|
|||
case R.id.nav_about:
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(this);
|
||||
builder.setTitle(resourceHelper.gs(R.string.app_name) + " " + BuildConfig.VERSION);
|
||||
builder.setIcon(MainApp.getIcon());
|
||||
builder.setIcon(resourceHelper.getIcon());
|
||||
String message = "Build: " + BuildConfig.BUILDVERSION + "\n";
|
||||
message += "Flavor: " + BuildConfig.FLAVOR + BuildConfig.BUILD_TYPE + "\n";
|
||||
message += resourceHelper.gs(R.string.configbuilder_nightscoutversion_label) + " " + nsSettingsStatus.getNightscoutVersionName();
|
||||
|
|
|
@ -108,7 +108,7 @@ public class MainApp extends DaggerApplication {
|
|||
static Logger log = LoggerFactory.getLogger(L.CORE);
|
||||
|
||||
static MainApp sInstance;
|
||||
public static Resources sResources;
|
||||
private static Resources sResources;
|
||||
|
||||
static FirebaseAnalytics mFirebaseAnalytics;
|
||||
|
||||
|
@ -147,6 +147,7 @@ public class MainApp extends DaggerApplication {
|
|||
@Inject OpenAPSAMAPlugin openAPSAMAPlugin;
|
||||
@Inject OpenAPSSMBPlugin openAPSSMBPlugin;
|
||||
@Inject OverviewPlugin overviewPlugin;
|
||||
@Inject PersistentNotificationPlugin persistentNotificationPlugin;
|
||||
@Inject RandomBgPlugin randomBgPlugin;
|
||||
@Inject DexcomPlugin dexcomPlugin;
|
||||
@Inject EversensePlugin eversensePlugin;
|
||||
|
@ -263,7 +264,7 @@ public class MainApp extends DaggerApplication {
|
|||
|
||||
pluginsList.add(wearPlugin);
|
||||
pluginsList.add(statusLinePlugin);
|
||||
pluginsList.add(PersistentNotificationPlugin.getPlugin());
|
||||
pluginsList.add(persistentNotificationPlugin);
|
||||
pluginsList.add(NSClientPlugin.getPlugin());
|
||||
// if (engineeringMode) pluginsList.add(tidepoolPlugin);
|
||||
pluginsList.add(maintenancePlugin);
|
||||
|
@ -357,6 +358,11 @@ public class MainApp extends DaggerApplication {
|
|||
return ContextCompat.getColor(instance(), id);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static Resources resources() {
|
||||
return sResources;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static MainApp instance() {
|
||||
return sInstance;
|
||||
|
@ -442,24 +448,6 @@ public class MainApp extends DaggerApplication {
|
|||
return devBranch;
|
||||
}
|
||||
|
||||
public static int getIcon() {
|
||||
if (Config.NSCLIENT)
|
||||
return R.mipmap.ic_yellowowl;
|
||||
else if (Config.PUMPCONTROL)
|
||||
return R.mipmap.ic_pumpcontrol;
|
||||
else
|
||||
return R.mipmap.ic_launcher;
|
||||
}
|
||||
|
||||
public static int getNotificationIcon() {
|
||||
if (Config.NSCLIENT)
|
||||
return R.drawable.ic_notif_nsclient;
|
||||
else if (Config.PUMPCONTROL)
|
||||
return R.drawable.ic_notif_pumpcontrol;
|
||||
else
|
||||
return R.drawable.ic_notif_aaps;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTerminate() {
|
||||
|
||||
|
@ -472,6 +460,7 @@ public class MainApp extends DaggerApplication {
|
|||
super.onTerminate();
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static int dpToPx(int dp) {
|
||||
float scale = sResources.getDisplayMetrics().density;
|
||||
return (int) (dp * scale + 0.5f);
|
||||
|
|
|
@ -260,7 +260,7 @@ public class CareportalEvent implements DataPointWithLabelInterface, Interval {
|
|||
|
||||
@Override
|
||||
public float getSize() {
|
||||
boolean isTablet = MainApp.sResources.getBoolean(R.bool.isTablet);
|
||||
boolean isTablet = MainApp.resources().getBoolean(R.bool.isTablet);
|
||||
return isTablet ? 12 : 10;
|
||||
}
|
||||
|
||||
|
|
|
@ -3,12 +3,18 @@ package info.nightscout.androidaps.dependencyInjection
|
|||
import dagger.Module
|
||||
import dagger.android.ContributesAndroidInjector
|
||||
import info.nightscout.androidaps.plugins.general.nsclient.services.NSClientService
|
||||
import info.nightscout.androidaps.plugins.general.persistentNotification.DummyService
|
||||
import info.nightscout.androidaps.services.AlarmSoundService
|
||||
import info.nightscout.androidaps.services.DataService
|
||||
import info.nightscout.androidaps.services.LocationService
|
||||
|
||||
@Module
|
||||
@Suppress("unused")
|
||||
abstract class ServicesModule {
|
||||
|
||||
@ContributesAndroidInjector abstract fun contributesAlarmSoundService(): AlarmSoundService
|
||||
@ContributesAndroidInjector abstract fun contributesDataService(): DataService
|
||||
@ContributesAndroidInjector abstract fun contributesDummyService(): DummyService
|
||||
@ContributesAndroidInjector abstract fun contributesLocationService(): LocationService
|
||||
@ContributesAndroidInjector abstract fun contributesNSClientService(): NSClientService
|
||||
}
|
|
@ -19,7 +19,6 @@ import androidx.recyclerview.widget.ItemTouchHelper
|
|||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import dagger.android.support.DaggerFragment
|
||||
import info.nightscout.androidaps.MainApp
|
||||
import info.nightscout.androidaps.R
|
||||
import info.nightscout.androidaps.plugins.bus.RxBusWrapper
|
||||
import info.nightscout.androidaps.plugins.general.automation.dialogs.EditEventDialog
|
||||
|
@ -129,7 +128,7 @@ class AutomationFragment : DaggerFragment(), OnStartDragListener {
|
|||
private fun addImage(@DrawableRes res: Int, context: Context, layout: LinearLayout) {
|
||||
val iv = ImageView(context)
|
||||
iv.setImageResource(res)
|
||||
iv.layoutParams = LinearLayout.LayoutParams(MainApp.dpToPx(24), MainApp.dpToPx(24))
|
||||
iv.layoutParams = LinearLayout.LayoutParams(resourceHelper.dpToPx(24), resourceHelper.dpToPx(24))
|
||||
layout.addView(iv)
|
||||
}
|
||||
|
||||
|
@ -148,8 +147,8 @@ class AutomationFragment : DaggerFragment(), OnStartDragListener {
|
|||
// arrow icon
|
||||
val iv = ImageView(holder.context)
|
||||
iv.setImageResource(R.drawable.ic_arrow_forward_white_24dp)
|
||||
iv.layoutParams = LinearLayout.LayoutParams(MainApp.dpToPx(24), MainApp.dpToPx(24))
|
||||
iv.setPadding(MainApp.dpToPx(4), 0, MainApp.dpToPx(4), 0)
|
||||
iv.layoutParams = LinearLayout.LayoutParams(resourceHelper.dpToPx(24), resourceHelper.dpToPx(24))
|
||||
iv.setPadding(resourceHelper.dpToPx(4), 0, resourceHelper.dpToPx(4), 0)
|
||||
holder.iconLayout.addView(iv)
|
||||
// action icons
|
||||
val actionIcons = HashSet<Int>()
|
||||
|
|
|
@ -156,31 +156,11 @@ public class TriggerLocation extends Trigger {
|
|||
}
|
||||
|
||||
|
||||
TriggerLocation setLatitude(double value) {
|
||||
latitude.setValue(value);
|
||||
return this;
|
||||
}
|
||||
|
||||
TriggerLocation setLongitude(double value) {
|
||||
longitude.setValue(value);
|
||||
return this;
|
||||
}
|
||||
|
||||
TriggerLocation setdistance(double value) {
|
||||
distance.setValue(value);
|
||||
return this;
|
||||
}
|
||||
|
||||
TriggerLocation lastRun(long lastRun) {
|
||||
this.lastRun = lastRun;
|
||||
return this;
|
||||
}
|
||||
|
||||
TriggerLocation setMode(InputLocationMode.Mode value) {
|
||||
modeSelected.setValue(value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void generateDialog(LinearLayout root, FragmentManager fragmentManager) {
|
||||
new LayoutBuilder()
|
||||
|
@ -202,6 +182,7 @@ public class TriggerLocation extends Trigger {
|
|||
return OUTSIDE;
|
||||
}
|
||||
|
||||
// for mocking only TODO remove
|
||||
static Location getCurrentLocation(){
|
||||
return LocationService.getLastLocation();
|
||||
}
|
||||
|
|
|
@ -237,7 +237,7 @@ public class OverviewFragment extends DaggerFragment implements View.OnClickList
|
|||
|
||||
View view;
|
||||
|
||||
if (MainApp.sResources.getBoolean(R.bool.isTablet) && (Config.NSCLIENT)) {
|
||||
if (resourceHelper.gb(R.bool.isTablet) && (Config.NSCLIENT)) {
|
||||
view = inflater.inflate(R.layout.overview_fragment_nsclient_tablet, container, false);
|
||||
} else if (Config.NSCLIENT) {
|
||||
view = inflater.inflate(R.layout.overview_fragment_nsclient, container, false);
|
||||
|
@ -1310,7 +1310,7 @@ public class OverviewFragment extends DaggerFragment implements View.OnClickList
|
|||
+ resourceHelper.gs(R.string.basal) + ": " + DecimalFormatter.to2Decimal(basalIob.basaliob) + "U\n";
|
||||
OKDialog.show(getActivity(), resourceHelper.gs(R.string.iob), iobtext1);
|
||||
});
|
||||
} else if (MainApp.sResources.getBoolean(R.bool.isTablet)) {
|
||||
} else if (resourceHelper.gb(R.bool.isTablet)) {
|
||||
String iobtext = DecimalFormatter.to2Decimal(bolusIob.iob + basalIob.basaliob) + "U ("
|
||||
+ resourceHelper.gs(R.string.bolus) + ": " + DecimalFormatter.to2Decimal(bolusIob.iob) + "U "
|
||||
+ resourceHelper.gs(R.string.basal) + ": " + DecimalFormatter.to2Decimal(basalIob.basaliob) + "U)";
|
||||
|
|
|
@ -5,7 +5,6 @@ import android.app.NotificationChannel
|
|||
import android.app.NotificationManager
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.graphics.BitmapFactory
|
||||
import android.media.AudioManager
|
||||
import android.media.RingtoneManager
|
||||
import android.os.Build
|
||||
|
@ -31,9 +30,6 @@ import java.util.*
|
|||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
/**
|
||||
* Created by mike on 03.12.2016.
|
||||
*/
|
||||
@Singleton
|
||||
class NotificationStore @Inject constructor(
|
||||
private val aapsLogger: AAPSLogger,
|
||||
|
@ -113,8 +109,8 @@ class NotificationStore @Inject constructor(
|
|||
|
||||
private fun raiseSystemNotification(n: Notification) {
|
||||
val mgr = mainApp.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
|
||||
val largeIcon = BitmapFactory.decodeResource(mainApp.resources, MainApp.getIcon())
|
||||
val smallIcon = MainApp.getNotificationIcon()
|
||||
val largeIcon = resourceHelper.decodeResource(resourceHelper.getIcon())
|
||||
val smallIcon = resourceHelper.getNotificationIcon()
|
||||
val sound = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_ALARM)
|
||||
val notificationBuilder = NotificationCompat.Builder(mainApp, CHANNEL_ID)
|
||||
.setSmallIcon(smallIcon)
|
||||
|
|
|
@ -1,63 +0,0 @@
|
|||
package info.nightscout.androidaps.plugins.general.persistentNotification;
|
||||
|
||||
import android.app.Service;
|
||||
import android.content.Intent;
|
||||
import android.os.IBinder;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import info.nightscout.androidaps.events.EventAppExit;
|
||||
import info.nightscout.androidaps.logging.L;
|
||||
import info.nightscout.androidaps.plugins.bus.RxBus;
|
||||
import info.nightscout.androidaps.utils.FabricPrivacy;
|
||||
import io.reactivex.disposables.CompositeDisposable;
|
||||
import io.reactivex.schedulers.Schedulers;
|
||||
|
||||
/**
|
||||
* Keeps AndroidAPS in foreground state, so it won't be terminated by Android nor get restricted by the background execution limits
|
||||
*/
|
||||
public class DummyService extends Service {
|
||||
private static Logger log = LoggerFactory.getLogger(L.CORE);
|
||||
private CompositeDisposable disposable = new CompositeDisposable();
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public IBinder onBind(Intent intent) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
// TODO: I guess this was moved here in order to adhere to the 5 seconds rule to call "startForeground" after a Service was called as Foreground service?
|
||||
// As onCreate() is not called every time a service is started, copied to onStartCommand().
|
||||
startForeground(PersistentNotificationPlugin.ONGOING_NOTIFICATION_ID, PersistentNotificationPlugin.getPlugin().getLastNotification());
|
||||
disposable.add(RxBus.Companion.getINSTANCE()
|
||||
.toObservable(EventAppExit.class)
|
||||
.observeOn(Schedulers.io())
|
||||
.subscribe(event -> {
|
||||
if (L.isEnabled(L.PUMP)) log.debug("EventAppExit received");
|
||||
stopSelf();
|
||||
}, FabricPrivacy::logException)
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
if (L.isEnabled(L.CORE)) log.debug("onDestroy");
|
||||
disposable.clear();
|
||||
super.onDestroy();
|
||||
stopForeground(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int onStartCommand(Intent intent, int flags, int startId) {
|
||||
super.onStartCommand(intent, flags, startId);
|
||||
startForeground(PersistentNotificationPlugin.ONGOING_NOTIFICATION_ID, PersistentNotificationPlugin.getPlugin().getLastNotification());
|
||||
return START_STICKY;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
package info.nightscout.androidaps.plugins.general.persistentNotification
|
||||
|
||||
import android.app.Service
|
||||
import android.content.Intent
|
||||
import android.os.IBinder
|
||||
import dagger.android.DaggerService
|
||||
import info.nightscout.androidaps.events.EventAppExit
|
||||
import info.nightscout.androidaps.logging.AAPSLogger
|
||||
import info.nightscout.androidaps.logging.LTag
|
||||
import info.nightscout.androidaps.plugins.bus.RxBusWrapper
|
||||
import info.nightscout.androidaps.utils.FabricPrivacy
|
||||
import io.reactivex.disposables.CompositeDisposable
|
||||
import io.reactivex.schedulers.Schedulers
|
||||
import javax.inject.Inject
|
||||
|
||||
/**
|
||||
* Keeps AndroidAPS in foreground state, so it won't be terminated by Android nor get restricted by the background execution limits
|
||||
*/
|
||||
class DummyService : DaggerService() {
|
||||
|
||||
@Inject lateinit var rxBus: RxBusWrapper
|
||||
@Inject lateinit var aapsLogger: AAPSLogger
|
||||
@Inject lateinit var persistentNotificationPlugin: PersistentNotificationPlugin
|
||||
|
||||
private val disposable = CompositeDisposable()
|
||||
|
||||
override fun onBind(intent: Intent): IBinder? = null
|
||||
|
||||
override fun onCreate() {
|
||||
super.onCreate()
|
||||
// TODO: I guess this was moved here in order to adhere to the 5 seconds rule to call "startForeground" after a Service was called as Foreground service?
|
||||
// As onCreate() is not called every time a service is started, copied to onStartCommand().
|
||||
startForeground(persistentNotificationPlugin.ONGOING_NOTIFICATION_ID, persistentNotificationPlugin.getLastNotification())
|
||||
disposable.add(rxBus
|
||||
.toObservable(EventAppExit::class.java)
|
||||
.observeOn(Schedulers.io())
|
||||
.subscribe({
|
||||
aapsLogger.debug(LTag.CORE, "EventAppExit received")
|
||||
stopSelf()
|
||||
}) { FabricPrivacy.logException(it) }
|
||||
)
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
aapsLogger.debug(LTag.CORE, "onDestroy")
|
||||
disposable.clear()
|
||||
super.onDestroy()
|
||||
stopForeground(true)
|
||||
}
|
||||
|
||||
override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int {
|
||||
super.onStartCommand(intent, flags, startId)
|
||||
startForeground(persistentNotificationPlugin.ONGOING_NOTIFICATION_ID, persistentNotificationPlugin.getLastNotification())
|
||||
return Service.START_STICKY
|
||||
}
|
||||
}
|
|
@ -1,338 +0,0 @@
|
|||
package info.nightscout.androidaps.plugins.general.persistentNotification;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.Notification;
|
||||
import android.app.NotificationChannel;
|
||||
import android.app.NotificationManager;
|
||||
import android.app.PendingIntent;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.os.Build;
|
||||
|
||||
import androidx.core.app.NotificationCompat;
|
||||
import androidx.core.app.RemoteInput;
|
||||
import androidx.core.app.TaskStackBuilder;
|
||||
|
||||
import info.nightscout.androidaps.Constants;
|
||||
import info.nightscout.androidaps.MainActivity;
|
||||
import info.nightscout.androidaps.MainApp;
|
||||
import info.nightscout.androidaps.R;
|
||||
import info.nightscout.androidaps.data.IobTotal;
|
||||
import info.nightscout.androidaps.db.BgReading;
|
||||
import info.nightscout.androidaps.db.DatabaseHelper;
|
||||
import info.nightscout.androidaps.db.TemporaryBasal;
|
||||
import info.nightscout.androidaps.events.EventExtendedBolusChange;
|
||||
import info.nightscout.androidaps.events.EventInitializationChanged;
|
||||
import info.nightscout.androidaps.events.EventNewBasalProfile;
|
||||
import info.nightscout.androidaps.events.EventPreferenceChange;
|
||||
import info.nightscout.androidaps.events.EventRefreshOverview;
|
||||
import info.nightscout.androidaps.events.EventTempBasalChange;
|
||||
import info.nightscout.androidaps.events.EventTreatmentChange;
|
||||
import info.nightscout.androidaps.interfaces.PluginBase;
|
||||
import info.nightscout.androidaps.interfaces.PluginDescription;
|
||||
import info.nightscout.androidaps.interfaces.PluginType;
|
||||
import info.nightscout.androidaps.plugins.bus.RxBus;
|
||||
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin;
|
||||
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions;
|
||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatus;
|
||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin;
|
||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.events.EventAutosensCalculationFinished;
|
||||
import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin;
|
||||
import info.nightscout.androidaps.utils.DecimalFormatter;
|
||||
import info.nightscout.androidaps.utils.FabricPrivacy;
|
||||
import io.reactivex.disposables.CompositeDisposable;
|
||||
import io.reactivex.schedulers.Schedulers;
|
||||
|
||||
/**
|
||||
* Created by adrian on 23/12/16.
|
||||
*/
|
||||
|
||||
public class PersistentNotificationPlugin extends PluginBase {
|
||||
|
||||
private CompositeDisposable disposable = new CompositeDisposable();
|
||||
|
||||
private static PersistentNotificationPlugin plugin;
|
||||
private Notification notification;
|
||||
|
||||
@Deprecated
|
||||
public static PersistentNotificationPlugin getPlugin() {
|
||||
if (plugin == null) plugin = new PersistentNotificationPlugin();
|
||||
return plugin;
|
||||
}
|
||||
|
||||
public static final String CHANNEL_ID = "AndroidAPS-Ongoing";
|
||||
|
||||
public static final int ONGOING_NOTIFICATION_ID = 4711;
|
||||
|
||||
/// For Android Auto
|
||||
/// Intents are not declared in manifest and not consumed, this is intentionally because actually we can't do anything with
|
||||
private static final String PACKAGE = "info.nightscout";
|
||||
private static final String READ_ACTION =
|
||||
"info.nightscout.androidaps.ACTION_MESSAGE_READ";
|
||||
private static final String REPLY_ACTION =
|
||||
"info.nightscout.androidaps.ACTION_MESSAGE_REPLY";
|
||||
private static final String CONVERSATION_ID = "conversation_id";
|
||||
private static final String EXTRA_VOICE_REPLY = "extra_voice_reply";
|
||||
/// End Android Auto
|
||||
|
||||
|
||||
private PersistentNotificationPlugin() {
|
||||
super(new PluginDescription()
|
||||
.mainType(PluginType.GENERAL)
|
||||
.neverVisible(true)
|
||||
.pluginName(R.string.ongoingnotificaction)
|
||||
.enableByDefault(true)
|
||||
.alwaysEnabled(true)
|
||||
.showInList(false)
|
||||
.description(R.string.description_persistent_notification)
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStart() {
|
||||
super.onStart();
|
||||
createNotificationChannel(); // make sure channels exist before triggering updates through the bus
|
||||
disposable.add(RxBus.Companion.getINSTANCE()
|
||||
.toObservable(EventRefreshOverview.class)
|
||||
.observeOn(Schedulers.io())
|
||||
.subscribe(event -> triggerNotificationUpdate(false),
|
||||
FabricPrivacy::logException
|
||||
));
|
||||
disposable.add(RxBus.Companion.getINSTANCE()
|
||||
.toObservable(EventExtendedBolusChange.class)
|
||||
.observeOn(Schedulers.io())
|
||||
.subscribe(event -> triggerNotificationUpdate(false),
|
||||
FabricPrivacy::logException
|
||||
));
|
||||
disposable.add(RxBus.Companion.getINSTANCE()
|
||||
.toObservable(EventTempBasalChange.class)
|
||||
.observeOn(Schedulers.io())
|
||||
.subscribe(event -> triggerNotificationUpdate(false),
|
||||
FabricPrivacy::logException
|
||||
));
|
||||
disposable.add(RxBus.Companion.getINSTANCE()
|
||||
.toObservable(EventTreatmentChange.class)
|
||||
.observeOn(Schedulers.io())
|
||||
.subscribe(event -> triggerNotificationUpdate(false),
|
||||
FabricPrivacy::logException
|
||||
));
|
||||
disposable.add(RxBus.Companion.getINSTANCE()
|
||||
.toObservable(EventInitializationChanged.class)
|
||||
.observeOn(Schedulers.io())
|
||||
.subscribe(event -> triggerNotificationUpdate(false),
|
||||
FabricPrivacy::logException
|
||||
));
|
||||
disposable.add(RxBus.Companion.getINSTANCE()
|
||||
.toObservable(EventNewBasalProfile.class)
|
||||
.observeOn(Schedulers.io())
|
||||
.subscribe(event -> triggerNotificationUpdate(false),
|
||||
FabricPrivacy::logException
|
||||
));
|
||||
disposable.add(RxBus.Companion.getINSTANCE()
|
||||
.toObservable(EventAutosensCalculationFinished.class)
|
||||
.observeOn(Schedulers.io())
|
||||
.subscribe(event -> triggerNotificationUpdate(false),
|
||||
FabricPrivacy::logException
|
||||
));
|
||||
disposable.add(RxBus.Companion.getINSTANCE()
|
||||
.toObservable(EventPreferenceChange.class)
|
||||
.observeOn(Schedulers.io())
|
||||
.subscribe(event -> triggerNotificationUpdate(false),
|
||||
FabricPrivacy::logException
|
||||
));
|
||||
triggerNotificationUpdate(true);
|
||||
}
|
||||
|
||||
private void createNotificationChannel() {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
|
||||
NotificationManager mNotificationManager =
|
||||
(NotificationManager) MainApp.instance().getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
@SuppressLint("WrongConstant") NotificationChannel channel = new NotificationChannel(CHANNEL_ID,
|
||||
CHANNEL_ID,
|
||||
NotificationManager.IMPORTANCE_HIGH);
|
||||
mNotificationManager.createNotificationChannel(channel);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStop() {
|
||||
disposable.clear();
|
||||
MainApp.instance().stopService(new Intent(MainApp.instance(), DummyService.class));
|
||||
super.onStop();
|
||||
}
|
||||
|
||||
private void triggerNotificationUpdate(boolean boot) {
|
||||
updateNotification(boot);
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
|
||||
MainApp.instance().startForegroundService(new Intent(MainApp.instance(), DummyService.class));
|
||||
else
|
||||
MainApp.instance().startService(new Intent(MainApp.instance(), DummyService.class));
|
||||
}
|
||||
|
||||
private void updateNotification(boolean boot) {
|
||||
String line1;
|
||||
String line2 = null;
|
||||
String line3 = null;
|
||||
NotificationCompat.CarExtender.UnreadConversation.Builder unreadConversationBuilder = null;
|
||||
|
||||
if (boot) {
|
||||
line1 = MainApp.gs(R.string.loading);
|
||||
} else if (ConfigBuilderPlugin.getPlugin().getActiveProfileInterface() != null && ProfileFunctions.getInstance().isProfileValid("Notification")) {
|
||||
String line1_aa;
|
||||
String units = ProfileFunctions.getSystemUnits();
|
||||
|
||||
|
||||
BgReading lastBG = DatabaseHelper.lastBg();
|
||||
GlucoseStatus glucoseStatus = GlucoseStatus.getGlucoseStatusData();
|
||||
|
||||
if (lastBG != null) {
|
||||
line1 = line1_aa = lastBG.valueToUnitsToString(units);
|
||||
if (glucoseStatus != null) {
|
||||
line1 += " Δ" + deltastring(glucoseStatus.delta, glucoseStatus.delta * Constants.MGDL_TO_MMOLL, units)
|
||||
+ " avgΔ" + deltastring(glucoseStatus.avgdelta, glucoseStatus.avgdelta * Constants.MGDL_TO_MMOLL, units);
|
||||
line1_aa += " " + lastBG.directionToSymbol();
|
||||
} else {
|
||||
line1 += " " +
|
||||
MainApp.gs(R.string.old_data) +
|
||||
" ";
|
||||
line1_aa += line1 + ".";
|
||||
}
|
||||
} else {
|
||||
line1 = line1_aa = MainApp.gs(R.string.missed_bg_readings);
|
||||
}
|
||||
|
||||
TemporaryBasal activeTemp = TreatmentsPlugin.getPlugin().getTempBasalFromHistory(System.currentTimeMillis());
|
||||
if (activeTemp != null) {
|
||||
line1 += " " + activeTemp.toStringShort();
|
||||
line1_aa += " " + activeTemp.toStringShort() + ".";
|
||||
}
|
||||
|
||||
//IOB
|
||||
TreatmentsPlugin.getPlugin().updateTotalIOBTreatments();
|
||||
TreatmentsPlugin.getPlugin().updateTotalIOBTempBasals();
|
||||
IobTotal bolusIob = TreatmentsPlugin.getPlugin().getLastCalculationTreatments().round();
|
||||
IobTotal basalIob = TreatmentsPlugin.getPlugin().getLastCalculationTempBasals().round();
|
||||
|
||||
|
||||
line2 = MainApp.gs(R.string.treatments_iob_label_string) + " " + DecimalFormatter.to2Decimal(bolusIob.iob + basalIob.basaliob) + "U " + MainApp.gs(R.string.cob) + ": " + IobCobCalculatorPlugin.getPlugin().getCobInfo(false, "PersistentNotificationPlugin").generateCOBString();
|
||||
String line2_aa = MainApp.gs(R.string.treatments_iob_label_string) + " " + DecimalFormatter.to2Decimal(bolusIob.iob + basalIob.basaliob) + "U. " + MainApp.gs(R.string.cob) + ": " + IobCobCalculatorPlugin.getPlugin().getCobInfo(false, "PersistentNotificationPlugin").generateCOBString() + ".";
|
||||
|
||||
|
||||
line3 = DecimalFormatter.to2Decimal(ConfigBuilderPlugin.getPlugin().getActivePump().getBaseBasalRate()) + " U/h";
|
||||
String line3_aa = DecimalFormatter.to2Decimal(ConfigBuilderPlugin.getPlugin().getActivePump().getBaseBasalRate()) + " U/h.";
|
||||
|
||||
|
||||
line3 += " - " + ProfileFunctions.getInstance().getProfileName();
|
||||
line3_aa += " - " + ProfileFunctions.getInstance().getProfileName() + ".";
|
||||
|
||||
/// For Android Auto
|
||||
Intent msgReadIntent = new Intent()
|
||||
.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES)
|
||||
.setAction(READ_ACTION)
|
||||
.putExtra(CONVERSATION_ID, ONGOING_NOTIFICATION_ID)
|
||||
.setPackage(PACKAGE);
|
||||
|
||||
PendingIntent msgReadPendingIntent =
|
||||
PendingIntent.getBroadcast(MainApp.instance(),
|
||||
ONGOING_NOTIFICATION_ID,
|
||||
msgReadIntent,
|
||||
PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
|
||||
Intent msgReplyIntent = new Intent()
|
||||
.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES)
|
||||
.setAction(REPLY_ACTION)
|
||||
.putExtra(CONVERSATION_ID, ONGOING_NOTIFICATION_ID)
|
||||
.setPackage(PACKAGE);
|
||||
|
||||
PendingIntent msgReplyPendingIntent = PendingIntent.getBroadcast(
|
||||
MainApp.instance(),
|
||||
ONGOING_NOTIFICATION_ID,
|
||||
msgReplyIntent,
|
||||
PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
|
||||
// Build a RemoteInput for receiving voice input from devices
|
||||
RemoteInput remoteInput = new RemoteInput.Builder(EXTRA_VOICE_REPLY).build();
|
||||
|
||||
// Create the UnreadConversation
|
||||
unreadConversationBuilder =
|
||||
new NotificationCompat.CarExtender.UnreadConversation.Builder(line1_aa + "\n" + line2_aa)
|
||||
.setLatestTimestamp(System.currentTimeMillis())
|
||||
.setReadPendingIntent(msgReadPendingIntent)
|
||||
.setReplyAction(msgReplyPendingIntent, remoteInput);
|
||||
|
||||
/// Add dot to produce a "more natural sounding result"
|
||||
unreadConversationBuilder.addMessage(line3_aa);
|
||||
/// End Android Auto
|
||||
} else {
|
||||
line1 = MainApp.gs(R.string.noprofileset);
|
||||
}
|
||||
|
||||
NotificationCompat.Builder builder = new NotificationCompat.Builder(MainApp.instance(), CHANNEL_ID);
|
||||
builder.setOngoing(true);
|
||||
builder.setOnlyAlertOnce(true);
|
||||
builder.setCategory(NotificationCompat.CATEGORY_STATUS);
|
||||
builder.setSmallIcon(MainApp.getNotificationIcon());
|
||||
Bitmap largeIcon = BitmapFactory.decodeResource(MainApp.instance().getResources(), MainApp.getIcon());
|
||||
builder.setLargeIcon(largeIcon);
|
||||
if (line1 != null) builder.setContentTitle(line1);
|
||||
if (line2 != null) builder.setContentText(line2);
|
||||
if (line3 != null) builder.setSubText(line3);
|
||||
/// Android Auto
|
||||
if (unreadConversationBuilder != null) {
|
||||
builder.extend(new NotificationCompat.CarExtender()
|
||||
.setUnreadConversation(unreadConversationBuilder.build()));
|
||||
}
|
||||
/// End Android Auto
|
||||
|
||||
|
||||
Intent resultIntent = new Intent(MainApp.instance(), MainActivity.class);
|
||||
|
||||
TaskStackBuilder stackBuilder = TaskStackBuilder.create(MainApp.instance());
|
||||
stackBuilder.addParentStack(MainActivity.class);
|
||||
stackBuilder.addNextIntent(resultIntent);
|
||||
PendingIntent resultPendingIntent =
|
||||
stackBuilder.getPendingIntent(
|
||||
0,
|
||||
PendingIntent.FLAG_UPDATE_CURRENT
|
||||
);
|
||||
builder.setContentIntent(resultPendingIntent);
|
||||
NotificationManager mNotificationManager =
|
||||
(NotificationManager) MainApp.instance().getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
|
||||
android.app.Notification notification = builder.build();
|
||||
mNotificationManager.notify(ONGOING_NOTIFICATION_ID, notification);
|
||||
this.notification = notification;
|
||||
}
|
||||
|
||||
private String deltastring(double deltaMGDL, double deltaMMOL, String units) {
|
||||
String deltastring = "";
|
||||
if (deltaMGDL >= 0) {
|
||||
deltastring += "+";
|
||||
} else {
|
||||
deltastring += "-";
|
||||
|
||||
}
|
||||
if (units.equals(Constants.MGDL)) {
|
||||
deltastring += DecimalFormatter.to1Decimal(Math.abs(deltaMGDL));
|
||||
} else {
|
||||
deltastring += DecimalFormatter.to1Decimal(Math.abs(deltaMMOL));
|
||||
}
|
||||
return deltastring;
|
||||
}
|
||||
|
||||
/***
|
||||
* returns the current ongoing notification.
|
||||
*
|
||||
* If it does not exist, return a dummy notification. This should only happen if onStart() wasn't called.
|
||||
*/
|
||||
|
||||
public Notification getLastNotification() {
|
||||
if (notification != null) return notification;
|
||||
else {
|
||||
throw new IllegalStateException("Notification is null");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,246 @@
|
|||
package info.nightscout.androidaps.plugins.general.persistentNotification
|
||||
|
||||
import android.app.Notification
|
||||
import android.app.NotificationChannel
|
||||
import android.app.NotificationManager
|
||||
import android.app.PendingIntent
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Build
|
||||
import androidx.core.app.NotificationCompat
|
||||
import androidx.core.app.RemoteInput
|
||||
import androidx.core.app.TaskStackBuilder
|
||||
import info.nightscout.androidaps.Constants
|
||||
import info.nightscout.androidaps.MainActivity
|
||||
import info.nightscout.androidaps.MainApp
|
||||
import info.nightscout.androidaps.R
|
||||
import info.nightscout.androidaps.data.Profile
|
||||
import info.nightscout.androidaps.db.DatabaseHelper
|
||||
import info.nightscout.androidaps.events.*
|
||||
import info.nightscout.androidaps.interfaces.PluginBase
|
||||
import info.nightscout.androidaps.interfaces.PluginDescription
|
||||
import info.nightscout.androidaps.interfaces.PluginType
|
||||
import info.nightscout.androidaps.plugins.bus.RxBusWrapper
|
||||
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin
|
||||
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunction
|
||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatus
|
||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin
|
||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.events.EventAutosensCalculationFinished
|
||||
import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin
|
||||
import info.nightscout.androidaps.utils.DecimalFormatter
|
||||
import info.nightscout.androidaps.utils.FabricPrivacy
|
||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||
import io.reactivex.disposables.CompositeDisposable
|
||||
import io.reactivex.schedulers.Schedulers
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Singleton
|
||||
class PersistentNotificationPlugin @Inject constructor() : PluginBase(PluginDescription()
|
||||
.mainType(PluginType.GENERAL)
|
||||
.neverVisible(true)
|
||||
.pluginName(R.string.ongoingnotificaction)
|
||||
.enableByDefault(true)
|
||||
.alwaysEnabled(true)
|
||||
.showInList(false)
|
||||
.description(R.string.description_persistent_notification)
|
||||
) {
|
||||
|
||||
@Inject lateinit var rxBus: RxBusWrapper
|
||||
@Inject lateinit var mainApp: MainApp
|
||||
@Inject lateinit var resourceHelper: ResourceHelper
|
||||
@Inject lateinit var profileFunction: ProfileFunction
|
||||
@Inject lateinit var configBuilderPlugin: ConfigBuilderPlugin
|
||||
@Inject lateinit var treatmentsPlugin: TreatmentsPlugin
|
||||
@Inject lateinit var iobCobCalculatorPlugin: IobCobCalculatorPlugin
|
||||
|
||||
// For Android Auto
|
||||
// Intents are not declared in manifest and not consumed, this is intentionally because actually we can't do anything with
|
||||
private val PACKAGE = "info.nightscout"
|
||||
private val READ_ACTION = "info.nightscout.androidaps.ACTION_MESSAGE_READ"
|
||||
private val REPLY_ACTION = "info.nightscout.androidaps.ACTION_MESSAGE_REPLY"
|
||||
private val CONVERSATION_ID = "conversation_id"
|
||||
private val EXTRA_VOICE_REPLY = "extra_voice_reply"
|
||||
// End Android auto
|
||||
|
||||
private val disposable = CompositeDisposable()
|
||||
private var notification: Notification? = null
|
||||
|
||||
val CHANNEL_ID = "AndroidAPS-Ongoing"
|
||||
val ONGOING_NOTIFICATION_ID = 4711
|
||||
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
createNotificationChannel() // make sure channels exist before triggering updates through the bus
|
||||
disposable.add(rxBus
|
||||
.toObservable(EventRefreshOverview::class.java)
|
||||
.observeOn(Schedulers.io())
|
||||
.subscribe({ event: EventRefreshOverview? -> triggerNotificationUpdate(false) }) { throwable: Throwable? -> FabricPrivacy.logException(throwable) })
|
||||
disposable.add(rxBus
|
||||
.toObservable(EventExtendedBolusChange::class.java)
|
||||
.observeOn(Schedulers.io())
|
||||
.subscribe({ event: EventExtendedBolusChange? -> triggerNotificationUpdate(false) }) { throwable: Throwable? -> FabricPrivacy.logException(throwable) })
|
||||
disposable.add(rxBus
|
||||
.toObservable(EventTempBasalChange::class.java)
|
||||
.observeOn(Schedulers.io())
|
||||
.subscribe({ event: EventTempBasalChange? -> triggerNotificationUpdate(false) }) { throwable: Throwable? -> FabricPrivacy.logException(throwable) })
|
||||
disposable.add(rxBus
|
||||
.toObservable(EventTreatmentChange::class.java)
|
||||
.observeOn(Schedulers.io())
|
||||
.subscribe({ event: EventTreatmentChange? -> triggerNotificationUpdate(false) }) { throwable: Throwable? -> FabricPrivacy.logException(throwable) })
|
||||
disposable.add(rxBus
|
||||
.toObservable(EventInitializationChanged::class.java)
|
||||
.observeOn(Schedulers.io())
|
||||
.subscribe({ event: EventInitializationChanged? -> triggerNotificationUpdate(false) }) { throwable: Throwable? -> FabricPrivacy.logException(throwable) })
|
||||
disposable.add(rxBus
|
||||
.toObservable(EventNewBasalProfile::class.java)
|
||||
.observeOn(Schedulers.io())
|
||||
.subscribe({ event: EventNewBasalProfile? -> triggerNotificationUpdate(false) }) { throwable: Throwable? -> FabricPrivacy.logException(throwable) })
|
||||
disposable.add(rxBus
|
||||
.toObservable(EventAutosensCalculationFinished::class.java)
|
||||
.observeOn(Schedulers.io())
|
||||
.subscribe({ event: EventAutosensCalculationFinished? -> triggerNotificationUpdate(false) }) { throwable: Throwable? -> FabricPrivacy.logException(throwable) })
|
||||
disposable.add(rxBus
|
||||
.toObservable(EventPreferenceChange::class.java)
|
||||
.observeOn(Schedulers.io())
|
||||
.subscribe({ event: EventPreferenceChange? -> triggerNotificationUpdate(false) }) { throwable: Throwable? -> FabricPrivacy.logException(throwable) })
|
||||
triggerNotificationUpdate(true)
|
||||
}
|
||||
|
||||
private fun createNotificationChannel() {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
val mNotificationManager = mainApp.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
|
||||
val channel = NotificationChannel(CHANNEL_ID, CHANNEL_ID as CharSequence, NotificationManager.IMPORTANCE_HIGH)
|
||||
mNotificationManager.createNotificationChannel(channel)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onStop() {
|
||||
disposable.clear()
|
||||
mainApp.stopService(Intent(mainApp, DummyService::class.java))
|
||||
super.onStop()
|
||||
}
|
||||
|
||||
private fun triggerNotificationUpdate(boot: Boolean) {
|
||||
updateNotification(boot)
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
|
||||
mainApp.startForegroundService(Intent(mainApp, DummyService::class.java))
|
||||
else
|
||||
mainApp.startService(Intent(mainApp, DummyService::class.java))
|
||||
}
|
||||
|
||||
private fun updateNotification(boot: Boolean) {
|
||||
val pump = configBuilderPlugin.activePump ?: return
|
||||
var line1: String?
|
||||
var line2: String? = null
|
||||
var line3: String? = null
|
||||
var unreadConversationBuilder: NotificationCompat.CarExtender.UnreadConversation.Builder? = null
|
||||
if (boot) {
|
||||
line1 = resourceHelper.gs(R.string.loading)
|
||||
} else if (profileFunction.isProfileValid("Notification")) {
|
||||
var line1_aa: String
|
||||
val units = profileFunction.getUnits()
|
||||
val lastBG = DatabaseHelper.lastBg()
|
||||
val glucoseStatus = GlucoseStatus.getGlucoseStatusData()
|
||||
if (lastBG != null) {
|
||||
line1_aa = lastBG.valueToUnitsToString(units)
|
||||
line1 = line1_aa
|
||||
if (glucoseStatus != null) {
|
||||
line1 += (" Δ" + Profile.toSignedUnitsString(glucoseStatus.delta, glucoseStatus.delta * Constants.MGDL_TO_MMOLL, units)
|
||||
+ " avgΔ" + Profile.toSignedUnitsString(glucoseStatus.avgdelta, glucoseStatus.avgdelta * Constants.MGDL_TO_MMOLL, units))
|
||||
line1_aa += " " + lastBG.directionToSymbol()
|
||||
} else {
|
||||
line1 += " " +
|
||||
resourceHelper.gs(R.string.old_data) +
|
||||
" "
|
||||
line1_aa += "$line1."
|
||||
}
|
||||
} else {
|
||||
line1_aa = resourceHelper.gs(R.string.missed_bg_readings)
|
||||
line1 = line1_aa
|
||||
}
|
||||
val activeTemp = treatmentsPlugin.getTempBasalFromHistory(System.currentTimeMillis())
|
||||
if (activeTemp != null) {
|
||||
line1 += " " + activeTemp.toStringShort()
|
||||
line1_aa += " " + activeTemp.toStringShort() + "."
|
||||
}
|
||||
//IOB
|
||||
treatmentsPlugin.updateTotalIOBTreatments()
|
||||
treatmentsPlugin.updateTotalIOBTempBasals()
|
||||
val bolusIob = treatmentsPlugin.lastCalculationTreatments.round()
|
||||
val basalIob = treatmentsPlugin.lastCalculationTempBasals.round()
|
||||
line2 = resourceHelper.gs(R.string.treatments_iob_label_string) + " " + DecimalFormatter.to2Decimal(bolusIob.iob + basalIob.basaliob) + "U " + resourceHelper.gs(R.string.cob) + ": " + iobCobCalculatorPlugin.getCobInfo(false, "PersistentNotificationPlugin").generateCOBString()
|
||||
val line2_aa = resourceHelper.gs(R.string.treatments_iob_label_string) + " " + DecimalFormatter.to2Decimal(bolusIob.iob + basalIob.basaliob) + "U. " + resourceHelper.gs(R.string.cob) + ": " + iobCobCalculatorPlugin.getCobInfo(false, "PersistentNotificationPlugin").generateCOBString() + "."
|
||||
line3 = DecimalFormatter.to2Decimal(pump.baseBasalRate) + " U/h"
|
||||
var line3_aa = DecimalFormatter.to2Decimal(pump.baseBasalRate) + " U/h."
|
||||
line3 += " - " + profileFunction.getProfileName()
|
||||
line3_aa += " - " + profileFunction.getProfileName() + "."
|
||||
/// For Android Auto
|
||||
val msgReadIntent = Intent()
|
||||
.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES)
|
||||
.setAction(READ_ACTION)
|
||||
.putExtra(CONVERSATION_ID, ONGOING_NOTIFICATION_ID)
|
||||
.setPackage(PACKAGE)
|
||||
val msgReadPendingIntent = PendingIntent.getBroadcast(mainApp,
|
||||
ONGOING_NOTIFICATION_ID,
|
||||
msgReadIntent,
|
||||
PendingIntent.FLAG_UPDATE_CURRENT)
|
||||
val msgReplyIntent = Intent()
|
||||
.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES)
|
||||
.setAction(REPLY_ACTION)
|
||||
.putExtra(CONVERSATION_ID, ONGOING_NOTIFICATION_ID)
|
||||
.setPackage(PACKAGE)
|
||||
val msgReplyPendingIntent = PendingIntent.getBroadcast(
|
||||
mainApp,
|
||||
ONGOING_NOTIFICATION_ID,
|
||||
msgReplyIntent,
|
||||
PendingIntent.FLAG_UPDATE_CURRENT)
|
||||
// Build a RemoteInput for receiving voice input from devices
|
||||
val remoteInput = RemoteInput.Builder(EXTRA_VOICE_REPLY).build()
|
||||
// Create the UnreadConversation
|
||||
unreadConversationBuilder = NotificationCompat.CarExtender.UnreadConversation.Builder(line1_aa + "\n" + line2_aa)
|
||||
.setLatestTimestamp(System.currentTimeMillis())
|
||||
.setReadPendingIntent(msgReadPendingIntent)
|
||||
.setReplyAction(msgReplyPendingIntent, remoteInput)
|
||||
/// Add dot to produce a "more natural sounding result"
|
||||
unreadConversationBuilder.addMessage(line3_aa)
|
||||
/// End Android Auto
|
||||
} else {
|
||||
line1 = resourceHelper.gs(R.string.noprofileset)
|
||||
}
|
||||
val builder = NotificationCompat.Builder(mainApp, CHANNEL_ID)
|
||||
builder.setOngoing(true)
|
||||
builder.setOnlyAlertOnce(true)
|
||||
builder.setCategory(NotificationCompat.CATEGORY_STATUS)
|
||||
builder.setSmallIcon(resourceHelper.getNotificationIcon())
|
||||
builder.setLargeIcon(resourceHelper.decodeResource(resourceHelper.getIcon()))
|
||||
if (line1 != null) builder.setContentTitle(line1)
|
||||
if (line2 != null) builder.setContentText(line2)
|
||||
if (line3 != null) builder.setSubText(line3)
|
||||
/// Android Auto
|
||||
if (unreadConversationBuilder != null) {
|
||||
builder.extend(NotificationCompat.CarExtender()
|
||||
.setUnreadConversation(unreadConversationBuilder.build()))
|
||||
}
|
||||
/// End Android Auto
|
||||
val resultIntent = Intent(mainApp, MainActivity::class.java)
|
||||
val stackBuilder = TaskStackBuilder.create(mainApp)
|
||||
stackBuilder.addParentStack(MainActivity::class.java)
|
||||
stackBuilder.addNextIntent(resultIntent)
|
||||
val resultPendingIntent = stackBuilder.getPendingIntent(
|
||||
0,
|
||||
PendingIntent.FLAG_UPDATE_CURRENT
|
||||
)
|
||||
builder.setContentIntent(resultPendingIntent)
|
||||
val mNotificationManager = mainApp.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
|
||||
val notification = builder.build()
|
||||
mNotificationManager.notify(ONGOING_NOTIFICATION_ID, notification)
|
||||
this.notification = notification
|
||||
}
|
||||
|
||||
fun getLastNotification(): Notification {
|
||||
if (notification == null)
|
||||
updateNotification(true)
|
||||
return notification!!
|
||||
}
|
||||
}
|
|
@ -117,7 +117,7 @@ class VirtualPumpPlugin @Inject constructor(
|
|||
disposable += rxBus
|
||||
.toObservable(EventPreferenceChange::class.java)
|
||||
.observeOn(Schedulers.io())
|
||||
.subscribe({ event: EventPreferenceChange -> if (event.isChanged(R.string.key_virtualpump_type)) refreshConfiguration() }) { throwable: Throwable? -> FabricPrivacy.logException(throwable) }
|
||||
.subscribe({ event: EventPreferenceChange -> if (event.isChanged(R.string.key_virtualpump_type)) refreshConfiguration() }) { FabricPrivacy.logException(it) }
|
||||
refreshConfiguration()
|
||||
}
|
||||
|
||||
|
|
|
@ -1,85 +0,0 @@
|
|||
package info.nightscout.androidaps.services;
|
||||
|
||||
import android.app.Notification;
|
||||
import android.app.Service;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.res.AssetFileDescriptor;
|
||||
import android.media.AudioManager;
|
||||
import android.media.MediaPlayer;
|
||||
import android.os.IBinder;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import info.nightscout.androidaps.MainApp;
|
||||
import info.nightscout.androidaps.R;
|
||||
import info.nightscout.androidaps.logging.L;
|
||||
import info.nightscout.androidaps.plugins.general.persistentNotification.PersistentNotificationPlugin;
|
||||
|
||||
public class AlarmSoundService extends Service {
|
||||
private static Logger log = LoggerFactory.getLogger(L.CORE);
|
||||
|
||||
MediaPlayer player;
|
||||
int resourceId = R.raw.error;
|
||||
|
||||
public AlarmSoundService() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public IBinder onBind(Intent intent) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
if (L.isEnabled(L.CORE))
|
||||
log.debug("onCreate");
|
||||
Notification notification = PersistentNotificationPlugin.getPlugin().getLastNotification();
|
||||
startForeground(PersistentNotificationPlugin.ONGOING_NOTIFICATION_ID, notification);
|
||||
}
|
||||
|
||||
public int onStartCommand(Intent intent, int flags, int startId) {
|
||||
Notification notification = PersistentNotificationPlugin.getPlugin().getLastNotification();
|
||||
startForeground(PersistentNotificationPlugin.ONGOING_NOTIFICATION_ID, notification);
|
||||
if (player != null && player.isPlaying())
|
||||
player.stop();
|
||||
if (L.isEnabled(L.CORE))
|
||||
log.debug("onStartCommand");
|
||||
if (intent != null && intent.hasExtra("soundid"))
|
||||
resourceId = intent.getIntExtra("soundid", R.raw.error);
|
||||
|
||||
player = new MediaPlayer();
|
||||
try {
|
||||
AssetFileDescriptor afd = MainApp.sResources.openRawResourceFd(resourceId);
|
||||
if (afd == null)
|
||||
return START_STICKY;
|
||||
player.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength());
|
||||
afd.close();
|
||||
player.setLooping(true); // Set looping
|
||||
AudioManager manager = (AudioManager) this.getSystemService(Context.AUDIO_SERVICE);
|
||||
if (manager == null || !manager.isMusicActive()) {
|
||||
player.setVolume(100, 100);
|
||||
}
|
||||
player.prepare();
|
||||
player.start();
|
||||
} catch (Exception e) {
|
||||
log.error("Unhandled exception", e);
|
||||
}
|
||||
return START_STICKY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
if (player != null) {
|
||||
player.stop();
|
||||
player.release();
|
||||
}
|
||||
|
||||
if (L.isEnabled(L.CORE))
|
||||
log.debug("onDestroy");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,64 @@
|
|||
package info.nightscout.androidaps.services
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.media.AudioManager
|
||||
import android.media.MediaPlayer
|
||||
import android.os.IBinder
|
||||
import dagger.android.DaggerService
|
||||
import info.nightscout.androidaps.R
|
||||
import info.nightscout.androidaps.logging.AAPSLogger
|
||||
import info.nightscout.androidaps.logging.LTag
|
||||
import info.nightscout.androidaps.plugins.general.persistentNotification.PersistentNotificationPlugin
|
||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||
import javax.inject.Inject
|
||||
|
||||
class AlarmSoundService : DaggerService() {
|
||||
@Inject lateinit var aapsLogger: AAPSLogger
|
||||
@Inject lateinit var resourceHelper: ResourceHelper
|
||||
@Inject lateinit var persistentNotificationPlugin: PersistentNotificationPlugin
|
||||
|
||||
private var player: MediaPlayer? = null
|
||||
private var resourceId = R.raw.error
|
||||
|
||||
override fun onBind(intent: Intent): IBinder? = null
|
||||
|
||||
override fun onCreate() {
|
||||
super.onCreate()
|
||||
aapsLogger.debug(LTag.CORE, "onCreate")
|
||||
val notification = persistentNotificationPlugin.getLastNotification()
|
||||
startForeground(persistentNotificationPlugin.ONGOING_NOTIFICATION_ID, notification)
|
||||
}
|
||||
|
||||
override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int {
|
||||
val notification = persistentNotificationPlugin.getLastNotification()
|
||||
startForeground(persistentNotificationPlugin.ONGOING_NOTIFICATION_ID, notification)
|
||||
|
||||
player?.let { if (it.isPlaying) it.stop() }
|
||||
|
||||
aapsLogger.debug(LTag.CORE, "onStartCommand")
|
||||
if (intent.hasExtra("soundid")) resourceId = intent.getIntExtra("soundid", R.raw.error)
|
||||
player = MediaPlayer()
|
||||
try {
|
||||
val afd = resourceHelper.openRawResourceFd(resourceId) ?: return START_STICKY
|
||||
player?.setDataSource(afd.fileDescriptor, afd.startOffset, afd.length)
|
||||
afd.close()
|
||||
player?.isLooping = true // Set looping
|
||||
val manager = getSystemService(Context.AUDIO_SERVICE) as AudioManager
|
||||
if (!manager.isMusicActive) {
|
||||
player?.setVolume(100f, 100f)
|
||||
}
|
||||
player?.prepare()
|
||||
player?.start()
|
||||
} catch (e: Exception) {
|
||||
aapsLogger.error("Unhandled exception", e)
|
||||
}
|
||||
return START_STICKY
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
player?.stop()
|
||||
player?.release()
|
||||
aapsLogger.debug(LTag.CORE, "onDestroy")
|
||||
}
|
||||
}
|
|
@ -1,168 +0,0 @@
|
|||
package info.nightscout.androidaps.services;
|
||||
|
||||
import android.app.Service;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.location.Location;
|
||||
import android.location.LocationManager;
|
||||
import android.os.Bundle;
|
||||
import android.os.IBinder;
|
||||
|
||||
import androidx.core.app.ActivityCompat;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import info.nightscout.androidaps.R;
|
||||
import info.nightscout.androidaps.events.EventAppExit;
|
||||
import info.nightscout.androidaps.events.EventLocationChange;
|
||||
import info.nightscout.androidaps.logging.L;
|
||||
import info.nightscout.androidaps.plugins.bus.RxBus;
|
||||
import info.nightscout.androidaps.plugins.general.persistentNotification.PersistentNotificationPlugin;
|
||||
import info.nightscout.androidaps.utils.FabricPrivacy;
|
||||
import info.nightscout.androidaps.utils.SP;
|
||||
import info.nightscout.androidaps.utils.T;
|
||||
import io.reactivex.disposables.CompositeDisposable;
|
||||
import io.reactivex.schedulers.Schedulers;
|
||||
|
||||
public class LocationService extends Service {
|
||||
private static Logger log = LoggerFactory.getLogger(L.LOCATION);
|
||||
private CompositeDisposable disposable = new CompositeDisposable();
|
||||
|
||||
private LocationManager mLocationManager = null;
|
||||
private static final float LOCATION_DISTANCE = 10f;
|
||||
|
||||
private static final long LOCATION_INTERVAL_ACTIVE = T.mins(5).msecs();
|
||||
private static final long LOCATION_INTERVAL_PASSIVE = T.mins(1).msecs(); // this doesn't cost more power
|
||||
|
||||
private static Location mLastLocation;
|
||||
|
||||
private class LocationListener implements android.location.LocationListener {
|
||||
|
||||
LocationListener(String provider) {
|
||||
if (L.isEnabled(L.LOCATION))
|
||||
log.debug("LocationListener " + provider);
|
||||
mLastLocation = new Location(provider);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLocationChanged(Location location) {
|
||||
if (L.isEnabled(L.LOCATION))
|
||||
log.debug("onLocationChanged: " + location);
|
||||
mLastLocation.set(location);
|
||||
RxBus.Companion.getINSTANCE().send(new EventLocationChange(location));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onProviderDisabled(String provider) {
|
||||
if (L.isEnabled(L.LOCATION))
|
||||
log.debug("onProviderDisabled: " + provider);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onProviderEnabled(String provider) {
|
||||
if (L.isEnabled(L.LOCATION))
|
||||
log.debug("onProviderEnabled: " + provider);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStatusChanged(String provider, int status, Bundle extras) {
|
||||
if (L.isEnabled(L.LOCATION))
|
||||
log.debug("onStatusChanged: " + provider);
|
||||
}
|
||||
}
|
||||
|
||||
LocationListener mLocationListener;
|
||||
|
||||
@Override
|
||||
public IBinder onBind(Intent arg0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int onStartCommand(Intent intent, int flags, int startId) {
|
||||
super.onStartCommand(intent, flags, startId);
|
||||
if (L.isEnabled(L.LOCATION))
|
||||
log.debug("onStartCommand");
|
||||
startForeground(PersistentNotificationPlugin.ONGOING_NOTIFICATION_ID, PersistentNotificationPlugin.getPlugin().getLastNotification());
|
||||
return START_STICKY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
startForeground(PersistentNotificationPlugin.ONGOING_NOTIFICATION_ID, PersistentNotificationPlugin.getPlugin().getLastNotification());
|
||||
|
||||
if (L.isEnabled(L.LOCATION))
|
||||
log.debug("onCreate");
|
||||
|
||||
initializeLocationManager();
|
||||
|
||||
try {
|
||||
if (SP.getString(R.string.key_location, "NONE").equals("NETWORK"))
|
||||
mLocationManager.requestLocationUpdates(
|
||||
LocationManager.NETWORK_PROVIDER,
|
||||
LOCATION_INTERVAL_ACTIVE,
|
||||
LOCATION_DISTANCE,
|
||||
mLocationListener = new LocationListener(LocationManager.NETWORK_PROVIDER)
|
||||
);
|
||||
if (SP.getString(R.string.key_location, "NONE").equals("GPS"))
|
||||
mLocationManager.requestLocationUpdates(
|
||||
LocationManager.GPS_PROVIDER,
|
||||
LOCATION_INTERVAL_ACTIVE,
|
||||
LOCATION_DISTANCE,
|
||||
mLocationListener = new LocationListener(LocationManager.GPS_PROVIDER)
|
||||
);
|
||||
if (SP.getString(R.string.key_location, "NONE").equals("PASSIVE"))
|
||||
mLocationManager.requestLocationUpdates(
|
||||
LocationManager.PASSIVE_PROVIDER,
|
||||
LOCATION_INTERVAL_PASSIVE,
|
||||
LOCATION_DISTANCE,
|
||||
mLocationListener = new LocationListener(LocationManager.PASSIVE_PROVIDER)
|
||||
);
|
||||
} catch (java.lang.SecurityException ex) {
|
||||
log.error("fail to request location update, ignore", ex);
|
||||
} catch (IllegalArgumentException ex) {
|
||||
log.error("network provider does not exist, " + ex.getMessage());
|
||||
}
|
||||
disposable.add(RxBus.Companion.getINSTANCE()
|
||||
.toObservable(EventAppExit.class)
|
||||
.observeOn(Schedulers.io())
|
||||
.subscribe(event -> {
|
||||
if (L.isEnabled(L.CORE)) log.debug("EventAppExit received");
|
||||
stopSelf();
|
||||
}, FabricPrivacy::logException)
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
if (L.isEnabled(L.LOCATION))
|
||||
log.debug("onDestroy");
|
||||
super.onDestroy();
|
||||
if (mLocationManager != null) {
|
||||
try {
|
||||
if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
|
||||
return;
|
||||
}
|
||||
mLocationManager.removeUpdates(mLocationListener);
|
||||
} catch (Exception ex) {
|
||||
log.error("fail to remove location listener, ignore", ex);
|
||||
}
|
||||
}
|
||||
disposable.clear();
|
||||
}
|
||||
|
||||
private void initializeLocationManager() {
|
||||
if (L.isEnabled(L.LOCATION))
|
||||
log.debug("initializeLocationManager - Provider: " + SP.getString(R.string.key_location, "NONE"));
|
||||
if (mLocationManager == null) {
|
||||
mLocationManager = (LocationManager) getApplicationContext().getSystemService(Context.LOCATION_SERVICE);
|
||||
}
|
||||
}
|
||||
|
||||
public static Location getLastLocation() {
|
||||
return mLastLocation;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,152 @@
|
|||
package info.nightscout.androidaps.services
|
||||
|
||||
import android.Manifest
|
||||
import android.app.Service
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.pm.PackageManager
|
||||
import android.location.Location
|
||||
import android.location.LocationManager
|
||||
import android.os.Bundle
|
||||
import android.os.IBinder
|
||||
import androidx.core.app.ActivityCompat
|
||||
import com.google.android.gms.location.FusedLocationProviderClient
|
||||
import com.google.android.gms.location.LocationServices
|
||||
import com.google.android.gms.tasks.OnSuccessListener
|
||||
import dagger.android.DaggerService
|
||||
import info.nightscout.androidaps.R
|
||||
import info.nightscout.androidaps.events.EventAppExit
|
||||
import info.nightscout.androidaps.events.EventLocationChange
|
||||
import info.nightscout.androidaps.logging.AAPSLogger
|
||||
import info.nightscout.androidaps.logging.LTag
|
||||
import info.nightscout.androidaps.plugins.bus.RxBusWrapper
|
||||
import info.nightscout.androidaps.plugins.general.persistentNotification.PersistentNotificationPlugin
|
||||
import info.nightscout.androidaps.utils.FabricPrivacy
|
||||
import info.nightscout.androidaps.utils.T
|
||||
import info.nightscout.androidaps.utils.sharedPreferences.SP
|
||||
import io.reactivex.disposables.CompositeDisposable
|
||||
import io.reactivex.schedulers.Schedulers
|
||||
import javax.inject.Inject
|
||||
|
||||
class LocationService : DaggerService() {
|
||||
@Inject lateinit var aapsLogger: AAPSLogger
|
||||
@Inject lateinit var rxBus: RxBusWrapper
|
||||
@Inject lateinit var sp: SP
|
||||
@Inject lateinit var persistentNotificationPlugin: PersistentNotificationPlugin
|
||||
|
||||
private val disposable = CompositeDisposable()
|
||||
private var locationManager: LocationManager? = null
|
||||
private var locationListener: LocationListener? = null
|
||||
|
||||
private val LOCATION_INTERVAL_ACTIVE = T.mins(5).msecs()
|
||||
private val LOCATION_INTERVAL_PASSIVE = T.mins(1).msecs() // this doesn't cost more power
|
||||
|
||||
companion object {
|
||||
private const val LOCATION_DISTANCE = 10f
|
||||
private var lastLocation: Location? = null
|
||||
|
||||
@JvmStatic
|
||||
@Deprecated("replace by injection")
|
||||
fun getLastLocation(): Location? = lastLocation
|
||||
}
|
||||
|
||||
inner class LocationListener internal constructor(val provider: String) : android.location.LocationListener {
|
||||
|
||||
init {
|
||||
aapsLogger.debug(LTag.LOCATION, "LocationListener $provider")
|
||||
}
|
||||
|
||||
override fun onLocationChanged(location: Location) {
|
||||
aapsLogger.debug(LTag.LOCATION, "onLocationChanged: $location")
|
||||
lastLocation = location
|
||||
rxBus.send(EventLocationChange(location))
|
||||
}
|
||||
|
||||
override fun onProviderDisabled(provider: String) {
|
||||
aapsLogger.debug(LTag.LOCATION, "onProviderDisabled: $provider")
|
||||
}
|
||||
|
||||
override fun onProviderEnabled(provider: String) {
|
||||
aapsLogger.debug(LTag.LOCATION, "onProviderEnabled: $provider")
|
||||
}
|
||||
|
||||
override fun onStatusChanged(provider: String, status: Int, extras: Bundle) {
|
||||
aapsLogger.debug(LTag.LOCATION, "onStatusChanged: $provider")
|
||||
}
|
||||
}
|
||||
|
||||
override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int {
|
||||
super.onStartCommand(intent, flags, startId)
|
||||
startForeground(persistentNotificationPlugin.ONGOING_NOTIFICATION_ID, persistentNotificationPlugin.getLastNotification())
|
||||
return Service.START_STICKY
|
||||
}
|
||||
|
||||
override fun onCreate() {
|
||||
super.onCreate()
|
||||
startForeground(persistentNotificationPlugin.ONGOING_NOTIFICATION_ID, persistentNotificationPlugin.getLastNotification())
|
||||
|
||||
// Get last location once until we get regular update
|
||||
LocationServices.getFusedLocationProviderClient(this).lastLocation.addOnSuccessListener {
|
||||
lastLocation = it
|
||||
}
|
||||
|
||||
initializeLocationManager()
|
||||
|
||||
try {
|
||||
if (sp.getString(R.string.key_location, "NONE") == "NETWORK") locationManager?.requestLocationUpdates(
|
||||
LocationManager.NETWORK_PROVIDER,
|
||||
LOCATION_INTERVAL_ACTIVE,
|
||||
LOCATION_DISTANCE,
|
||||
LocationListener(LocationManager.NETWORK_PROVIDER).also { locationListener = it }
|
||||
)
|
||||
if (sp.getString(R.string.key_location, "NONE") == "GPS") locationManager?.requestLocationUpdates(
|
||||
LocationManager.GPS_PROVIDER,
|
||||
LOCATION_INTERVAL_ACTIVE,
|
||||
LOCATION_DISTANCE,
|
||||
LocationListener(LocationManager.GPS_PROVIDER).also { locationListener = it }
|
||||
)
|
||||
if (sp.getString(R.string.key_location, "NONE") == "PASSIVE") locationManager?.requestLocationUpdates(
|
||||
LocationManager.PASSIVE_PROVIDER,
|
||||
LOCATION_INTERVAL_PASSIVE,
|
||||
LOCATION_DISTANCE,
|
||||
LocationListener(LocationManager.PASSIVE_PROVIDER).also { locationListener = it }
|
||||
)
|
||||
} catch (ex: SecurityException) {
|
||||
aapsLogger.error(LTag.LOCATION, "fail to request location update, ignore", ex)
|
||||
} catch (ex: IllegalArgumentException) {
|
||||
aapsLogger.error(LTag.LOCATION, "network provider does not exist", ex)
|
||||
}
|
||||
disposable.add(rxBus
|
||||
.toObservable(EventAppExit::class.java)
|
||||
.observeOn(Schedulers.io())
|
||||
.subscribe({
|
||||
aapsLogger.debug(LTag.LOCATION, "EventAppExit received")
|
||||
stopSelf()
|
||||
}) { FabricPrivacy.logException(it) }
|
||||
)
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
if (locationManager != null) {
|
||||
try {
|
||||
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
|
||||
return
|
||||
}
|
||||
locationManager!!.removeUpdates(locationListener)
|
||||
} catch (ex: Exception) {
|
||||
aapsLogger.error(LTag.LOCATION, "fail to remove location listener, ignore", ex)
|
||||
}
|
||||
}
|
||||
disposable.clear()
|
||||
}
|
||||
|
||||
override fun onBind(intent: Intent?): IBinder? = null
|
||||
|
||||
private fun initializeLocationManager() {
|
||||
aapsLogger.debug(LTag.LOCATION, "initializeLocationManager - Provider: " + sp.getString(R.string.key_location, "NONE"))
|
||||
if (locationManager == null) {
|
||||
locationManager = applicationContext.getSystemService(Context.LOCATION_SERVICE) as LocationManager
|
||||
}
|
||||
}
|
||||
}
|
|
@ -32,11 +32,11 @@ public class SWRadioButton extends SWItem {
|
|||
}
|
||||
|
||||
public String[] labels() {
|
||||
return MainApp.sResources.getStringArray(labelsArray);
|
||||
return MainApp.resources().getStringArray(labelsArray);
|
||||
}
|
||||
|
||||
public String[] values() {
|
||||
return MainApp.sResources.getStringArray(valuesArray);
|
||||
return MainApp.resources().getStringArray(valuesArray);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -1,7 +1,11 @@
|
|||
package info.nightscout.androidaps.utils.resources
|
||||
|
||||
import android.content.res.AssetFileDescriptor
|
||||
import android.graphics.Bitmap
|
||||
import androidx.annotation.BoolRes
|
||||
import androidx.annotation.ColorRes
|
||||
import androidx.annotation.PluralsRes
|
||||
import androidx.annotation.RawRes
|
||||
import androidx.annotation.StringRes
|
||||
|
||||
interface ResourceHelper {
|
||||
|
@ -9,5 +13,12 @@ interface ResourceHelper {
|
|||
fun gs(@StringRes id: Int, vararg args: Any?): String
|
||||
fun gq(@PluralsRes id: Int, quantity: Int, vararg args: Any?): String
|
||||
fun gc(@ColorRes id: Int): Int
|
||||
fun gb(@BoolRes id :Int) : Boolean
|
||||
fun gcs(@ColorRes id: Int): String
|
||||
fun openRawResourceFd(@RawRes id : Int) : AssetFileDescriptor?
|
||||
|
||||
fun getIcon() : Int
|
||||
fun getNotificationIcon() : Int
|
||||
fun decodeResource(id : Int) : Bitmap
|
||||
fun dpToPx(dp: Int): Int
|
||||
}
|
|
@ -1,11 +1,17 @@
|
|||
package info.nightscout.androidaps.utils.resources
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.res.AssetFileDescriptor
|
||||
import android.graphics.Bitmap
|
||||
import android.graphics.BitmapFactory
|
||||
import androidx.annotation.BoolRes
|
||||
import androidx.annotation.ColorRes
|
||||
import androidx.annotation.PluralsRes
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.core.content.ContextCompat
|
||||
import info.nightscout.androidaps.Config
|
||||
import info.nightscout.androidaps.MainApp
|
||||
import info.nightscout.androidaps.R
|
||||
import javax.inject.Inject
|
||||
|
||||
/**
|
||||
|
@ -22,7 +28,36 @@ class ResourceHelperImplementation @Inject constructor(private val mainApp: Main
|
|||
|
||||
override fun gc(@ColorRes id: Int): Int = ContextCompat.getColor(mainApp, id)
|
||||
|
||||
override fun gb(@BoolRes id :Int) : Boolean = mainApp.resources.getBoolean(id)
|
||||
|
||||
@SuppressLint("ResourceType")
|
||||
override fun gcs(@ColorRes id: Int): String =
|
||||
gs(id).replace("#ff", "#")
|
||||
|
||||
override fun openRawResourceFd(id: Int): AssetFileDescriptor =
|
||||
mainApp.resources.openRawResourceFd(id)
|
||||
|
||||
override fun getIcon(): Int {
|
||||
return when {
|
||||
Config.NSCLIENT -> R.mipmap.ic_yellowowl
|
||||
Config.PUMPCONTROL -> R.mipmap.ic_pumpcontrol
|
||||
else -> R.mipmap.ic_launcher
|
||||
}
|
||||
}
|
||||
|
||||
override fun getNotificationIcon(): Int {
|
||||
return when {
|
||||
Config.NSCLIENT -> R.drawable.ic_notif_nsclient
|
||||
Config.PUMPCONTROL -> R.drawable.ic_notif_pumpcontrol
|
||||
else -> R.drawable.ic_notif_aaps
|
||||
}
|
||||
}
|
||||
|
||||
override fun decodeResource(id: Int): Bitmap =
|
||||
BitmapFactory.decodeResource(mainApp.resources, id)
|
||||
|
||||
override fun dpToPx(dp: Int): Int {
|
||||
val scale = mainApp.resources.displayMetrics.density
|
||||
return (dp * scale + 0.5f).toInt()
|
||||
}
|
||||
}
|
|
@ -141,34 +141,6 @@ public class TriggerLocationTest {
|
|||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setLatitudeTest() {
|
||||
TriggerLocation t = new TriggerLocation();
|
||||
t.setLatitude(212);
|
||||
Assert.assertEquals(t.latitude.getValue(), 212, 0d);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setLongitudeTest() {
|
||||
TriggerLocation t = new TriggerLocation();
|
||||
t.setLongitude(213);
|
||||
Assert.assertEquals(t.longitude.getValue(), 213, 0d);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setdistanceTest() {
|
||||
TriggerLocation t = new TriggerLocation();
|
||||
t.setdistance(2);
|
||||
Assert.assertEquals(t.distance.getValue(), 2, 0d);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setModeTest() {
|
||||
TriggerLocation t = new TriggerLocation();
|
||||
t.setMode(InputLocationMode.Mode.INSIDE);
|
||||
Assert.assertEquals(t.modeSelected.getValue(), InputLocationMode.Mode.INSIDE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void lastRunTest() {
|
||||
TriggerLocation t = new TriggerLocation();
|
||||
|
|
Loading…
Reference in a new issue