2020-01-09 10:44:32 +01:00
|
|
|
/* Copyright (C) 2016-2020 0nse, Andreas Shimokawa, Carsten Pfeiffer
|
2017-03-10 14:53:19 +01:00
|
|
|
|
|
|
|
This file is part of Gadgetbridge.
|
|
|
|
|
|
|
|
Gadgetbridge is free software: you can redistribute it and/or modify
|
|
|
|
it under the terms of the GNU Affero General Public License as published
|
|
|
|
by the Free Software Foundation, either version 3 of the License, or
|
|
|
|
(at your option) any later version.
|
|
|
|
|
|
|
|
Gadgetbridge 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 Affero General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU Affero General Public License
|
|
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
2016-02-29 21:36:39 +01:00
|
|
|
package nodomain.freeyourgadget.gadgetbridge;
|
|
|
|
|
|
|
|
import android.annotation.TargetApi;
|
|
|
|
import android.app.AlarmManager;
|
|
|
|
import android.app.PendingIntent;
|
|
|
|
import android.appwidget.AppWidgetManager;
|
|
|
|
import android.appwidget.AppWidgetProvider;
|
|
|
|
import android.content.Context;
|
|
|
|
import android.content.Intent;
|
|
|
|
import android.os.Build;
|
2022-05-28 14:57:01 +02:00
|
|
|
import android.os.Bundle;
|
2016-02-29 21:36:39 +01:00
|
|
|
import android.widget.RemoteViews;
|
|
|
|
import android.widget.Toast;
|
|
|
|
|
2019-01-10 23:50:02 +01:00
|
|
|
import java.util.ArrayList;
|
2016-02-29 21:36:39 +01:00
|
|
|
import java.util.Calendar;
|
|
|
|
import java.util.GregorianCalendar;
|
|
|
|
|
|
|
|
import nodomain.freeyourgadget.gadgetbridge.activities.ConfigureAlarms;
|
2019-01-10 23:50:02 +01:00
|
|
|
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
2016-02-29 21:36:39 +01:00
|
|
|
import nodomain.freeyourgadget.gadgetbridge.model.ActivityUser;
|
2019-01-10 23:50:02 +01:00
|
|
|
import nodomain.freeyourgadget.gadgetbridge.model.Alarm;
|
|
|
|
import nodomain.freeyourgadget.gadgetbridge.util.AlarmUtils;
|
2016-03-02 00:01:41 +01:00
|
|
|
import nodomain.freeyourgadget.gadgetbridge.util.GB;
|
2022-05-28 14:57:01 +02:00
|
|
|
import nodomain.freeyourgadget.gadgetbridge.util.WidgetPreferenceStorage;
|
2016-02-29 21:36:39 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Implementation of SleepAlarmWidget functionality. When pressing the widget, an alarm will be set
|
|
|
|
* to trigger after a predefined number of hours. A toast will confirm the user about this. The
|
2016-05-13 23:47:47 +02:00
|
|
|
* value is retrieved using ActivityUser.().getSleepDuration().
|
2016-02-29 21:36:39 +01:00
|
|
|
*/
|
|
|
|
public class SleepAlarmWidget extends AppWidgetProvider {
|
|
|
|
/**
|
|
|
|
* This is our dedicated action to detect when the widget has been clicked.
|
|
|
|
*/
|
2022-05-28 14:57:01 +02:00
|
|
|
public static final String ACTION_CLICK =
|
2016-02-29 21:36:39 +01:00
|
|
|
"nodomain.freeyourgadget.gadgetbridge.SLEEP_ALARM_WIDGET_CLICK";
|
|
|
|
|
|
|
|
static void updateAppWidget(Context context, AppWidgetManager appWidgetManager,
|
|
|
|
int appWidgetId) {
|
|
|
|
|
|
|
|
// Construct the RemoteViews object
|
|
|
|
RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.sleep_alarm_widget);
|
|
|
|
|
|
|
|
// Add our own click intent
|
2019-01-10 23:50:02 +01:00
|
|
|
Intent intent = new Intent(context, SleepAlarmWidget.class);
|
2022-05-28 14:57:01 +02:00
|
|
|
intent.setAction(ACTION_CLICK);
|
|
|
|
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
|
2016-02-29 21:36:39 +01:00
|
|
|
PendingIntent clickPI = PendingIntent.getBroadcast(
|
2022-05-28 14:57:01 +02:00
|
|
|
context, appWidgetId, intent, PendingIntent.FLAG_UPDATE_CURRENT);
|
2016-02-29 21:36:39 +01:00
|
|
|
views.setOnClickPendingIntent(R.id.sleepalarmwidget_text, clickPI);
|
|
|
|
|
|
|
|
// Instruct the widget manager to update the widget
|
|
|
|
appWidgetManager.updateAppWidget(appWidgetId, views);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
|
|
|
|
// There may be multiple widgets active, so update all of them
|
|
|
|
for (int appWidgetId : appWidgetIds) {
|
|
|
|
updateAppWidget(context, appWidgetManager, appWidgetId);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onEnabled(Context context) {
|
|
|
|
// Enter relevant functionality for when the first widget is created
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onDisabled(Context context) {
|
|
|
|
// Enter relevant functionality for when the last widget is disabled
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onReceive(Context context, Intent intent) {
|
|
|
|
super.onReceive(context, intent);
|
2022-05-28 14:57:01 +02:00
|
|
|
Bundle extras = intent.getExtras();
|
|
|
|
int appWidgetId = -1;
|
|
|
|
if (extras != null) {
|
|
|
|
appWidgetId = extras.getInt(
|
|
|
|
AppWidgetManager.EXTRA_APPWIDGET_ID,
|
|
|
|
AppWidgetManager.INVALID_APPWIDGET_ID);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ACTION_CLICK.equals(intent.getAction())) {
|
2021-12-05 10:32:35 +01:00
|
|
|
int userSleepDuration = new ActivityUser().getSleepDurationGoal();
|
2016-02-29 21:36:39 +01:00
|
|
|
// current timestamp
|
|
|
|
GregorianCalendar calendar = new GregorianCalendar();
|
|
|
|
// add preferred sleep duration
|
2019-01-10 23:50:02 +01:00
|
|
|
if (userSleepDuration > 0) {
|
|
|
|
calendar.add(Calendar.HOUR_OF_DAY, userSleepDuration);
|
|
|
|
} else { // probably testing
|
|
|
|
calendar.add(Calendar.MINUTE, 1);
|
2016-03-02 00:05:58 +01:00
|
|
|
}
|
2016-02-29 21:36:39 +01:00
|
|
|
|
2019-01-10 23:50:02 +01:00
|
|
|
// overwrite the first alarm and activate it, without
|
|
|
|
|
2022-05-28 14:57:01 +02:00
|
|
|
GBDevice deviceForWidget = new WidgetPreferenceStorage().getDeviceForWidget(appWidgetId);
|
|
|
|
if (deviceForWidget == null || !deviceForWidget.isInitialized()) {
|
|
|
|
GB.toast(context, context.getString(R.string.appwidget_not_connected),
|
|
|
|
Toast.LENGTH_SHORT, GB.WARN);
|
|
|
|
return;
|
2019-01-10 23:50:02 +01:00
|
|
|
}
|
2016-10-20 20:08:17 +02:00
|
|
|
|
2019-01-11 00:03:17 +01:00
|
|
|
int hours = calendar.get(Calendar.HOUR_OF_DAY);
|
|
|
|
int minutes = calendar.get(Calendar.MINUTE);
|
|
|
|
|
|
|
|
GB.toast(context,
|
|
|
|
context.getString(R.string.appwidget_setting_alarm, hours, minutes),
|
|
|
|
Toast.LENGTH_SHORT, GB.INFO);
|
|
|
|
|
2020-01-12 08:12:21 +01:00
|
|
|
Alarm alarm = AlarmUtils.createSingleShot(0, true, false, calendar);
|
2019-01-10 23:50:02 +01:00
|
|
|
ArrayList<Alarm> alarms = new ArrayList<>(1);
|
|
|
|
alarms.add(alarm);
|
|
|
|
GBApplication.deviceService().onSetAlarms(alarms);
|
|
|
|
|
|
|
|
// if (GBApplication.isRunningLollipopOrLater()) {
|
|
|
|
// setAlarmViaAlarmManager(context, calendar.getTimeInMillis());
|
|
|
|
// }
|
2016-02-29 21:36:39 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Use the Android alarm manager to create the alarm icon in the status bar.
|
|
|
|
*
|
|
|
|
* @param packageContext {@code Context}: A Context of the application package implementing this
|
2016-03-02 00:05:58 +01:00
|
|
|
* class.
|
|
|
|
* @param triggerTime {@code long}: time at which the underlying alarm is triggered in wall time
|
|
|
|
* milliseconds since the epoch
|
2016-02-29 21:36:39 +01:00
|
|
|
*/
|
|
|
|
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
|
|
|
|
private void setAlarmViaAlarmManager(Context packageContext, long triggerTime) {
|
|
|
|
AlarmManager am = (AlarmManager) packageContext.getSystemService(Context.ALARM_SERVICE);
|
|
|
|
// TODO: launch the alarm configuration activity when clicking the alarm in the status bar
|
|
|
|
Intent intent = new Intent(packageContext, ConfigureAlarms.class);
|
|
|
|
PendingIntent pi = PendingIntent.getBroadcast(packageContext, 0, intent,
|
|
|
|
PendingIntent.FLAG_CANCEL_CURRENT);
|
|
|
|
am.setAlarmClock(new AlarmManager.AlarmClockInfo(triggerTime, pi), pi);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|