diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index f695715..4193831 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -79,7 +79,7 @@ android:name="io.flutter.plugins.androidalarmmanager.RebootBroadcastReceiver" android:enabled="false"> - + diff --git a/android/app/src/main/java/com/keyboardcrumbs/hassclient/NextAlarmBroadcastReceiver.java b/android/app/src/main/java/com/keyboardcrumbs/hassclient/NextAlarmBroadcastReceiver.java index c31a407..36b4729 100644 --- a/android/app/src/main/java/com/keyboardcrumbs/hassclient/NextAlarmBroadcastReceiver.java +++ b/android/app/src/main/java/com/keyboardcrumbs/hassclient/NextAlarmBroadcastReceiver.java @@ -4,25 +4,21 @@ import android.app.AlarmManager; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; -import android.util.Log; -import android.webkit.URLUtil; +import androidx.work.BackoffPolicy; +import androidx.work.Constraints; +import androidx.work.ExistingWorkPolicy; +import androidx.work.NetworkType; +import androidx.work.OneTimeWorkRequest; +import androidx.work.WorkManager; +import androidx.work.WorkRequest; -import java.text.SimpleDateFormat; -import java.util.Calendar; -import java.util.Locale; - -import org.json.JSONArray; -import org.json.JSONObject; -import android.content.SharedPreferences; +import java.util.concurrent.TimeUnit; public class NextAlarmBroadcastReceiver extends BroadcastReceiver { private static final String TAG = "NextAlarmReceiver"; - private static final SimpleDateFormat DATE_TIME_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:00", Locale.ENGLISH); - private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd", Locale.ENGLISH); - private static final SimpleDateFormat TIME_FORMAT = new SimpleDateFormat("HH:mm:00", Locale.ENGLISH); @Override public void onReceive(Context context, Intent intent) { @@ -35,63 +31,21 @@ public class NextAlarmBroadcastReceiver extends BroadcastReceiver { if (!isBootIntent && !isNextAlarmIntent) { return; } - final AlarmManager alarmManager; - if (android.os.Build.VERSION.SDK_INT >= 23) { - alarmManager = context.getSystemService(AlarmManager.class); - } else { - alarmManager = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE); - } + Constraints constraints = new Constraints.Builder() + .setRequiredNetworkType(NetworkType.CONNECTED) + .build(); - final AlarmManager.AlarmClockInfo alarmClockInfo = alarmManager.getNextAlarmClock(); + OneTimeWorkRequest uploadWorkRequest = + new OneTimeWorkRequest.Builder(UpdateNextAlarmWorker.class) + .setBackoffCriteria( + BackoffPolicy.EXPONENTIAL, + 10, + TimeUnit.SECONDS) + .setConstraints(constraints) + .build(); - SharedPreferences prefs = context.getSharedPreferences("FlutterSharedPreferences", Context.MODE_PRIVATE); - String webhookId = prefs.getString("flutter.app-webhook-id", null); - if (webhookId != null) { - try { - String requestUrl = prefs.getString("flutter.hassio-res-protocol", "") + - "://" + - prefs.getString("flutter.hassio-domain", "") + - ":" + - prefs.getString("flutter.hassio-port", "") + "/api/webhook/" + webhookId; - JSONObject dataToSend = new JSONObject(); - if (URLUtil.isValidUrl(requestUrl)) { - dataToSend.put("type", "update_sensor_states"); - JSONArray dataArray = new JSONArray(); - JSONObject sensorData = new JSONObject(); - JSONObject sensorAttrs = new JSONObject(); - sensorData.put("unique_id", "next_alarm"); - sensorData.put("type", "sensor"); - final long triggerTimestamp; - if (alarmClockInfo != null) { - triggerTimestamp = alarmClockInfo.getTriggerTime(); - final Calendar calendar = Calendar.getInstance(); - calendar.setTimeInMillis(triggerTimestamp); - sensorData.put("state", DATE_TIME_FORMAT.format(calendar.getTime())); - sensorAttrs.put("date", DATE_FORMAT.format(calendar.getTime())); - sensorAttrs.put("time", TIME_FORMAT.format(calendar.getTime())); - sensorAttrs.put("timestamp", triggerTimestamp); - } else { - sensorData.put("state", ""); - sensorAttrs.put("date", ""); - sensorAttrs.put("time", ""); - sensorAttrs.put("timestamp", 0); - } - sensorData.put("icon", "mdi:alarm"); - sensorData.put("attributes", sensorAttrs); - dataArray.put(0, sensorData); - dataToSend.put("data", dataArray); - - String stringRequest = dataToSend.toString(); - SendTask sendTask = new SendTask(); - sendTask.execute(requestUrl, stringRequest); - } else { - Log.w(TAG, "Invalid HA url"); - } - } catch (Exception e) { - Log.e(TAG, "Error setting next alarm", e); - } - } else { - Log.w(TAG, "Webhook id not found"); - } + WorkManager + .getInstance(context) + .enqueueUniqueWork("NextAlarmUpdate", ExistingWorkPolicy.REPLACE, uploadWorkRequest); } } \ No newline at end of file diff --git a/android/app/src/main/java/com/keyboardcrumbs/hassclient/NotificationActionReceiver.java b/android/app/src/main/java/com/keyboardcrumbs/hassclient/NotificationActionReceiver.java index ef23b80..8c2e266 100644 --- a/android/app/src/main/java/com/keyboardcrumbs/hassclient/NotificationActionReceiver.java +++ b/android/app/src/main/java/com/keyboardcrumbs/hassclient/NotificationActionReceiver.java @@ -15,7 +15,7 @@ import android.content.SharedPreferences; public class NotificationActionReceiver extends BroadcastReceiver { - private static final String TAG = "NotificationActionReceiver"; + private static final String TAG = "NotificationAction"; @Override public void onReceive(Context context, Intent intent) { diff --git a/android/app/src/main/java/com/keyboardcrumbs/hassclient/UpdateNextAlarmWorker.java b/android/app/src/main/java/com/keyboardcrumbs/hassclient/UpdateNextAlarmWorker.java new file mode 100644 index 0000000..a6d69a6 --- /dev/null +++ b/android/app/src/main/java/com/keyboardcrumbs/hassclient/UpdateNextAlarmWorker.java @@ -0,0 +1,119 @@ +package com.keyboardcrumbs.hassclient; + +import android.app.AlarmManager; +import android.content.Context; +import android.content.SharedPreferences; +import android.util.Log; +import android.webkit.URLUtil; + +import androidx.annotation.NonNull; +import androidx.work.Worker; +import androidx.work.WorkerParameters; + +import org.json.JSONArray; +import org.json.JSONObject; + +import java.io.OutputStream; +import java.net.HttpURLConnection; +import java.net.URL; +import java.text.SimpleDateFormat; +import java.util.Calendar; +import java.util.Locale; + +public class UpdateNextAlarmWorker extends Worker { + + private Context currentContext; + private static final String TAG = "NextAlarmWorker"; + private static final SimpleDateFormat DATE_TIME_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:00", Locale.ENGLISH); + private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd", Locale.ENGLISH); + private static final SimpleDateFormat TIME_FORMAT = new SimpleDateFormat("HH:mm:00", Locale.ENGLISH); + + public UpdateNextAlarmWorker(@NonNull Context context, @NonNull WorkerParameters workerParams) { + super(context, workerParams); + currentContext = context; + } + + @NonNull + @Override + public Result doWork() { + final AlarmManager alarmManager; + if (android.os.Build.VERSION.SDK_INT >= 23) { + alarmManager = currentContext.getSystemService(AlarmManager.class); + } else { + alarmManager = (AlarmManager)currentContext.getSystemService(Context.ALARM_SERVICE); + } + + final AlarmManager.AlarmClockInfo alarmClockInfo = alarmManager.getNextAlarmClock(); + + SharedPreferences prefs = currentContext.getSharedPreferences("FlutterSharedPreferences", Context.MODE_PRIVATE); + String webhookId = prefs.getString("flutter.app-webhook-id", null); + if (webhookId != null) { + try { + String requestUrl = prefs.getString("flutter.hassio-res-protocol", "") + + "://" + + prefs.getString("flutter.hassio-domain", "") + + ":" + + prefs.getString("flutter.hassio-port", "") + "/api/webhook/" + webhookId; + JSONObject dataToSend = new JSONObject(); + if (URLUtil.isValidUrl(requestUrl)) { + dataToSend.put("type", "update_sensor_states"); + JSONArray dataArray = new JSONArray(); + JSONObject sensorData = new JSONObject(); + JSONObject sensorAttrs = new JSONObject(); + sensorData.put("unique_id", "next_alarm"); + sensorData.put("type", "sensor"); + final long triggerTimestamp; + if (alarmClockInfo != null) { + triggerTimestamp = alarmClockInfo.getTriggerTime(); + final Calendar calendar = Calendar.getInstance(); + calendar.setTimeInMillis(triggerTimestamp); + sensorData.put("state", DATE_TIME_FORMAT.format(calendar.getTime())); + sensorAttrs.put("date", DATE_FORMAT.format(calendar.getTime())); + sensorAttrs.put("time", TIME_FORMAT.format(calendar.getTime())); + sensorAttrs.put("timestamp", triggerTimestamp); + } else { + sensorData.put("state", ""); + sensorAttrs.put("date", ""); + sensorAttrs.put("time", ""); + sensorAttrs.put("timestamp", 0); + } + sensorData.put("icon", "mdi:alarm"); + sensorData.put("attributes", sensorAttrs); + dataArray.put(0, sensorData); + dataToSend.put("data", dataArray); + + String stringRequest = dataToSend.toString(); + try { + URL url = new URL(requestUrl); + HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection(); + urlConnection.setRequestMethod("POST"); + urlConnection.setRequestProperty("Content-Type", "application/json"); + urlConnection.setDoOutput(true); + byte[] outputBytes = stringRequest.getBytes("UTF-8"); + OutputStream os = urlConnection.getOutputStream(); + os.write(outputBytes); + + int responseCode = urlConnection.getResponseCode(); + urlConnection.disconnect(); + if (responseCode >= 300) { + return Result.retry(); + } + } catch (Exception e) { + Log.e(TAG, "Error sending data", e); + return Result.retry(); + } + } else { + Log.w(TAG, "Invalid HA url"); + return Result.failure(); + } + } catch (Exception e) { + Log.e(TAG, "Error setting next alarm", e); + return Result.failure(); + } + } else { + Log.w(TAG, "Webhook id not found"); + return Result.failure(); + } + return Result.success(); + } +}