Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

alarms reboot #653

Merged
merged 9 commits into from
Nov 22, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,7 @@
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<action android:name="android.intent.action.TIMEZONE_CHANGED" />
<action android:name="android.intent.action.MY_PACKAGE_REPLACED" />
<!--<action android:name="android.intent.action.TIME_SET" />-->
</intent-filter>
<intent-filter>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,10 @@
import android.app.Dialog;
import android.app.KeyguardManager;
import android.app.ProgressDialog;
import android.content.BroadcastReceiver;
import android.content.ActivityNotFoundException;
import android.content.ComponentName;
import android.content.ContentUris;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
Expand All @@ -37,6 +39,8 @@
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.preference.CheckBoxPreference;
import android.preference.ListPreference;
import android.preference.Preference;
Expand Down Expand Up @@ -129,6 +133,7 @@ public class SuntimesSettingsActivity extends PreferenceActivity implements Shar
private Context context;
private PlacesPrefsBase placesPrefBase = null;
private String appTheme = null;
private static SuntimesUtils utils = new SuntimesUtils();

public SuntimesSettingsActivity()
{
Expand Down Expand Up @@ -326,6 +331,7 @@ public void onDestroy()

private void initLocale(Bundle icicle)
{
SuntimesUtils.initDisplayStrings(context);
WidgetSettings.initDefaults(context);

AppSettings.initDisplayStrings(context);
Expand Down Expand Up @@ -1599,13 +1605,45 @@ public void onCreate(Bundle savedInstanceState)
}
}

private final BroadcastReceiver updateAlarmPrefsReceiver = new BroadcastReceiver()
{
@Override
public void onReceive(Context context, Intent intent)
{
String action = intent.getAction();
Uri data = intent.getData();
Log.d(LOG_TAG, "updateAlarmPrefsReceiver.onReceive: " + data + " :: " + action);

if (action != null)
{
if (action.equals(AlarmNotifications.ACTION_UPDATE_UI))
{
new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
@Override
public void run() {
AlarmPrefsFragment.this.setBootCompletedPrefEnabled(true);
initPref_alarms_bootCompleted(AlarmPrefsFragment.this);
}
}, 500);
} else Log.e(LOG_TAG, "updateAlarmPrefsReceiver.onReceive: unrecognized action: " + action);
} else Log.e(LOG_TAG, "updateAlarmPrefsReceiver.onReceive: null action!");
}
};

@Override
public void onResume()
{
super.onResume();
getActivity().registerReceiver(updateAlarmPrefsReceiver, AlarmNotifications.getUpdateBroadcastIntentFilter(false));
initPref_alarms(AlarmPrefsFragment.this);
}

@Override
public void onPause() {
getActivity().unregisterReceiver(updateAlarmPrefsReceiver);
super.onPause();
}

public static final int REQUEST_PERMISSION_POWEROFFALARMS = 100;
protected boolean checkPermissions(Activity activity, boolean requestIfMissing)
{
Expand All @@ -1618,6 +1656,14 @@ protected boolean checkPermissions(Activity activity, boolean requestIfMissing)
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {}

protected void setBootCompletedPrefEnabled(boolean value)
{
final Preference pref = findPreference(AlarmSettings.PREF_KEY_ALARM_BOOTCOMPLETED);
if (pref != null) {
pref.setEnabled(value);
}
}
}

private void initPref_alarms()
Expand All @@ -1636,9 +1682,10 @@ private static void initPref_alarms(final AlarmPrefsFragment fragment)
return;
}

int[] colorAttrs = { R.attr.tagColor_warning };
int[] colorAttrs = { R.attr.tagColor_warning, R.attr.text_accentColor };
TypedArray typedArray = context.obtainStyledAttributes(colorAttrs);
int colorWarning = ContextCompat.getColor(context, typedArray.getResourceId(0, R.color.warningTag_dark));
int accentColor = ContextCompat.getColor(context, typedArray.getResourceId(1, R.color.text_accent_dark));
typedArray.recycle();

Preference batteryOptimization = fragment.findPreference(AlarmSettings.PREF_KEY_ALARM_BATTERYOPT);
Expand Down Expand Up @@ -1709,6 +1756,8 @@ public boolean onPreferenceChange(Preference preference, Object newValue)
powerOffAlarmsPref.setSummary(context.getString(R.string.configLabel_alarms_poweroffalarms_summary, findPermission(context, AlarmNotifications.PERMISSION_POWEROFFALARM)));
}

initPref_alarms_bootCompleted(fragment);

Preference showLauncher = fragment.findPreference(AlarmSettings.PREF_KEY_ALARM_SHOWLAUNCHER);
if (showLauncher != null)
{
Expand All @@ -1732,6 +1781,50 @@ public boolean onPreferenceChange(Preference preference, Object newValue)
}
}

@TargetApi(Build.VERSION_CODES.HONEYCOMB)
private static void initPref_alarms_bootCompleted(final AlarmPrefsFragment fragment)
{
final Context context = fragment.getActivity();
if (context == null) {
return;
}

final Preference bootCompletedPref = fragment.findPreference(AlarmSettings.PREF_KEY_ALARM_BOOTCOMPLETED);
if (bootCompletedPref != null)
{
bootCompletedPref.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener()
{
@Override
public boolean onPreferenceClick(Preference preference)
{
AlertDialog.Builder confirm = new AlertDialog.Builder(context)
.setMessage(context.getString(R.string.configLabel_alarms_bootcompleted_action_confirm))
.setIcon(android.R.drawable.ic_dialog_alert)
.setPositiveButton(context.getString(R.string.dialog_ok), new DialogInterface.OnClickListener()
{
public void onClick(DialogInterface dialog, int whichButton)
{
bootCompletedPref.setEnabled(false);
context.sendBroadcast(new Intent(AlarmNotifications.getAlarmIntent(context, AlarmNotifications.ACTION_SCHEDULE, null)));
}
})
.setNegativeButton(context.getString(R.string.dialog_cancel), null);
confirm.show();
return true;
}
});

AlarmSettings.BootCompletedInfo bootCompletedInfo = AlarmSettings.loadPrefLastBootCompleted(context);
long lastRunMillis = bootCompletedInfo.getTimeMillis();
String lastBootCompleted = utils.calendarDateTimeDisplayString(context, lastRunMillis).toString();
String afterDelay = (lastRunMillis >= 0 ? utils.timeDeltaLongDisplayString(0, bootCompletedInfo.getAtElapsedMillis(), true).getValue() : "");
String took = (lastRunMillis >= 0 ? bootCompletedInfo.getDurationMillis() + "ms": "");
CharSequence infoSpan = (lastRunMillis >= 0 ? context.getString(R.string.configLabel_alarms_bootcompleted_info, lastBootCompleted, afterDelay, took)
: context.getString(R.string.configLabel_alarms_bootcompleted_info_never));
bootCompletedPref.setSummary(context.getString(R.string.configLabel_alarms_bootcompleted_summary, infoSpan));
}
}

private static void removePrefFromCategory(Preference pref, PreferenceCategory category)
{
if (pref != null && category != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.SystemClock;
import android.os.Vibrator;
import android.provider.Settings;
import android.support.annotation.NonNull;
Expand All @@ -58,6 +60,7 @@
import android.widget.Toast;

import com.forrestguice.suntimeswidget.R;
import com.forrestguice.suntimeswidget.SuntimesSettingsActivity;
import com.forrestguice.suntimeswidget.SuntimesUtils;
import com.forrestguice.suntimeswidget.alarmclock.ui.AlarmClockActivity;
import com.forrestguice.suntimeswidget.alarmclock.ui.AlarmDismissActivity;
Expand Down Expand Up @@ -100,6 +103,9 @@ public class AlarmNotifications extends BroadcastReceiver
public static final String EXTRA_NOTIFICATION_ID = "notificationID";
public static final String ALARM_NOTIFICATION_TAG = "suntimesalarm";

public static final int NOTIFICATION_SCHEDULE_ALL_ID = -10;
public static final int NOTIFICATION_SCHEDULE_ALL_DURATION = 4000;

private static SuntimesUtils utils = new SuntimesUtils();

/**
Expand Down Expand Up @@ -406,7 +412,11 @@ protected static Intent getPowerOffAlarmIntent(@Nullable String action, long dat
////////////////////////////////////////////////////////////////////////////////////////////////

public static Intent getServiceIntent(Context context) {
return new Intent(context, NotificationService.class);
Intent intent = new Intent(context, NotificationService.class);
if (Build.VERSION.SDK_INT >= 16) {
intent.setFlags(Intent.FLAG_RECEIVER_FOREGROUND);
}
return intent;
}

public static Intent getFullscreenIntent(Context context, Uri data)
Expand All @@ -425,11 +435,16 @@ public static Intent getFullscreenBroadcast(Uri data)
return intent;
}

public static IntentFilter getUpdateBroadcastIntentFilter()
public static IntentFilter getUpdateBroadcastIntentFilter() {
return getUpdateBroadcastIntentFilter(true);
}
public static IntentFilter getUpdateBroadcastIntentFilter(boolean withData)
{
IntentFilter filter = new IntentFilter();
filter.addAction(ACTION_UPDATE_UI);
filter.addDataScheme("content");
if (withData) {
filter.addDataScheme("content");
}
return filter;
}

Expand Down Expand Up @@ -935,6 +950,27 @@ public static Notification createNotification(Context context, @NonNull AlarmClo
return builder.build();
}

public static Notification createProgressNotification(Context context, String title, String message)
{
NotificationCompat.Builder builder = new NotificationCompat.Builder(context);
builder.setDefaults(Notification.DEFAULT_LIGHTS);
builder.setPriority(NotificationCompat.PRIORITY_HIGH);
builder.setCategory(NotificationCompat.CATEGORY_PROGRESS);
builder.setProgress(0,0,true);
builder.setAutoCancel(false);
builder.setOngoing(true);
builder.setContentTitle(title);
builder.setContentText(message);
builder.setSmallIcon(R.drawable.ic_action_alarms_light);
//builder.setColor(ContextCompat.getColor(context, R.color.sunIcon_color_setting_dark))
builder.setVisibility(NotificationCompat.VISIBILITY_PUBLIC);
builder.setOnlyAlertOnce(false);

PendingIntent pendingView = PendingIntent.getActivity(context, title.hashCode(), getAlarmListIntent(context, null), PendingIntent.FLAG_UPDATE_CURRENT);
builder.addAction(R.drawable.ic_action_settings, context.getString(R.string.app_name_alarmclock), pendingView);
return builder.build();
}

public static String formatOffsetMessage(Context context, long offset, long timestamp, @NonNull AlarmEvent.AlarmEventItem event)
{
String eventString = event.getEventID();
Expand Down Expand Up @@ -1172,21 +1208,35 @@ public int onStartCommand(final Intent intent, int flags, final int startId)
itemTask.execute(ContentUris.parseId(data));

} else {
if (AlarmNotifications.ACTION_SCHEDULE.equals(action) || Intent.ACTION_BOOT_COMPLETED.equals(action))
if (AlarmNotifications.ACTION_SCHEDULE.equals(action) || Intent.ACTION_BOOT_COMPLETED.equals(action) || Intent.ACTION_MY_PACKAGE_REPLACED.equals(action))
{
Log.d(TAG, action + ": schedule all");
Log.d(TAG, action + ": schedule all (prevCompleted=" + AlarmSettings.bootCompletedWasRun(getApplicationContext()) + ")");
final long startTime = SystemClock.elapsedRealtime();
AlarmSettings.savePrefLastBootCompleted_started(getApplicationContext(), startTime);

AlarmDatabaseAdapter.AlarmListTask alarmListTask = new AlarmDatabaseAdapter.AlarmListTask(getApplicationContext());
alarmListTask.setParam_enabledOnly(true);
alarmListTask.setAlarmItemTaskListener(new AlarmDatabaseAdapter.AlarmListTask.AlarmListTaskListener() {
@Override
public void onItemsLoaded(Long[] ids)
public void onItemsLoaded(final Long[] ids)
{
final AlarmDatabaseAdapter.AlarmListObserver observer = new AlarmDatabaseAdapter.AlarmListObserver(ids, new AlarmDatabaseAdapter.AlarmListObserver.AlarmListObserverListener()
{
@Override
public void onObservedAll() {
Log.d(TAG, "schedule all completed");
notifications.stopSelf(startId);
final long endTime = SystemClock.elapsedRealtime();
final long duration = endTime - startTime;
AlarmSettings.savePrefLastBootCompleted_finished(getApplicationContext(), System.currentTimeMillis(), duration);
Log.d(TAG, "schedule all completed (took " + duration + "ms); " + AlarmSettings.bootCompletedWasRun(getApplicationContext()));
new Handler(Looper.getMainLooper()).postDelayed(new Runnable()
{
@Override
public void run() {
notifications.dismissNotification(getApplicationContext(), NOTIFICATION_SCHEDULE_ALL_ID);
sendBroadcast(getFullscreenBroadcast(null));
notifications.stopSelf(startId);
}
}, (ids.length > 0 ? NOTIFICATION_SCHEDULE_ALL_DURATION : 0));
}
});

Expand All @@ -1211,6 +1261,7 @@ public void onFinished(Boolean result, AlarmClockItem item) {
}
}
});
notifications.startForeground(NOTIFICATION_SCHEDULE_ALL_ID, createProgressNotification(getApplicationContext(), getString(R.string.app_name_alarmclock), getString(R.string.configLabel_alarms_bootcompleted_action_message)));
alarmListTask.execute();

} else if (Intent.ACTION_TIMEZONE_CHANGED.equals(action)) {
Expand All @@ -1227,6 +1278,7 @@ public void onFinished(Boolean result, AlarmClockItem item) {
if (tzOffset != tzOffset_prev)
{
Log.i(TAG, "system tz offset changed from " + tzOffset_prev + " to " + tzOffset);
notifications.startForeground(NOTIFICATION_SCHEDULE_ALL_ID, createProgressNotification(getApplicationContext(), getString(R.string.app_name_alarmclock), getString(R.string.configLabel_alarms_bootcompleted_action_message)));
findEnabledAlarms(getApplicationContext(), rescheduleTaskListener_clocktime(startId));
rescheduling = true;
}
Expand Down Expand Up @@ -1283,12 +1335,23 @@ private AlarmDatabaseAdapter.AlarmListTask.AlarmListTaskListener rescheduleTaskL
return new AlarmDatabaseAdapter.AlarmListTask.AlarmListTaskListener()
{
@Override
public void onItemsLoaded(Long[] ids) {
public void onItemsLoaded(final Long[] ids)
{
final long startedAt = System.currentTimeMillis();
final AlarmDatabaseAdapter.AlarmListObserver observer = new AlarmDatabaseAdapter.AlarmListObserver(ids, new AlarmDatabaseAdapter.AlarmListObserver.AlarmListObserverListener() {
@Override
public void onObservedAll() {
Log.d(TAG, "Re-schedule completed (time zone changed)");
notifications.stopSelf(startId);
public void onObservedAll()
{
long duration = System.currentTimeMillis() - startedAt;
Log.d(TAG, "Re-schedule completed (time zone changed); took " + duration + "ms");
new Handler(Looper.getMainLooper()).postDelayed(new Runnable()
{
@Override
public void run() {
notifications.dismissNotification(getApplicationContext(), NOTIFICATION_SCHEDULE_ALL_ID);
notifications.stopSelf(startId);
}
}, (ids.length > 0 ? NOTIFICATION_SCHEDULE_ALL_DURATION : 0));
}
});
if (ids.length == 0) {
Expand Down Expand Up @@ -1790,6 +1853,7 @@ public void onFinished(Boolean result, AlarmClockItem item)
{
Log.d(TAG, "State Saved (onScheduledNotification)");
addAlarmTimeout(context, ACTION_SHOW, item.getUri(), item.alarmtime);
context.sendBroadcast(getFullscreenBroadcast(item.getUri()));
}
if (chained != null) {
chained.onFinished(true, item);
Expand All @@ -1813,6 +1877,7 @@ public void onFinished(Boolean result, final AlarmClockItem item)
addAlarmTimeout(context, ACTION_SHOW, item.getUri(), item.alarmtime);
//context.startActivity(getAlarmListIntent(context, item.rowID)); // open the alarm list
notifications.dismissNotification(context, (int)item.rowID);
context.sendBroadcast(getFullscreenBroadcast(item.getUri()));

findUpcomingAlarm(context, new AlarmDatabaseAdapter.AlarmListTask.AlarmListTaskListener() {
@Override
Expand Down Expand Up @@ -1847,6 +1912,7 @@ public void onFinished(Boolean result, final AlarmClockItem item)
if (AlarmSettings.loadPrefAlarmUpcoming(context) > 0) {
notifications.showNotification(context, item, true); // show upcoming reminder
}
context.sendBroadcast(getFullscreenBroadcast(item.getUri()));

findUpcomingAlarm(context, new AlarmDatabaseAdapter.AlarmListTask.AlarmListTaskListener() {
@Override
Expand Down
Loading