mirror of
https://codeberg.org/Freeyourgadget/Gadgetbridge.git
synced 2026-07-31 07:44:24 +02:00
Extract GBDeviceEvent to each individual event
This commit is contained in:
+110
@@ -18,10 +18,120 @@
|
||||
package nodomain.freeyourgadget.gadgetbridge.deviceevents;
|
||||
|
||||
|
||||
import android.app.NotificationManager;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Build;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.R;
|
||||
import nodomain.freeyourgadget.gadgetbridge.externalevents.opentracks.OpenTracksController;
|
||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||
|
||||
public abstract class GBDeviceEvent {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(GBDeviceEvent.class);
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public String toString() {
|
||||
return getClass().getSimpleName() + ": ";
|
||||
}
|
||||
|
||||
public abstract void evaluate(final Context context, final GBDevice device);
|
||||
|
||||
/**
|
||||
* Helper method to run specific actions configured in the device preferences, upon wear state
|
||||
* or awake/asleep events.
|
||||
*
|
||||
* @param actions
|
||||
* @param message
|
||||
*/
|
||||
protected void handleDeviceAction(final Context context, final GBDevice device, Set<String> actions, String message) {
|
||||
if (actions.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
LOG.debug("Handing device actions: {}", TextUtils.join(",", actions));
|
||||
|
||||
final String actionBroadcast = context.getString(R.string.pref_device_action_broadcast_value);
|
||||
final String actionFitnessControlStart = context.getString(R.string.pref_device_action_fitness_app_control_start_value);
|
||||
final String actionFitnessControlStop = context.getString(R.string.pref_device_action_fitness_app_control_stop_value);
|
||||
final String actionFitnessControlToggle = context.getString(R.string.pref_device_action_fitness_app_control_toggle_value);
|
||||
final String actionMediaPlay = context.getString(R.string.pref_media_play_value);
|
||||
final String actionMediaPause = context.getString(R.string.pref_media_pause_value);
|
||||
final String actionMediaPlayPause = context.getString(R.string.pref_media_playpause_value);
|
||||
final String actionDndOff = context.getString(R.string.pref_device_action_dnd_off_value);
|
||||
final String actionDndpriority = context.getString(R.string.pref_device_action_dnd_priority_value);
|
||||
final String actionDndAlarms = context.getString(R.string.pref_device_action_dnd_alarms_value);
|
||||
final String actionDndOn = context.getString(R.string.pref_device_action_dnd_on_value);
|
||||
|
||||
if (actions.contains(actionBroadcast)) {
|
||||
if (message != null) {
|
||||
Intent in = new Intent();
|
||||
in.setAction(message);
|
||||
LOG.info("Sending broadcast {}", message);
|
||||
context.getApplicationContext().sendBroadcast(in);
|
||||
}
|
||||
}
|
||||
|
||||
if (actions.contains(actionFitnessControlStart)) {
|
||||
OpenTracksController.startRecording(context);
|
||||
} else if (actions.contains(actionFitnessControlStop)) {
|
||||
OpenTracksController.stopRecording(context);
|
||||
} else if (actions.contains(actionFitnessControlToggle)) {
|
||||
OpenTracksController.toggleRecording(context);
|
||||
}
|
||||
|
||||
final String mediaAction;
|
||||
if (actions.contains(actionMediaPlayPause)) {
|
||||
mediaAction = actionMediaPlayPause;
|
||||
} else if (actions.contains(actionMediaPause)) {
|
||||
mediaAction = actionMediaPause;
|
||||
} else if (actions.contains(actionMediaPlay)) {
|
||||
mediaAction = actionMediaPlay;
|
||||
} else {
|
||||
mediaAction = null;
|
||||
}
|
||||
|
||||
if (mediaAction != null) {
|
||||
GBDeviceEventMusicControl deviceEventMusicControl = new GBDeviceEventMusicControl();
|
||||
deviceEventMusicControl.event = GBDeviceEventMusicControl.Event.valueOf(mediaAction);
|
||||
deviceEventMusicControl.evaluate(context, device);
|
||||
}
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
final NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
|
||||
final int interruptionFilter;
|
||||
if (actions.contains(actionDndOff)) {
|
||||
interruptionFilter = NotificationManager.INTERRUPTION_FILTER_ALL;
|
||||
} else if (actions.contains(actionDndpriority)) {
|
||||
interruptionFilter = NotificationManager.INTERRUPTION_FILTER_PRIORITY;
|
||||
} else if (actions.contains(actionDndAlarms)) {
|
||||
interruptionFilter = NotificationManager.INTERRUPTION_FILTER_ALARMS;
|
||||
} else if (actions.contains(actionDndOn)) {
|
||||
interruptionFilter = NotificationManager.INTERRUPTION_FILTER_NONE;
|
||||
} else {
|
||||
interruptionFilter = NotificationManager.INTERRUPTION_FILTER_UNKNOWN;
|
||||
}
|
||||
|
||||
if (interruptionFilter != NotificationManager.INTERRUPTION_FILTER_UNKNOWN) {
|
||||
LOG.debug("Setting do not disturb to {}", interruptionFilter);
|
||||
|
||||
if (!notificationManager.isNotificationPolicyAccessGranted()) {
|
||||
LOG.warn("Do not disturb permissions not granted");
|
||||
}
|
||||
|
||||
notificationManager.setInterruptionFilter(interruptionFilter);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+30
-1
@@ -16,9 +16,38 @@
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>. */
|
||||
package nodomain.freeyourgadget.gadgetbridge.deviceevents;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
|
||||
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.activities.appmanager.AbstractAppManagerFragment;
|
||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDeviceApp;
|
||||
|
||||
public class GBDeviceEventAppInfo extends GBDeviceEvent {
|
||||
public GBDeviceApp apps[];
|
||||
private static final Logger LOG = LoggerFactory.getLogger(GBDeviceEventAppInfo.class);
|
||||
|
||||
public GBDeviceApp[] apps;
|
||||
public byte freeSlot = -1;
|
||||
|
||||
@Override
|
||||
public void evaluate(final Context context, final GBDevice device) {
|
||||
LOG.info("Got event for APP_INFO");
|
||||
|
||||
Intent appInfoIntent = new Intent(AbstractAppManagerFragment.ACTION_REFRESH_APPLIST);
|
||||
int appCount = apps.length;
|
||||
appInfoIntent.putExtra("app_count", appCount);
|
||||
for (int i = 0; i < appCount; i++) {
|
||||
appInfoIntent.putExtra("app_name" + i, apps[i].getName());
|
||||
appInfoIntent.putExtra("app_creator" + i, apps[i].getCreator());
|
||||
appInfoIntent.putExtra("app_version" + i, apps[i].getVersion());
|
||||
appInfoIntent.putExtra("app_uuid" + i, apps[i].getUUID().toString());
|
||||
appInfoIntent.putExtra("app_type" + i, apps[i].getType().ordinal());
|
||||
}
|
||||
LocalBroadcastManager.getInstance(context).sendBroadcast(appInfoIntent);
|
||||
}
|
||||
}
|
||||
|
||||
+9
@@ -16,14 +16,23 @@
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>. */
|
||||
package nodomain.freeyourgadget.gadgetbridge.deviceevents;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||
|
||||
public class GBDeviceEventAppManagement extends GBDeviceEvent {
|
||||
public Event event = Event.UNKNOWN;
|
||||
public EventType type = EventType.UNKNOWN;
|
||||
public int token = -1;
|
||||
public UUID uuid = null;
|
||||
|
||||
@Override
|
||||
public void evaluate(final Context context, final GBDevice device) {
|
||||
// FIXME: Pebble-specific, handled in support class
|
||||
}
|
||||
|
||||
public enum EventType {
|
||||
UNKNOWN,
|
||||
INSTALL,
|
||||
|
||||
+12
@@ -16,8 +16,14 @@
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>. */
|
||||
package nodomain.freeyourgadget.gadgetbridge.deviceevents;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||
|
||||
public class GBDeviceEventAppMessage extends GBDeviceEvent {
|
||||
public static int TYPE_APPMESSAGE = 0;
|
||||
public static int TYPE_ACK = 1;
|
||||
@@ -28,6 +34,7 @@ public class GBDeviceEventAppMessage extends GBDeviceEvent {
|
||||
public int id;
|
||||
public String message;
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public String toString() {
|
||||
return "GBDeviceEventAppMessage{" +
|
||||
@@ -37,4 +44,9 @@ public class GBDeviceEventAppMessage extends GBDeviceEvent {
|
||||
", id=" + id +
|
||||
'}';
|
||||
}
|
||||
|
||||
@Override
|
||||
public void evaluate(final Context context, final GBDevice device) {
|
||||
// FIXME: Pebble-specific, handled in support class
|
||||
}
|
||||
}
|
||||
|
||||
+105
-3
@@ -18,11 +18,31 @@
|
||||
package nodomain.freeyourgadget.gadgetbridge.deviceevents;
|
||||
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.text.DateFormat;
|
||||
import java.util.GregorianCalendar;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
|
||||
import nodomain.freeyourgadget.gadgetbridge.R;
|
||||
import nodomain.freeyourgadget.gadgetbridge.database.DBAccess;
|
||||
import nodomain.freeyourgadget.gadgetbridge.database.DBHandler;
|
||||
import nodomain.freeyourgadget.gadgetbridge.database.DBHelper;
|
||||
import nodomain.freeyourgadget.gadgetbridge.entities.BatteryLevel;
|
||||
import nodomain.freeyourgadget.gadgetbridge.entities.DaoSession;
|
||||
import nodomain.freeyourgadget.gadgetbridge.entities.Device;
|
||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.BatteryConfig;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.BatteryState;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.GB;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.preferences.DevicePrefs;
|
||||
|
||||
public class GBDeviceEventBatteryInfo extends GBDeviceEvent {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(GBDeviceEventBatteryInfo.class);
|
||||
|
||||
public GregorianCalendar lastChargeTime = null;
|
||||
public BatteryState state = BatteryState.UNKNOWN;
|
||||
public int batteryIndex = 0;
|
||||
@@ -31,9 +51,91 @@ public class GBDeviceEventBatteryInfo extends GBDeviceEvent {
|
||||
public float voltage = -1f;
|
||||
|
||||
public boolean extendedInfoAvailable() {
|
||||
if (numCharges != -1 && lastChargeTime != null) {
|
||||
return true;
|
||||
return numCharges != -1 && lastChargeTime != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void evaluate(final Context context, final GBDevice device) {
|
||||
LOG.info("Got BATTERY_INFO device event");
|
||||
device.setBatteryLevel(this.level, this.batteryIndex);
|
||||
device.setBatteryState(this.state, this.batteryIndex);
|
||||
device.setBatteryVoltage(this.voltage, this.batteryIndex);
|
||||
|
||||
final DevicePrefs devicePrefs = GBApplication.getDevicePrefs(device);
|
||||
final BatteryConfig batteryConfig = device.getDeviceCoordinator().getBatteryConfig(device)[this.batteryIndex];
|
||||
|
||||
if (this.level == GBDevice.BATTERY_UNKNOWN) {
|
||||
// no level available, just "high" or "low"
|
||||
GB.removeBatteryFullNotification(context);
|
||||
if (devicePrefs.getBatteryNotifyLowEnabled(batteryConfig) && BatteryState.BATTERY_LOW.equals(this.state)) {
|
||||
GB.updateBatteryLowNotification(context.getString(R.string.notif_battery_low, device.getAliasOrName()),
|
||||
this.extendedInfoAvailable() ?
|
||||
context.getString(R.string.notif_battery_low_extended, device.getAliasOrName(),
|
||||
context.getString(R.string.notif_battery_low_bigtext_last_charge_time, DateFormat.getDateTimeInstance().format(this.lastChargeTime.getTime())) +
|
||||
context.getString(R.string.notif_battery_low_bigtext_number_of_charges, String.valueOf(this.numCharges)))
|
||||
: ""
|
||||
, context);
|
||||
} else if (devicePrefs.getBatteryNotifyFullEnabled(batteryConfig) && BatteryState.BATTERY_CHARGING_FULL.equals(this.state)) {
|
||||
GB.removeBatteryLowNotification(context);
|
||||
GB.updateBatteryFullNotification(context.getString(R.string.notif_battery_full, device.getAliasOrName()), "", context);
|
||||
} else {
|
||||
GB.removeBatteryLowNotification(context);
|
||||
GB.removeBatteryFullNotification(context);
|
||||
}
|
||||
} else {
|
||||
new StoreDataTask("Storing battery data", context, device, this).execute();
|
||||
|
||||
final boolean batteryNotifyLowEnabled = devicePrefs.getBatteryNotifyLowEnabled(batteryConfig);
|
||||
final boolean isBatteryLow = this.level <= devicePrefs.getBatteryNotifyLowThreshold(batteryConfig) &&
|
||||
(BatteryState.BATTERY_LOW.equals(this.state) || BatteryState.BATTERY_NORMAL.equals(this.state));
|
||||
|
||||
final boolean batteryNotifyFullEnabled = devicePrefs.getBatteryNotifyFullEnabled(batteryConfig);
|
||||
final boolean isBatteryFull = this.level >= devicePrefs.getBatteryNotifyFullThreshold(batteryConfig) &&
|
||||
(BatteryState.BATTERY_CHARGING.equals(this.state) || BatteryState.BATTERY_CHARGING_FULL.equals(this.state));
|
||||
|
||||
//show the notification if the battery level is below threshold and only if not connected to charger
|
||||
if (batteryNotifyLowEnabled && isBatteryLow) {
|
||||
GB.removeBatteryFullNotification(context);
|
||||
GB.updateBatteryLowNotification(context.getString(R.string.notif_battery_low_percent, device.getAliasOrName(), String.valueOf(this.level)),
|
||||
this.extendedInfoAvailable() ?
|
||||
context.getString(R.string.notif_battery_low_percent, device.getAliasOrName(), String.valueOf(this.level)) + "\n" +
|
||||
context.getString(R.string.notif_battery_low_bigtext_last_charge_time, DateFormat.getDateTimeInstance().format(this.lastChargeTime.getTime())) +
|
||||
context.getString(R.string.notif_battery_low_bigtext_number_of_charges, String.valueOf(this.numCharges))
|
||||
: ""
|
||||
, context);
|
||||
} else if (batteryNotifyFullEnabled && isBatteryFull) {
|
||||
GB.removeBatteryLowNotification(context);
|
||||
GB.updateBatteryFullNotification(context.getString(R.string.notif_battery_full, device.getAliasOrName()), "", context);
|
||||
} else {
|
||||
GB.removeBatteryLowNotification(context);
|
||||
GB.removeBatteryFullNotification(context);
|
||||
}
|
||||
}
|
||||
|
||||
device.sendDeviceUpdateIntent(context);
|
||||
}
|
||||
|
||||
public static class StoreDataTask extends DBAccess {
|
||||
GBDeviceEventBatteryInfo deviceEvent;
|
||||
GBDevice gbDevice;
|
||||
|
||||
public StoreDataTask(String task, Context context, GBDevice device, GBDeviceEventBatteryInfo deviceEvent) {
|
||||
super(task, context);
|
||||
this.deviceEvent = deviceEvent;
|
||||
this.gbDevice = device;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doInBackground(DBHandler handler) {
|
||||
DaoSession daoSession = handler.getDaoSession();
|
||||
Device device = DBHelper.getDevice(gbDevice, daoSession);
|
||||
int ts = (int) (System.currentTimeMillis() / 1000);
|
||||
BatteryLevel batteryLevel = new BatteryLevel();
|
||||
batteryLevel.setTimestamp(ts);
|
||||
batteryLevel.setBatteryIndex(deviceEvent.batteryIndex);
|
||||
batteryLevel.setDevice(device);
|
||||
batteryLevel.setLevel(deviceEvent.level);
|
||||
handler.getDaoSession().getBatteryLevelDao().insert(batteryLevel);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
+27
@@ -17,7 +17,18 @@
|
||||
package nodomain.freeyourgadget.gadgetbridge.deviceevents;
|
||||
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.receivers.GBCallControlReceiver;
|
||||
|
||||
public class GBDeviceEventCallControl extends GBDeviceEvent {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(GBDeviceEventCallControl.class);
|
||||
|
||||
public Event event = Event.UNKNOWN;
|
||||
|
||||
public GBDeviceEventCallControl() {
|
||||
@@ -27,6 +38,22 @@ public class GBDeviceEventCallControl extends GBDeviceEvent {
|
||||
this.event = event;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void evaluate(final Context context, final GBDevice device) {
|
||||
LOG.info("Got event for CALL_CONTROL");
|
||||
if (event == GBDeviceEventCallControl.Event.IGNORE) {
|
||||
LOG.info("Sending intent for mute");
|
||||
final Intent broadcastIntent = new Intent(context.getPackageName() + ".MUTE_CALL");
|
||||
broadcastIntent.setPackage(context.getPackageName());
|
||||
context.sendBroadcast(broadcastIntent);
|
||||
return;
|
||||
}
|
||||
final Intent callIntent = new Intent(GBCallControlReceiver.ACTION_CALLCONTROL);
|
||||
callIntent.putExtra("event", event.ordinal());
|
||||
callIntent.setPackage(context.getPackageName());
|
||||
context.sendBroadcast(callIntent);
|
||||
}
|
||||
|
||||
public enum Event {
|
||||
UNKNOWN,
|
||||
ACCEPT,
|
||||
|
||||
+14
@@ -16,9 +16,23 @@
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>. */
|
||||
package nodomain.freeyourgadget.gadgetbridge.deviceevents;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.activities.CameraActivity;
|
||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||
|
||||
public class GBDeviceEventCameraRemote extends GBDeviceEvent {
|
||||
public Event event = Event.UNKNOWN;
|
||||
|
||||
@Override
|
||||
public void evaluate(final Context context, final GBDevice device) {
|
||||
final Intent cameraIntent = new Intent(context, CameraActivity.class);
|
||||
cameraIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
cameraIntent.putExtra(CameraActivity.intentExtraEvent, GBDeviceEventCameraRemote.eventToInt(event));
|
||||
context.startActivity(cameraIntent);
|
||||
}
|
||||
|
||||
public enum Event {
|
||||
UNKNOWN,
|
||||
OPEN_CAMERA,
|
||||
|
||||
+21
-1
@@ -16,7 +16,15 @@
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>. */
|
||||
package nodomain.freeyourgadget.gadgetbridge.deviceevents;
|
||||
|
||||
public class GBDeviceEventDisplayMessage {
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
|
||||
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.GB;
|
||||
|
||||
public class GBDeviceEventDisplayMessage extends GBDeviceEvent {
|
||||
public String message;
|
||||
public int duration;
|
||||
public int severity;
|
||||
@@ -35,4 +43,16 @@ public class GBDeviceEventDisplayMessage {
|
||||
this.duration = duration;
|
||||
this.severity = severity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void evaluate(final Context context, final GBDevice device) {
|
||||
GB.log(this.message, this.severity, null);
|
||||
|
||||
Intent messageIntent = new Intent(GB.ACTION_DISPLAY_MESSAGE);
|
||||
messageIntent.putExtra(GB.DISPLAY_MESSAGE_MESSAGE, this.message);
|
||||
messageIntent.putExtra(GB.DISPLAY_MESSAGE_DURATION, this.duration);
|
||||
messageIntent.putExtra(GB.DISPLAY_MESSAGE_SEVERITY, this.severity);
|
||||
|
||||
LocalBroadcastManager.getInstance(context).sendBroadcast(messageIntent);
|
||||
}
|
||||
}
|
||||
|
||||
+110
@@ -17,9 +17,119 @@
|
||||
|
||||
package nodomain.freeyourgadget.gadgetbridge.deviceevents;
|
||||
|
||||
import static nodomain.freeyourgadget.gadgetbridge.util.GB.NOTIFICATION_CHANNEL_HIGH_PRIORITY_ID;
|
||||
|
||||
import android.app.PendingIntent;
|
||||
import android.companion.CompanionDeviceManager;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
|
||||
import androidx.annotation.RequiresApi;
|
||||
import androidx.core.app.NotificationCompat;
|
||||
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.BuildConfig;
|
||||
import nodomain.freeyourgadget.gadgetbridge.R;
|
||||
import nodomain.freeyourgadget.gadgetbridge.activities.FindPhoneActivity;
|
||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.GB;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.PendingIntentUtils;
|
||||
|
||||
public class GBDeviceEventFindPhone extends GBDeviceEvent {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(GBDeviceEventFindPhone.class);
|
||||
|
||||
public Event event = Event.UNKNOWN;
|
||||
|
||||
@Override
|
||||
public void evaluate(final Context context, final GBDevice device) {
|
||||
LOG.info("Got GBDeviceEventFindPhone: {}", this.event);
|
||||
switch (this.event) {
|
||||
case START:
|
||||
handleGBDeviceEventFindPhoneStart(context, true);
|
||||
break;
|
||||
case START_VIBRATE:
|
||||
handleGBDeviceEventFindPhoneStart(context, false);
|
||||
break;
|
||||
case VIBRATE:
|
||||
final Intent intentVibrate = new Intent(FindPhoneActivity.ACTION_VIBRATE);
|
||||
intentVibrate.setPackage(BuildConfig.APPLICATION_ID);
|
||||
LocalBroadcastManager.getInstance(context).sendBroadcast(intentVibrate);
|
||||
break;
|
||||
case RING:
|
||||
final Intent intentRing = new Intent(FindPhoneActivity.ACTION_RING);
|
||||
intentRing.setPackage(BuildConfig.APPLICATION_ID);
|
||||
LocalBroadcastManager.getInstance(context).sendBroadcast(intentRing);
|
||||
break;
|
||||
case STOP:
|
||||
final Intent intentStop = new Intent(FindPhoneActivity.ACTION_FOUND);
|
||||
intentStop.setPackage(BuildConfig.APPLICATION_ID);
|
||||
LocalBroadcastManager.getInstance(context).sendBroadcast(intentStop);
|
||||
break;
|
||||
default:
|
||||
LOG.warn("unknown GBDeviceEventFindPhone");
|
||||
}
|
||||
}
|
||||
|
||||
private void handleGBDeviceEventFindPhoneStart(final Context context, final boolean ring) {
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) { // this could be used if app in foreground // TODO: Below Q?
|
||||
final Intent startIntent = new Intent(context, FindPhoneActivity.class);
|
||||
startIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
startIntent.putExtra(FindPhoneActivity.EXTRA_RING, ring);
|
||||
context.startActivity(startIntent);
|
||||
} else {
|
||||
handleGBDeviceEventFindPhoneStartNotification(context, ring);
|
||||
}
|
||||
}
|
||||
|
||||
@RequiresApi(Build.VERSION_CODES.Q)
|
||||
private void handleGBDeviceEventFindPhoneStartNotification(final Context context, final boolean ring) {
|
||||
LOG.info("Got handleGBDeviceEventFindPhoneStartNotification");
|
||||
final CompanionDeviceManager manager = (CompanionDeviceManager) context.getSystemService(Context.COMPANION_DEVICE_SERVICE);
|
||||
if (manager.getAssociations().isEmpty()) {
|
||||
// On Android Q and above, we need the device to be paired as companion. If it is not, display a notification
|
||||
// notifying the user and linking to further instructions
|
||||
final Intent instructionsIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("https://gadgetbridge.org/basics/pairing/companion-device/"));
|
||||
final PendingIntent pi = PendingIntentUtils.getActivity(context, 0, instructionsIntent, PendingIntent.FLAG_ONE_SHOT, false);
|
||||
final NotificationCompat.Builder notification = new NotificationCompat.Builder(context, NOTIFICATION_CHANNEL_HIGH_PRIORITY_ID)
|
||||
.setSmallIcon(R.drawable.ic_warning)
|
||||
.setOngoing(false)
|
||||
.setPriority(NotificationCompat.PRIORITY_HIGH)
|
||||
.setContentIntent(pi)
|
||||
.setAutoCancel(true)
|
||||
.setContentTitle(context.getString(R.string.find_my_phone_notification))
|
||||
.setContentText(context.getString(R.string.find_my_phone_companion_warning));
|
||||
|
||||
GB.notify(GB.NOTIFICATION_ID_PHONE_FIND, notification.build(), context);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
final Intent intent = new Intent(context, FindPhoneActivity.class);
|
||||
intent.setPackage(BuildConfig.APPLICATION_ID);
|
||||
intent.putExtra(FindPhoneActivity.EXTRA_RING, ring);
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
|
||||
final PendingIntent pi = PendingIntentUtils.getActivity(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT, false);
|
||||
|
||||
final NotificationCompat.Builder notification = new NotificationCompat.Builder(context, NOTIFICATION_CHANNEL_HIGH_PRIORITY_ID)
|
||||
.setSmallIcon(R.drawable.ic_notification)
|
||||
.setOngoing(false)
|
||||
.setFullScreenIntent(pi, true)
|
||||
.setPriority(NotificationCompat.PRIORITY_HIGH)
|
||||
.setAutoCancel(true)
|
||||
.setGroup("BackgroundService")
|
||||
.setContentTitle(context.getString(R.string.find_my_phone_notification));
|
||||
|
||||
GB.notify(GB.NOTIFICATION_ID_PHONE_FIND, notification.build(), context);
|
||||
context.startActivity(intent);
|
||||
LOG.debug("CompanionDeviceManager associations were found, starting intent");
|
||||
}
|
||||
|
||||
public enum Event {
|
||||
UNKNOWN,
|
||||
START,
|
||||
|
||||
+19
-1
@@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2018-2024 José Rebelo
|
||||
/* Copyright (C) 2018-2025 José Rebelo
|
||||
|
||||
This file is part of Gadgetbridge.
|
||||
|
||||
@@ -16,10 +16,28 @@
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>. */
|
||||
package nodomain.freeyourgadget.gadgetbridge.deviceevents;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||
|
||||
public class GBDeviceEventFmFrequency extends GBDeviceEvent {
|
||||
public final float frequency;
|
||||
|
||||
public GBDeviceEventFmFrequency(final float frequency) {
|
||||
this.frequency = frequency;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public String toString() {
|
||||
return super.toString() + "frequency: " + frequency;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void evaluate(final Context context, final GBDevice device) {
|
||||
device.setExtraInfo("fm_frequency", frequency);
|
||||
device.sendDeviceUpdateIntent(context);
|
||||
}
|
||||
}
|
||||
|
||||
+20
@@ -16,10 +16,30 @@
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>. */
|
||||
package nodomain.freeyourgadget.gadgetbridge.deviceevents;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||
|
||||
public class GBDeviceEventLEDColor extends GBDeviceEvent {
|
||||
public final int color;
|
||||
|
||||
public GBDeviceEventLEDColor(final int color) {
|
||||
this.color = color;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public String toString() {
|
||||
return super.toString() + "color: " + Integer.toHexString(this.color).toUpperCase(Locale.ROOT);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void evaluate(final Context context, final GBDevice device) {
|
||||
device.setExtraInfo("led_color", this.color);
|
||||
device.sendDeviceUpdateIntent(context);
|
||||
}
|
||||
}
|
||||
|
||||
+20
@@ -17,9 +17,29 @@
|
||||
package nodomain.freeyourgadget.gadgetbridge.deviceevents;
|
||||
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.receivers.GBMusicControlReceiver;
|
||||
|
||||
public class GBDeviceEventMusicControl extends GBDeviceEvent {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(GBDeviceEventMusicControl.class);
|
||||
|
||||
public Event event = Event.UNKNOWN;
|
||||
|
||||
@Override
|
||||
public void evaluate(final Context context, final GBDevice device) {
|
||||
LOG.info("Got event for MUSIC_CONTROL");
|
||||
final Intent musicIntent = new Intent(GBMusicControlReceiver.ACTION_MUSICCONTROL);
|
||||
musicIntent.putExtra("event", event.ordinal());
|
||||
musicIntent.setPackage(context.getPackageName());
|
||||
context.sendBroadcast(musicIntent);
|
||||
}
|
||||
|
||||
public enum Event {
|
||||
UNKNOWN,
|
||||
PLAY,
|
||||
|
||||
+68
@@ -16,13 +16,81 @@
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>. */
|
||||
package nodomain.freeyourgadget.gadgetbridge.deviceevents;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.telephony.SmsManager;
|
||||
|
||||
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
|
||||
import nodomain.freeyourgadget.gadgetbridge.externalevents.NotificationListener;
|
||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||
|
||||
public class GBDeviceEventNotificationControl extends GBDeviceEvent {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(GBDeviceEventNotificationControl.class);
|
||||
|
||||
public long handle;
|
||||
public String phoneNumber;
|
||||
public String reply;
|
||||
public String title;
|
||||
public Event event = Event.UNKNOWN;
|
||||
|
||||
@Override
|
||||
public void evaluate(final Context context, final GBDevice device) {
|
||||
LOG.info("Got NOTIFICATION CONTROL device event");
|
||||
final String action;
|
||||
switch (event) {
|
||||
case DISMISS:
|
||||
action = NotificationListener.ACTION_DISMISS;
|
||||
break;
|
||||
case DISMISS_ALL:
|
||||
action = NotificationListener.ACTION_DISMISS_ALL;
|
||||
break;
|
||||
case OPEN:
|
||||
action = NotificationListener.ACTION_OPEN;
|
||||
break;
|
||||
case MUTE:
|
||||
action = NotificationListener.ACTION_MUTE;
|
||||
break;
|
||||
case REPLY:
|
||||
if (phoneNumber == null) {
|
||||
phoneNumber = GBApplication.getIDSenderLookup().lookup((int) (handle >> 4));
|
||||
}
|
||||
if (phoneNumber != null) {
|
||||
LOG.info("Got notification reply for SMS from {} : {}", phoneNumber, reply);
|
||||
SmsManager.getDefault().sendTextMessage(phoneNumber, null, reply, null, null);
|
||||
return;
|
||||
} else {
|
||||
LOG.info("Got notification reply for notification id {} : {}", handle, reply);
|
||||
action = NotificationListener.ACTION_REPLY;
|
||||
}
|
||||
break;
|
||||
case UNKNOWN:
|
||||
default:
|
||||
LOG.error("Unknown notification control action {}", event);
|
||||
return;
|
||||
}
|
||||
|
||||
final Intent notificationListenerIntent = new Intent(action);
|
||||
notificationListenerIntent.putExtra("handle", handle);
|
||||
notificationListenerIntent.putExtra("title", title);
|
||||
if (reply != null) {
|
||||
final SharedPreferences prefs = GBApplication.getDeviceSpecificSharedPrefs(device.getAddress());
|
||||
String suffix = prefs.getString("canned_reply_suffix", null);
|
||||
if (suffix != null && !Objects.equals(suffix, "")) {
|
||||
reply += suffix;
|
||||
}
|
||||
notificationListenerIntent.putExtra("reply", reply);
|
||||
}
|
||||
LocalBroadcastManager.getInstance(context).sendBroadcast(notificationListenerIntent);
|
||||
}
|
||||
|
||||
public enum Event {
|
||||
UNKNOWN,
|
||||
DISMISS,
|
||||
|
||||
+79
@@ -16,7 +16,38 @@
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>. */
|
||||
package nodomain.freeyourgadget.gadgetbridge.deviceevents;
|
||||
|
||||
import static nodomain.freeyourgadget.gadgetbridge.util.GB.NOTIFICATION_CHANNEL_HIGH_PRIORITY_ID;
|
||||
|
||||
import android.app.Notification;
|
||||
import android.app.PendingIntent;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.net.Uri;
|
||||
|
||||
import androidx.core.app.NotificationCompat;
|
||||
import androidx.core.content.FileProvider;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.Locale;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.R;
|
||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.GB;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.PendingIntentUtils;
|
||||
|
||||
public class GBDeviceEventScreenshot extends GBDeviceEvent {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(GBDeviceEventScreenshot.class);
|
||||
|
||||
private static final int NOTIFICATION_ID_SCREENSHOT = 8000;
|
||||
|
||||
private final byte[] data;
|
||||
|
||||
public GBDeviceEventScreenshot(final byte[] data) {
|
||||
@@ -26,4 +57,52 @@ public class GBDeviceEventScreenshot extends GBDeviceEvent {
|
||||
public byte[] getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void evaluate(final Context context, final GBDevice device) {
|
||||
if (getData() == null) {
|
||||
LOG.warn("Screenshot data is null");
|
||||
return;
|
||||
}
|
||||
|
||||
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd-hhmmss", Locale.US);
|
||||
String filename = "screenshot_" + dateFormat.format(new Date()) + ".bmp";
|
||||
|
||||
try {
|
||||
final String fullpath = GB.writeScreenshot(this, filename);
|
||||
final Bitmap bmp = BitmapFactory.decodeFile(fullpath);
|
||||
final Intent intent = new Intent();
|
||||
intent.setAction(android.content.Intent.ACTION_VIEW);
|
||||
final Uri screenshotURI = FileProvider.getUriForFile(context, context.getApplicationContext().getPackageName() + ".screenshot_provider", new File(fullpath));
|
||||
intent.setDataAndType(screenshotURI, "image/*");
|
||||
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
||||
|
||||
final PendingIntent pIntent = PendingIntentUtils.getActivity(context, 0, intent, 0, false);
|
||||
|
||||
final Intent shareIntent = new Intent(Intent.ACTION_SEND);
|
||||
shareIntent.setType("image/*");
|
||||
shareIntent.putExtra(Intent.EXTRA_STREAM, screenshotURI);
|
||||
|
||||
final PendingIntent pendingShareIntent = PendingIntentUtils.getActivity(context, 0, Intent.createChooser(shareIntent, context.getString(R.string.share_screenshot)),
|
||||
PendingIntent.FLAG_UPDATE_CURRENT, false);
|
||||
|
||||
final NotificationCompat.Action action = new NotificationCompat.Action.Builder(android.R.drawable.ic_menu_share, context.getString(R.string.share), pendingShareIntent).build();
|
||||
|
||||
final Notification notification = new NotificationCompat.Builder(context, NOTIFICATION_CHANNEL_HIGH_PRIORITY_ID)
|
||||
.setContentTitle(context.getString(R.string.screenshot_taken))
|
||||
.setTicker(context.getString(R.string.screenshot_taken))
|
||||
.setContentText(filename)
|
||||
.setSmallIcon(R.drawable.ic_notification)
|
||||
.setStyle(new NotificationCompat.BigPictureStyle()
|
||||
.bigPicture(bmp))
|
||||
.setContentIntent(pIntent)
|
||||
.addAction(action)
|
||||
.setAutoCancel(true)
|
||||
.build();
|
||||
|
||||
GB.notify(NOTIFICATION_ID_SCREENSHOT, notification, context);
|
||||
} catch (IOException ex) {
|
||||
LOG.error("Error writing screenshot", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+9
@@ -16,6 +16,10 @@
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>. */
|
||||
package nodomain.freeyourgadget.gadgetbridge.deviceevents;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||
|
||||
public class GBDeviceEventSendBytes extends GBDeviceEvent {
|
||||
public byte[] encodedBytes;
|
||||
|
||||
@@ -25,4 +29,9 @@ public class GBDeviceEventSendBytes extends GBDeviceEvent {
|
||||
public GBDeviceEventSendBytes(final byte[] encodedBytes) {
|
||||
this.encodedBytes = encodedBytes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void evaluate(final Context context, final GBDevice device) {
|
||||
// Handled in support class
|
||||
}
|
||||
}
|
||||
|
||||
+19
-1
@@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2023-2024 José Rebelo
|
||||
/* Copyright (C) 2023-2025 José Rebelo
|
||||
|
||||
This file is part of Gadgetbridge.
|
||||
|
||||
@@ -16,6 +16,13 @@
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>. */
|
||||
package nodomain.freeyourgadget.gadgetbridge.deviceevents;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.SilentMode;
|
||||
|
||||
public class GBDeviceEventSilentMode extends GBDeviceEvent {
|
||||
private final boolean enabled;
|
||||
|
||||
@@ -26,4 +33,15 @@ public class GBDeviceEventSilentMode extends GBDeviceEvent {
|
||||
public boolean isEnabled() {
|
||||
return enabled;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public String toString() {
|
||||
return super.toString() + "enabled: " + enabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void evaluate(final Context context, final GBDevice device) {
|
||||
SilentMode.setPhoneSilentMode(device.getAddress(), isEnabled());
|
||||
}
|
||||
}
|
||||
|
||||
+52
-1
@@ -16,15 +16,66 @@
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>. */
|
||||
package nodomain.freeyourgadget.gadgetbridge.deviceevents;
|
||||
|
||||
import java.util.Locale;
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Locale;
|
||||
import java.util.Set;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
|
||||
import nodomain.freeyourgadget.gadgetbridge.R;
|
||||
import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst;
|
||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.SleepState;
|
||||
|
||||
public class GBDeviceEventSleepStateDetection extends GBDeviceEvent {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(GBDeviceEventSleepStateDetection.class);
|
||||
|
||||
public SleepState sleepState;
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public String toString() {
|
||||
return super.toString() + String.format(Locale.ROOT, "sleepState=%s", sleepState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void evaluate(final Context context, final GBDevice device) {
|
||||
if (this.sleepState == SleepState.UNKNOWN) {
|
||||
return;
|
||||
}
|
||||
|
||||
final String actionPreferenceKey, messagePreferenceKey;
|
||||
final int defaultBroadcastMessageResource;
|
||||
|
||||
switch (this.sleepState) {
|
||||
case AWAKE:
|
||||
actionPreferenceKey = DeviceSettingsPreferenceConst.PREF_DEVICE_ACTION_WOKE_UP_SELECTIONS;
|
||||
messagePreferenceKey = DeviceSettingsPreferenceConst.PREF_DEVICE_ACTION_WOKE_UP_BROADCAST;
|
||||
defaultBroadcastMessageResource = R.string.prefs_events_forwarding_wokeup_broadcast_default_value;
|
||||
break;
|
||||
case ASLEEP:
|
||||
actionPreferenceKey = DeviceSettingsPreferenceConst.PREF_DEVICE_ACTION_FELL_SLEEP_SELECTIONS;
|
||||
messagePreferenceKey = DeviceSettingsPreferenceConst.PREF_DEVICE_ACTION_FELL_SLEEP_BROADCAST;
|
||||
defaultBroadcastMessageResource = R.string.prefs_events_forwarding_fellsleep_broadcast_default_value;
|
||||
break;
|
||||
default:
|
||||
LOG.warn("Unable to deduce action and broadcast message preference key for sleep state {}", this.sleepState);
|
||||
return;
|
||||
}
|
||||
|
||||
final Set<String> actions = GBApplication.getDevicePrefs(device).getStringSet(actionPreferenceKey, Collections.emptySet());
|
||||
|
||||
if (actions.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
String broadcastMessage = GBApplication.getDevicePrefs(device).getString(messagePreferenceKey, context.getString(defaultBroadcastMessageResource));
|
||||
handleDeviceAction(context, device, actions, broadcastMessage);
|
||||
}
|
||||
}
|
||||
|
||||
+9
@@ -16,6 +16,9 @@
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>. */
|
||||
package nodomain.freeyourgadget.gadgetbridge.deviceevents;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.GenericItem;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.ItemWithDetails;
|
||||
|
||||
@@ -29,4 +32,10 @@ public class GBDeviceEventUpdateDeviceInfo extends GBDeviceEvent {
|
||||
public GBDeviceEventUpdateDeviceInfo(final String name, final String details) {
|
||||
this(new GenericItem(name, details));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void evaluate(final Context context, final GBDevice device) {
|
||||
device.addDeviceInfo(this.item);
|
||||
device.sendDeviceUpdateIntent(context);
|
||||
}
|
||||
}
|
||||
|
||||
+8
@@ -16,6 +16,8 @@
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>. */
|
||||
package nodomain.freeyourgadget.gadgetbridge.deviceevents;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||
|
||||
public class GBDeviceEventUpdateDeviceState extends GBDeviceEvent {
|
||||
@@ -24,4 +26,10 @@ public class GBDeviceEventUpdateDeviceState extends GBDeviceEvent {
|
||||
public GBDeviceEventUpdateDeviceState(final GBDevice.State state) {
|
||||
this.state = state;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void evaluate(final Context context, final GBDevice device) {
|
||||
device.setState(state);
|
||||
device.sendDeviceUpdateIntent(context, GBDevice.DeviceUpdateSubject.DEVICE_STATE);
|
||||
}
|
||||
}
|
||||
|
||||
+11
-1
@@ -16,6 +16,7 @@
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>. */
|
||||
package nodomain.freeyourgadget.gadgetbridge.deviceevents;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
@@ -25,6 +26,9 @@ import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
|
||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||
|
||||
public class GBDeviceEventUpdatePreferences extends GBDeviceEvent {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(GBDeviceEventUpdatePreferences.class);
|
||||
|
||||
@@ -55,12 +59,18 @@ public class GBDeviceEventUpdatePreferences extends GBDeviceEvent {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void evaluate(final Context context, final GBDevice device) {
|
||||
update(GBApplication.getDeviceSpecificSharedPrefs(device.getAddress()));
|
||||
device.sendDeviceUpdateIntent(context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a {@link SharedPreferences} instance with the preferences in the event.
|
||||
*
|
||||
* @param prefs the SharedPreferences object to update.
|
||||
*/
|
||||
public void update(final SharedPreferences prefs) {
|
||||
private void update(final SharedPreferences prefs) {
|
||||
final SharedPreferences.Editor editor = prefs.edit();
|
||||
|
||||
for (String key : preferences.keySet()) {
|
||||
|
||||
+27
@@ -16,10 +16,20 @@
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>. */
|
||||
package nodomain.freeyourgadget.gadgetbridge.deviceevents;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
|
||||
import nodomain.freeyourgadget.gadgetbridge.R;
|
||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||
|
||||
public class GBDeviceEventVersionInfo extends GBDeviceEvent {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(GBDeviceEventVersionInfo.class);
|
||||
|
||||
public String fwVersion = "N/A";
|
||||
public String fwVersion2 = null;
|
||||
public String hwVersion = "N/A";
|
||||
@@ -32,8 +42,25 @@ public class GBDeviceEventVersionInfo extends GBDeviceEvent {
|
||||
}
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public String toString() {
|
||||
return super.toString() + "fwVersion: " + fwVersion + "; fwVersion2: " + fwVersion2 + "; hwVersion: " + hwVersion;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void evaluate(final Context context, final GBDevice device) {
|
||||
LOG.info("Got event for VERSION_INFO: {}", this);
|
||||
if (device == null) {
|
||||
return;
|
||||
}
|
||||
if (fwVersion != null) {
|
||||
device.setFirmwareVersion(fwVersion);
|
||||
}
|
||||
if (fwVersion2 != null) {
|
||||
device.setFirmwareVersion2(fwVersion2);
|
||||
}
|
||||
device.setModel(hwVersion);
|
||||
device.sendDeviceUpdateIntent(context);
|
||||
}
|
||||
}
|
||||
|
||||
+46
-1
@@ -16,15 +16,60 @@
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>. */
|
||||
package nodomain.freeyourgadget.gadgetbridge.deviceevents;
|
||||
|
||||
import java.util.Locale;
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Locale;
|
||||
import java.util.Set;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
|
||||
import nodomain.freeyourgadget.gadgetbridge.R;
|
||||
import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst;
|
||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.WearingState;
|
||||
|
||||
public class GBDeviceEventWearState extends GBDeviceEvent {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(GBDeviceEventWearState.class);
|
||||
|
||||
public WearingState wearingState = WearingState.UNKNOWN;
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public String toString() {
|
||||
return super.toString() + String.format(Locale.ROOT, "wearingState=%s", wearingState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void evaluate(final Context context, final GBDevice device) {
|
||||
if (this.wearingState == WearingState.UNKNOWN) {
|
||||
LOG.warn("WEAR_STATE state is UNKNOWN, aborting further evaluation");
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.wearingState != WearingState.NOT_WEARING) {
|
||||
LOG.debug("WEAR_STATE state is not NOT_WEARING, aborting further evaluation");
|
||||
}
|
||||
|
||||
Set<String> actionOnUnwear = GBApplication.getDevicePrefs(device).getStringSet(
|
||||
DeviceSettingsPreferenceConst.PREF_DEVICE_ACTION_START_NON_WEAR_SELECTIONS,
|
||||
Collections.emptySet()
|
||||
);
|
||||
|
||||
// check if an action is set
|
||||
if (actionOnUnwear.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
String broadcastMessage = GBApplication.getDevicePrefs(device).getString(
|
||||
DeviceSettingsPreferenceConst.PREF_DEVICE_ACTION_START_NON_WEAR_BROADCAST,
|
||||
context.getString(R.string.prefs_events_forwarding_startnonwear_broadcast_default_value)
|
||||
);
|
||||
|
||||
handleDeviceAction(context, device, actionOnUnwear, broadcastMessage);
|
||||
}
|
||||
}
|
||||
|
||||
+39
@@ -16,8 +16,17 @@
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>. */
|
||||
package nodomain.freeyourgadget.gadgetbridge.deviceevents;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.activities.musicmanager.MusicManagerActivity;
|
||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDeviceMusic;
|
||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDeviceMusicPlaylist;
|
||||
|
||||
@@ -28,4 +37,34 @@ public class GBDeviceMusicData extends GBDeviceEvent {
|
||||
public String deviceInfo = null;
|
||||
public int maxMusicCount = 0;
|
||||
public int maxPlaylistCount = 0;
|
||||
|
||||
@Override
|
||||
public void evaluate(final Context context, final GBDevice device) {
|
||||
final Intent intent = new Intent(MusicManagerActivity.ACTION_MUSIC_DATA);
|
||||
|
||||
intent.putExtra("type", this.type);
|
||||
|
||||
if (this.list != null) {
|
||||
final ArrayList<GBDeviceMusic> list = new ArrayList<>(this.list);
|
||||
intent.putExtra("musicList", list);
|
||||
}
|
||||
|
||||
if (this.playlists != null) {
|
||||
final ArrayList<GBDeviceMusicPlaylist> list = new ArrayList<>(this.playlists);
|
||||
intent.putExtra("musicPlaylist", list);
|
||||
}
|
||||
|
||||
if (!TextUtils.isEmpty(this.deviceInfo)) {
|
||||
intent.putExtra("deviceInfo", this.deviceInfo);
|
||||
}
|
||||
|
||||
if (this.maxMusicCount > 0) {
|
||||
intent.putExtra("maxMusicCount", this.maxMusicCount);
|
||||
}
|
||||
if (this.maxPlaylistCount > 0) {
|
||||
intent.putExtra("maxPlaylistCount", this.maxPlaylistCount);
|
||||
}
|
||||
|
||||
LocalBroadcastManager.getInstance(context).sendBroadcast(intent);
|
||||
}
|
||||
}
|
||||
|
||||
+21
@@ -16,12 +16,33 @@
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>. */
|
||||
package nodomain.freeyourgadget.gadgetbridge.deviceevents;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
|
||||
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.activities.musicmanager.MusicManagerActivity;
|
||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||
|
||||
public class GBDeviceMusicUpdate extends GBDeviceEvent {
|
||||
public boolean success = false;
|
||||
public int operation = -1;
|
||||
public int playlistIndex = -1;
|
||||
public String playlistName;
|
||||
public ArrayList<Integer> musicIds = null;
|
||||
|
||||
@Override
|
||||
public void evaluate(final Context context, final GBDevice device) {
|
||||
final Intent intent = new Intent(MusicManagerActivity.ACTION_MUSIC_UPDATE);
|
||||
|
||||
intent.putExtra("success", success);
|
||||
intent.putExtra("operation", operation);
|
||||
intent.putExtra("playlistIndex", playlistIndex);
|
||||
intent.putExtra("playlistName", playlistName);
|
||||
intent.putExtra("musicIds", musicIds);
|
||||
|
||||
LocalBroadcastManager.getInstance(context).sendBroadcast(intent);
|
||||
}
|
||||
}
|
||||
|
||||
+8
@@ -16,9 +16,12 @@
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>. */
|
||||
package nodomain.freeyourgadget.gadgetbridge.deviceevents.pebble;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEvent;
|
||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||
|
||||
public class GBDeviceEventDataLogging extends GBDeviceEvent {
|
||||
public static final int COMMAND_RECEIVE_DATA = 1;
|
||||
@@ -30,4 +33,9 @@ public class GBDeviceEventDataLogging extends GBDeviceEvent {
|
||||
public long tag;
|
||||
public byte pebbleDataType;
|
||||
public Object[] data;
|
||||
|
||||
@Override
|
||||
public void evaluate(final Context context, final GBDevice device) {
|
||||
// FIXME: Pebble-specific, handled in support class
|
||||
}
|
||||
}
|
||||
|
||||
+6
-707
@@ -19,88 +19,26 @@
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>. */
|
||||
package nodomain.freeyourgadget.gadgetbridge.service;
|
||||
|
||||
import android.app.Notification;
|
||||
import android.app.NotificationManager;
|
||||
import android.app.PendingIntent;
|
||||
import android.bluetooth.BluetoothAdapter;
|
||||
import android.companion.CompanionDeviceManager;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.location.Location;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.telephony.SmsManager;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import androidx.annotation.RequiresApi;
|
||||
import androidx.core.app.NotificationCompat;
|
||||
import androidx.core.content.FileProvider;
|
||||
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.text.DateFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.Locale;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.BuildConfig;
|
||||
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
|
||||
import nodomain.freeyourgadget.gadgetbridge.R;
|
||||
import nodomain.freeyourgadget.gadgetbridge.activities.CameraActivity;
|
||||
import nodomain.freeyourgadget.gadgetbridge.activities.FindPhoneActivity;
|
||||
import nodomain.freeyourgadget.gadgetbridge.activities.appmanager.AbstractAppManagerFragment;
|
||||
import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst;
|
||||
import nodomain.freeyourgadget.gadgetbridge.activities.musicmanager.MusicManagerActivity;
|
||||
import nodomain.freeyourgadget.gadgetbridge.capabilities.loyaltycards.LoyaltyCard;
|
||||
import nodomain.freeyourgadget.gadgetbridge.database.DBAccess;
|
||||
import nodomain.freeyourgadget.gadgetbridge.database.DBHandler;
|
||||
import nodomain.freeyourgadget.gadgetbridge.database.DBHelper;
|
||||
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEvent;
|
||||
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventAppInfo;
|
||||
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventBatteryInfo;
|
||||
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventCallControl;
|
||||
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventCameraRemote;
|
||||
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventDisplayMessage;
|
||||
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventFindPhone;
|
||||
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventFmFrequency;
|
||||
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventSleepStateDetection;
|
||||
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventSilentMode;
|
||||
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventUpdateDeviceInfo;
|
||||
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventLEDColor;
|
||||
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventMusicControl;
|
||||
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventNotificationControl;
|
||||
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventUpdateDeviceState;
|
||||
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventUpdatePreferences;
|
||||
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventScreenshot;
|
||||
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventVersionInfo;
|
||||
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventWearState;
|
||||
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceMusicData;
|
||||
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceMusicUpdate;
|
||||
import nodomain.freeyourgadget.gadgetbridge.entities.BatteryLevel;
|
||||
import nodomain.freeyourgadget.gadgetbridge.entities.DaoSession;
|
||||
import nodomain.freeyourgadget.gadgetbridge.entities.Device;
|
||||
import nodomain.freeyourgadget.gadgetbridge.externalevents.CalendarReceiver;
|
||||
import nodomain.freeyourgadget.gadgetbridge.externalevents.NotificationListener;
|
||||
import nodomain.freeyourgadget.gadgetbridge.externalevents.opentracks.OpenTracksController;
|
||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDeviceMusic;
|
||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDeviceMusicPlaylist;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.Alarm;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.BatteryConfig;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.BatteryState;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.CalendarEventSpec;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.CallSpec;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.CannedMessagesSpec;
|
||||
@@ -109,20 +47,11 @@ import nodomain.freeyourgadget.gadgetbridge.model.MusicSpec;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.MusicStateSpec;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.NotificationSpec;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.Reminder;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.SleepState;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.WearingState;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.WeatherSpec;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.WorldClock;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.NavigationInfoSpec;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.receivers.GBCallControlReceiver;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.receivers.GBMusicControlReceiver;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.GB;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.PendingIntentUtils;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.SilentMode;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.preferences.DevicePrefs;
|
||||
|
||||
import static nodomain.freeyourgadget.gadgetbridge.util.GB.NOTIFICATION_CHANNEL_HIGH_PRIORITY_ID;
|
||||
|
||||
// TODO: support option for a single reminder notification when notifications could not be delivered?
|
||||
// conditions: app was running and received notifications, but device was not connected.
|
||||
// maybe need to check for "unread notifications" on device for that.
|
||||
@@ -133,7 +62,6 @@ import static nodomain.freeyourgadget.gadgetbridge.util.GB.NOTIFICATION_CHANNEL_
|
||||
*/
|
||||
public abstract class AbstractDeviceSupport implements DeviceSupport {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(AbstractDeviceSupport.class);
|
||||
private static final int NOTIFICATION_ID_SCREENSHOT = 8000;
|
||||
|
||||
protected GBDevice gbDevice;
|
||||
private BluetoothAdapter btAdapter;
|
||||
@@ -207,643 +135,14 @@ public abstract class AbstractDeviceSupport implements DeviceSupport {
|
||||
return context;
|
||||
}
|
||||
|
||||
public void evaluateGBDeviceEvent(GBDeviceEvent deviceEvent) {
|
||||
if (deviceEvent instanceof GBDeviceEventMusicControl) {
|
||||
handleGBDeviceEvent((GBDeviceEventMusicControl) deviceEvent);
|
||||
} else if (deviceEvent instanceof GBDeviceEventCallControl) {
|
||||
handleGBDeviceEvent((GBDeviceEventCallControl) deviceEvent);
|
||||
} else if (deviceEvent instanceof GBDeviceEventCameraRemote) {
|
||||
handleGBDeviceEvent((GBDeviceEventCameraRemote) deviceEvent);
|
||||
} else if (deviceEvent instanceof GBDeviceEventVersionInfo) {
|
||||
handleGBDeviceEvent((GBDeviceEventVersionInfo) deviceEvent);
|
||||
} else if (deviceEvent instanceof GBDeviceEventAppInfo) {
|
||||
handleGBDeviceEvent((GBDeviceEventAppInfo) deviceEvent);
|
||||
} else if (deviceEvent instanceof GBDeviceEventScreenshot) {
|
||||
handleGBDeviceEvent((GBDeviceEventScreenshot) deviceEvent);
|
||||
} else if (deviceEvent instanceof GBDeviceEventNotificationControl) {
|
||||
handleGBDeviceEvent((GBDeviceEventNotificationControl) deviceEvent);
|
||||
} else if (deviceEvent instanceof GBDeviceEventBatteryInfo) {
|
||||
handleGBDeviceEvent((GBDeviceEventBatteryInfo) deviceEvent);
|
||||
} else if (deviceEvent instanceof GBDeviceEventFindPhone) {
|
||||
handleGBDeviceEvent((GBDeviceEventFindPhone) deviceEvent);
|
||||
} else if (deviceEvent instanceof GBDeviceEventLEDColor) {
|
||||
handleGBDeviceEvent((GBDeviceEventLEDColor) deviceEvent);
|
||||
} else if (deviceEvent instanceof GBDeviceEventUpdateDeviceInfo) {
|
||||
handleGBDeviceEvent((GBDeviceEventUpdateDeviceInfo) deviceEvent);
|
||||
} else if (deviceEvent instanceof GBDeviceEventUpdatePreferences) {
|
||||
handleGBDeviceEvent((GBDeviceEventUpdatePreferences) deviceEvent);
|
||||
} else if (deviceEvent instanceof GBDeviceEventUpdateDeviceState) {
|
||||
handleGBDeviceEvent((GBDeviceEventUpdateDeviceState) deviceEvent);
|
||||
} else if (deviceEvent instanceof GBDeviceEventSilentMode) {
|
||||
handleGBDeviceEvent((GBDeviceEventSilentMode) deviceEvent);
|
||||
} else if (deviceEvent instanceof GBDeviceEventFmFrequency) {
|
||||
handleGBDeviceEvent((GBDeviceEventFmFrequency) deviceEvent);
|
||||
} else if (deviceEvent instanceof GBDeviceEventWearState) {
|
||||
handleGBDeviceEvent((GBDeviceEventWearState) deviceEvent);
|
||||
} else if (deviceEvent instanceof GBDeviceEventSleepStateDetection) {
|
||||
handleGBDeviceEvent((GBDeviceEventSleepStateDetection) deviceEvent);
|
||||
} else if (deviceEvent instanceof GBDeviceMusicData) {
|
||||
handleGBDeviceEvent((GBDeviceMusicData) deviceEvent);
|
||||
} else if (deviceEvent instanceof GBDeviceMusicUpdate) {
|
||||
handleGBDeviceEvent((GBDeviceMusicUpdate) deviceEvent);
|
||||
}
|
||||
|
||||
public void evaluateGBDeviceEvent(final GBDeviceEvent deviceEvent) {
|
||||
LOG.debug("Evaluating event: {}", deviceEvent);
|
||||
deviceEvent.evaluate(context, gbDevice);
|
||||
}
|
||||
|
||||
private void handleGBDeviceEvent(GBDeviceEventSilentMode deviceEvent) {
|
||||
LOG.info("Got GBDeviceEventSilentMode: enabled = {}", deviceEvent.isEnabled());
|
||||
|
||||
SilentMode.setPhoneSilentMode(getDevice().getAddress(), deviceEvent.isEnabled());
|
||||
}
|
||||
|
||||
private void handleGBDeviceEvent(final GBDeviceEventFindPhone deviceEvent) {
|
||||
final Context context = getContext();
|
||||
LOG.info("Got GBDeviceEventFindPhone: {}", deviceEvent.event);
|
||||
switch (deviceEvent.event) {
|
||||
case START:
|
||||
handleGBDeviceEventFindPhoneStart(true);
|
||||
break;
|
||||
case START_VIBRATE:
|
||||
handleGBDeviceEventFindPhoneStart(false);
|
||||
break;
|
||||
case VIBRATE:
|
||||
final Intent intentVibrate = new Intent(FindPhoneActivity.ACTION_VIBRATE);
|
||||
intentVibrate.setPackage(BuildConfig.APPLICATION_ID);
|
||||
LocalBroadcastManager.getInstance(context).sendBroadcast(intentVibrate);
|
||||
break;
|
||||
case RING:
|
||||
final Intent intentRing = new Intent(FindPhoneActivity.ACTION_RING);
|
||||
intentRing.setPackage(BuildConfig.APPLICATION_ID);
|
||||
LocalBroadcastManager.getInstance(context).sendBroadcast(intentRing);
|
||||
break;
|
||||
case STOP:
|
||||
final Intent intentStop = new Intent(FindPhoneActivity.ACTION_FOUND);
|
||||
intentStop.setPackage(BuildConfig.APPLICATION_ID);
|
||||
LocalBroadcastManager.getInstance(context).sendBroadcast(intentStop);
|
||||
break;
|
||||
default:
|
||||
LOG.warn("unknown GBDeviceEventFindPhone");
|
||||
}
|
||||
}
|
||||
|
||||
private void handleGBDeviceEventFindPhoneStart(final boolean ring) {
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) { // this could be used if app in foreground // TODO: Below Q?
|
||||
Intent startIntent = new Intent(getContext(), FindPhoneActivity.class);
|
||||
startIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
startIntent.putExtra(FindPhoneActivity.EXTRA_RING, ring);
|
||||
context.startActivity(startIntent);
|
||||
} else {
|
||||
handleGBDeviceEventFindPhoneStartNotification(ring);
|
||||
}
|
||||
}
|
||||
|
||||
@RequiresApi(Build.VERSION_CODES.Q)
|
||||
private void handleGBDeviceEventFindPhoneStartNotification(final boolean ring) {
|
||||
LOG.info("Got handleGBDeviceEventFindPhoneStartNotification");
|
||||
final CompanionDeviceManager manager = (CompanionDeviceManager) context.getSystemService(Context.COMPANION_DEVICE_SERVICE);
|
||||
if (manager.getAssociations().isEmpty()) {
|
||||
// On Android Q and above, we need the device to be paired as companion. If it is not, display a notification
|
||||
// notifying the user and linking to further instructions
|
||||
final Intent instructionsIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("https://gadgetbridge.org/basics/pairing/companion-device/"));
|
||||
final PendingIntent pi = PendingIntentUtils.getActivity(context, 0, instructionsIntent, PendingIntent.FLAG_ONE_SHOT, false);
|
||||
final NotificationCompat.Builder notification = new NotificationCompat.Builder(context, NOTIFICATION_CHANNEL_HIGH_PRIORITY_ID)
|
||||
.setSmallIcon(R.drawable.ic_warning)
|
||||
.setOngoing(false)
|
||||
.setPriority(NotificationCompat.PRIORITY_HIGH)
|
||||
.setContentIntent(pi)
|
||||
.setAutoCancel(true)
|
||||
.setContentTitle(context.getString(R.string.find_my_phone_notification))
|
||||
.setContentText(context.getString(R.string.find_my_phone_companion_warning));
|
||||
|
||||
GB.notify(GB.NOTIFICATION_ID_PHONE_FIND, notification.build(), context);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
final Intent intent = new Intent(context, FindPhoneActivity.class);
|
||||
intent.setPackage(BuildConfig.APPLICATION_ID);
|
||||
intent.putExtra(FindPhoneActivity.EXTRA_RING, ring);
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
|
||||
final PendingIntent pi = PendingIntentUtils.getActivity(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT, false);
|
||||
|
||||
final NotificationCompat.Builder notification = new NotificationCompat.Builder(context, NOTIFICATION_CHANNEL_HIGH_PRIORITY_ID)
|
||||
.setSmallIcon(R.drawable.ic_notification)
|
||||
.setOngoing(false)
|
||||
.setFullScreenIntent(pi, true)
|
||||
.setPriority(NotificationCompat.PRIORITY_HIGH)
|
||||
.setAutoCancel(true)
|
||||
.setGroup("BackgroundService")
|
||||
.setContentTitle(context.getString(R.string.find_my_phone_notification));
|
||||
|
||||
GB.notify(GB.NOTIFICATION_ID_PHONE_FIND, notification.build(), context);
|
||||
context.startActivity(intent);
|
||||
LOG.debug("CompanionDeviceManager associations were found, starting intent");
|
||||
}
|
||||
|
||||
|
||||
private void handleGBDeviceEvent(GBDeviceEventMusicControl musicEvent) {
|
||||
Context context = getContext();
|
||||
LOG.info("Got event for MUSIC_CONTROL");
|
||||
Intent musicIntent = new Intent(GBMusicControlReceiver.ACTION_MUSICCONTROL);
|
||||
musicIntent.putExtra("event", musicEvent.event.ordinal());
|
||||
musicIntent.setPackage(context.getPackageName());
|
||||
context.sendBroadcast(musicIntent);
|
||||
}
|
||||
|
||||
private void handleGBDeviceEvent(GBDeviceEventCallControl callEvent) {
|
||||
Context context = getContext();
|
||||
LOG.info("Got event for CALL_CONTROL");
|
||||
if(callEvent.event == GBDeviceEventCallControl.Event.IGNORE) {
|
||||
LOG.info("Sending intent for mute");
|
||||
Intent broadcastIntent = new Intent(context.getPackageName() + ".MUTE_CALL");
|
||||
broadcastIntent.setPackage(context.getPackageName());
|
||||
context.sendBroadcast(broadcastIntent);
|
||||
return;
|
||||
}
|
||||
Intent callIntent = new Intent(GBCallControlReceiver.ACTION_CALLCONTROL);
|
||||
callIntent.putExtra("event", callEvent.event.ordinal());
|
||||
callIntent.setPackage(context.getPackageName());
|
||||
context.sendBroadcast(callIntent);
|
||||
}
|
||||
|
||||
protected void handleGBDeviceEvent(GBDeviceEventCameraRemote cameraRemoteEvent) {
|
||||
Intent cameraIntent = new Intent(getContext(), CameraActivity.class);
|
||||
cameraIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
cameraIntent.putExtra(CameraActivity.intentExtraEvent, GBDeviceEventCameraRemote.eventToInt(cameraRemoteEvent.event));
|
||||
getContext().startActivity(cameraIntent);
|
||||
}
|
||||
|
||||
protected void handleGBDeviceEvent(GBDeviceEventVersionInfo infoEvent) {
|
||||
Context context = getContext();
|
||||
LOG.info("Got event for VERSION_INFO: " + infoEvent);
|
||||
if (gbDevice == null) {
|
||||
return;
|
||||
}
|
||||
if (infoEvent.fwVersion != null) {
|
||||
gbDevice.setFirmwareVersion(infoEvent.fwVersion);
|
||||
}
|
||||
if (infoEvent.fwVersion2 != null) {
|
||||
gbDevice.setFirmwareVersion2(infoEvent.fwVersion2);
|
||||
}
|
||||
gbDevice.setModel(infoEvent.hwVersion);
|
||||
gbDevice.sendDeviceUpdateIntent(context);
|
||||
}
|
||||
|
||||
protected void handleGBDeviceEvent(GBDeviceEventLEDColor colorEvent) {
|
||||
Context context = getContext();
|
||||
LOG.info("Got event for LED Color: #" + Integer.toHexString(colorEvent.color).toUpperCase(Locale.ROOT));
|
||||
if (gbDevice == null) {
|
||||
return;
|
||||
}
|
||||
gbDevice.setExtraInfo("led_color", colorEvent.color);
|
||||
gbDevice.sendDeviceUpdateIntent(context);
|
||||
}
|
||||
|
||||
protected void handleGBDeviceEvent(GBDeviceEventUpdateDeviceInfo itemEvent) {
|
||||
if (gbDevice == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
gbDevice.addDeviceInfo(itemEvent.item);
|
||||
gbDevice.sendDeviceUpdateIntent(context);
|
||||
}
|
||||
|
||||
protected void handleGBDeviceEvent(GBDeviceEventUpdatePreferences savePreferencesEvent) {
|
||||
if (gbDevice == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
savePreferencesEvent.update(GBApplication.getDeviceSpecificSharedPrefs(getDevice().getAddress()));
|
||||
gbDevice.sendDeviceUpdateIntent(context);
|
||||
}
|
||||
|
||||
protected void handleGBDeviceEvent(GBDeviceEventUpdateDeviceState updateDeviceState) {
|
||||
if (gbDevice == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
gbDevice.setState(updateDeviceState.state);
|
||||
gbDevice.sendDeviceUpdateIntent(getContext(), GBDevice.DeviceUpdateSubject.DEVICE_STATE);
|
||||
}
|
||||
|
||||
protected void handleGBDeviceEvent(GBDeviceEventFmFrequency frequencyEvent) {
|
||||
Context context = getContext();
|
||||
LOG.info("Got event for FM Frequency");
|
||||
if (gbDevice == null) {
|
||||
return;
|
||||
}
|
||||
gbDevice.setExtraInfo("fm_frequency", frequencyEvent.frequency);
|
||||
gbDevice.sendDeviceUpdateIntent(context);
|
||||
}
|
||||
|
||||
private void handleGBDeviceEvent(GBDeviceEventAppInfo appInfoEvent) {
|
||||
Context context = getContext();
|
||||
LOG.info("Got event for APP_INFO");
|
||||
|
||||
Intent appInfoIntent = new Intent(AbstractAppManagerFragment.ACTION_REFRESH_APPLIST);
|
||||
int appCount = appInfoEvent.apps.length;
|
||||
appInfoIntent.putExtra("app_count", appCount);
|
||||
for (int i = 0; i < appCount; i++) {
|
||||
appInfoIntent.putExtra("app_name" + i, appInfoEvent.apps[i].getName());
|
||||
appInfoIntent.putExtra("app_creator" + i, appInfoEvent.apps[i].getCreator());
|
||||
appInfoIntent.putExtra("app_version" + i, appInfoEvent.apps[i].getVersion());
|
||||
appInfoIntent.putExtra("app_uuid" + i, appInfoEvent.apps[i].getUUID().toString());
|
||||
appInfoIntent.putExtra("app_type" + i, appInfoEvent.apps[i].getType().ordinal());
|
||||
}
|
||||
LocalBroadcastManager.getInstance(context).sendBroadcast(appInfoIntent);
|
||||
}
|
||||
|
||||
private void handleGBDeviceEvent(GBDeviceEventScreenshot screenshot) {
|
||||
if (screenshot.getData() == null) {
|
||||
LOG.warn("Screnshot data is null");
|
||||
return;
|
||||
}
|
||||
|
||||
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd-hhmmss", Locale.US);
|
||||
String filename = "screenshot_" + dateFormat.format(new Date()) + ".bmp";
|
||||
|
||||
try {
|
||||
String fullpath = GB.writeScreenshot(screenshot, filename);
|
||||
Bitmap bmp = BitmapFactory.decodeFile(fullpath);
|
||||
Intent intent = new Intent();
|
||||
intent.setAction(android.content.Intent.ACTION_VIEW);
|
||||
Uri screenshotURI = FileProvider.getUriForFile(context, context.getApplicationContext().getPackageName() + ".screenshot_provider", new File(fullpath));
|
||||
intent.setDataAndType(screenshotURI, "image/*");
|
||||
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
||||
|
||||
PendingIntent pIntent = PendingIntentUtils.getActivity(context, 0, intent, 0, false);
|
||||
|
||||
Intent shareIntent = new Intent(Intent.ACTION_SEND);
|
||||
shareIntent.setType("image/*");
|
||||
shareIntent.putExtra(Intent.EXTRA_STREAM, screenshotURI);
|
||||
|
||||
PendingIntent pendingShareIntent = PendingIntentUtils.getActivity(context, 0, Intent.createChooser(shareIntent, context.getString(R.string.share_screenshot)),
|
||||
PendingIntent.FLAG_UPDATE_CURRENT, false);
|
||||
|
||||
NotificationCompat.Action action = new NotificationCompat.Action.Builder(android.R.drawable.ic_menu_share, context.getString(R.string.share), pendingShareIntent).build();
|
||||
|
||||
Notification notif = new NotificationCompat.Builder(context, NOTIFICATION_CHANNEL_HIGH_PRIORITY_ID)
|
||||
.setContentTitle(context.getString(R.string.screenshot_taken))
|
||||
.setTicker(context.getString(R.string.screenshot_taken))
|
||||
.setContentText(filename)
|
||||
.setSmallIcon(R.drawable.ic_notification)
|
||||
.setStyle(new NotificationCompat.BigPictureStyle()
|
||||
.bigPicture(bmp))
|
||||
.setContentIntent(pIntent)
|
||||
.addAction(action)
|
||||
.setAutoCancel(true)
|
||||
.build();
|
||||
|
||||
GB.notify(NOTIFICATION_ID_SCREENSHOT, notif, context);
|
||||
} catch (IOException ex) {
|
||||
LOG.error("Error writing screenshot", ex);
|
||||
}
|
||||
}
|
||||
|
||||
private void handleGBDeviceEvent(GBDeviceEventNotificationControl deviceEvent) {
|
||||
Context context = getContext();
|
||||
LOG.info("Got NOTIFICATION CONTROL device event");
|
||||
String action = null;
|
||||
switch (deviceEvent.event) {
|
||||
case DISMISS:
|
||||
action = NotificationListener.ACTION_DISMISS;
|
||||
break;
|
||||
case DISMISS_ALL:
|
||||
action = NotificationListener.ACTION_DISMISS_ALL;
|
||||
break;
|
||||
case OPEN:
|
||||
action = NotificationListener.ACTION_OPEN;
|
||||
break;
|
||||
case MUTE:
|
||||
action = NotificationListener.ACTION_MUTE;
|
||||
break;
|
||||
case REPLY:
|
||||
if (deviceEvent.phoneNumber == null) {
|
||||
deviceEvent.phoneNumber = GBApplication.getIDSenderLookup().lookup((int) (deviceEvent.handle >> 4));
|
||||
}
|
||||
if (deviceEvent.phoneNumber != null) {
|
||||
LOG.info("Got notification reply for SMS from {} : {}", deviceEvent.phoneNumber, deviceEvent.reply);
|
||||
SmsManager.getDefault().sendTextMessage(deviceEvent.phoneNumber, null, deviceEvent.reply, null, null);
|
||||
} else {
|
||||
LOG.info("Got notification reply for notification id {} : {}", deviceEvent.handle, deviceEvent.reply);
|
||||
action = NotificationListener.ACTION_REPLY;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (action != null) {
|
||||
Intent notificationListenerIntent = new Intent(action);
|
||||
notificationListenerIntent.putExtra("handle", deviceEvent.handle);
|
||||
notificationListenerIntent.putExtra("title", deviceEvent.title);
|
||||
if (deviceEvent.reply != null) {
|
||||
SharedPreferences prefs = GBApplication.getDeviceSpecificSharedPrefs(gbDevice.getAddress());
|
||||
String suffix = prefs.getString("canned_reply_suffix", null);
|
||||
if (suffix != null && !Objects.equals(suffix, "")) {
|
||||
deviceEvent.reply += suffix;
|
||||
}
|
||||
notificationListenerIntent.putExtra("reply", deviceEvent.reply);
|
||||
}
|
||||
LocalBroadcastManager.getInstance(context).sendBroadcast(notificationListenerIntent);
|
||||
}
|
||||
}
|
||||
|
||||
protected void handleGBDeviceEvent(GBDeviceEventBatteryInfo deviceEvent) {
|
||||
Context context = getContext();
|
||||
LOG.info("Got BATTERY_INFO device event");
|
||||
gbDevice.setBatteryLevel(deviceEvent.level, deviceEvent.batteryIndex);
|
||||
gbDevice.setBatteryState(deviceEvent.state, deviceEvent.batteryIndex);
|
||||
gbDevice.setBatteryVoltage(deviceEvent.voltage, deviceEvent.batteryIndex);
|
||||
|
||||
final DevicePrefs devicePrefs = GBApplication.getDevicePrefs(gbDevice);
|
||||
final BatteryConfig batteryConfig = gbDevice.getDeviceCoordinator().getBatteryConfig(gbDevice)[deviceEvent.batteryIndex];
|
||||
|
||||
if (deviceEvent.level == GBDevice.BATTERY_UNKNOWN) {
|
||||
// no level available, just "high" or "low"
|
||||
GB.removeBatteryFullNotification(context);
|
||||
if (devicePrefs.getBatteryNotifyLowEnabled(batteryConfig) && BatteryState.BATTERY_LOW.equals(deviceEvent.state)) {
|
||||
GB.updateBatteryLowNotification(context.getString(R.string.notif_battery_low, gbDevice.getAliasOrName()),
|
||||
deviceEvent.extendedInfoAvailable() ?
|
||||
context.getString(R.string.notif_battery_low_extended, gbDevice.getAliasOrName(),
|
||||
context.getString(R.string.notif_battery_low_bigtext_last_charge_time, DateFormat.getDateTimeInstance().format(deviceEvent.lastChargeTime.getTime())) +
|
||||
context.getString(R.string.notif_battery_low_bigtext_number_of_charges, String.valueOf(deviceEvent.numCharges)))
|
||||
: ""
|
||||
, context);
|
||||
} else if (devicePrefs.getBatteryNotifyFullEnabled(batteryConfig) && BatteryState.BATTERY_CHARGING_FULL.equals(deviceEvent.state)) {
|
||||
GB.removeBatteryLowNotification(context);
|
||||
GB.updateBatteryFullNotification(context.getString(R.string.notif_battery_full, gbDevice.getAliasOrName()), "", context);
|
||||
} else {
|
||||
GB.removeBatteryLowNotification(context);
|
||||
GB.removeBatteryFullNotification(context);
|
||||
}
|
||||
} else {
|
||||
createStoreTask("Storing battery data", context, deviceEvent).execute();
|
||||
|
||||
final boolean batteryNotifyLowEnabled = devicePrefs.getBatteryNotifyLowEnabled(batteryConfig);
|
||||
final boolean isBatteryLow = deviceEvent.level <= devicePrefs.getBatteryNotifyLowThreshold(batteryConfig) &&
|
||||
(BatteryState.BATTERY_LOW.equals(deviceEvent.state) || BatteryState.BATTERY_NORMAL.equals(deviceEvent.state));
|
||||
|
||||
final boolean batteryNotifyFullEnabled = devicePrefs.getBatteryNotifyFullEnabled(batteryConfig);
|
||||
final boolean isBatteryFull = deviceEvent.level >= devicePrefs.getBatteryNotifyFullThreshold(batteryConfig) &&
|
||||
(BatteryState.BATTERY_CHARGING.equals(deviceEvent.state) || BatteryState.BATTERY_CHARGING_FULL.equals(deviceEvent.state));
|
||||
|
||||
//show the notification if the battery level is below threshold and only if not connected to charger
|
||||
if (batteryNotifyLowEnabled && isBatteryLow) {
|
||||
GB.removeBatteryFullNotification(context);
|
||||
GB.updateBatteryLowNotification(context.getString(R.string.notif_battery_low_percent, gbDevice.getAliasOrName(), String.valueOf(deviceEvent.level)),
|
||||
deviceEvent.extendedInfoAvailable() ?
|
||||
context.getString(R.string.notif_battery_low_percent, gbDevice.getAliasOrName(), String.valueOf(deviceEvent.level)) + "\n" +
|
||||
context.getString(R.string.notif_battery_low_bigtext_last_charge_time, DateFormat.getDateTimeInstance().format(deviceEvent.lastChargeTime.getTime())) +
|
||||
context.getString(R.string.notif_battery_low_bigtext_number_of_charges, String.valueOf(deviceEvent.numCharges))
|
||||
: ""
|
||||
, context);
|
||||
} else if (batteryNotifyFullEnabled && isBatteryFull) {
|
||||
GB.removeBatteryLowNotification(context);
|
||||
GB.updateBatteryFullNotification(context.getString(R.string.notif_battery_full, gbDevice.getAliasOrName()), "", context);
|
||||
} else {
|
||||
GB.removeBatteryLowNotification(context);
|
||||
GB.removeBatteryFullNotification(context);
|
||||
}
|
||||
}
|
||||
|
||||
gbDevice.sendDeviceUpdateIntent(context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to run specific actions configured in the device preferences, upon wear state
|
||||
* or awake/asleep events.
|
||||
*
|
||||
* @param actions
|
||||
* @param message
|
||||
*/
|
||||
private void handleDeviceAction(Set<String> actions, String message) {
|
||||
if (actions.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
LOG.debug("Handing device actions: {}", TextUtils.join(",", actions));
|
||||
|
||||
final String actionBroadcast = getContext().getString(R.string.pref_device_action_broadcast_value);
|
||||
final String actionFitnessControlStart = getContext().getString(R.string.pref_device_action_fitness_app_control_start_value);
|
||||
final String actionFitnessControlStop = getContext().getString(R.string.pref_device_action_fitness_app_control_stop_value);
|
||||
final String actionFitnessControlToggle = getContext().getString(R.string.pref_device_action_fitness_app_control_toggle_value);
|
||||
final String actionMediaPlay = getContext().getString(R.string.pref_media_play_value);
|
||||
final String actionMediaPause = getContext().getString(R.string.pref_media_pause_value);
|
||||
final String actionMediaPlayPause = getContext().getString(R.string.pref_media_playpause_value);
|
||||
final String actionDndOff = getContext().getString(R.string.pref_device_action_dnd_off_value);
|
||||
final String actionDndpriority = getContext().getString(R.string.pref_device_action_dnd_priority_value);
|
||||
final String actionDndAlarms = getContext().getString(R.string.pref_device_action_dnd_alarms_value);
|
||||
final String actionDndOn = getContext().getString(R.string.pref_device_action_dnd_on_value);
|
||||
|
||||
if (actions.contains(actionBroadcast)) {
|
||||
if (message != null) {
|
||||
Intent in = new Intent();
|
||||
in.setAction(message);
|
||||
LOG.info("Sending broadcast {}", message);
|
||||
getContext().getApplicationContext().sendBroadcast(in);
|
||||
}
|
||||
}
|
||||
|
||||
if (actions.contains(actionFitnessControlStart)) {
|
||||
OpenTracksController.startRecording(getContext());
|
||||
} else if (actions.contains(actionFitnessControlStop)) {
|
||||
OpenTracksController.stopRecording(getContext());
|
||||
} else if (actions.contains(actionFitnessControlToggle)) {
|
||||
OpenTracksController.toggleRecording(getContext());
|
||||
}
|
||||
|
||||
final String mediaAction;
|
||||
if (actions.contains(actionMediaPlayPause)) {
|
||||
mediaAction = actionMediaPlayPause;
|
||||
} else if (actions.contains(actionMediaPause)) {
|
||||
mediaAction = actionMediaPause;
|
||||
} else if (actions.contains(actionMediaPlay)) {
|
||||
mediaAction = actionMediaPlay;
|
||||
} else {
|
||||
mediaAction = null;
|
||||
}
|
||||
|
||||
if (mediaAction != null) {
|
||||
GBDeviceEventMusicControl deviceEventMusicControl = new GBDeviceEventMusicControl();
|
||||
deviceEventMusicControl.event = GBDeviceEventMusicControl.Event.valueOf(mediaAction);
|
||||
evaluateGBDeviceEvent(deviceEventMusicControl);
|
||||
}
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
final NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
|
||||
final int interruptionFilter;
|
||||
if (actions.contains(actionDndOff)) {
|
||||
interruptionFilter = NotificationManager.INTERRUPTION_FILTER_ALL;
|
||||
} else if (actions.contains(actionDndpriority)) {
|
||||
interruptionFilter = NotificationManager.INTERRUPTION_FILTER_PRIORITY;
|
||||
} else if (actions.contains(actionDndAlarms)) {
|
||||
interruptionFilter = NotificationManager.INTERRUPTION_FILTER_ALARMS;
|
||||
} else if (actions.contains(actionDndOn)) {
|
||||
interruptionFilter = NotificationManager.INTERRUPTION_FILTER_NONE;
|
||||
} else {
|
||||
interruptionFilter = NotificationManager.INTERRUPTION_FILTER_UNKNOWN;
|
||||
}
|
||||
|
||||
if (interruptionFilter != NotificationManager.INTERRUPTION_FILTER_UNKNOWN) {
|
||||
LOG.debug("Setting do not disturb to {}", interruptionFilter);
|
||||
|
||||
if (!notificationManager.isNotificationPolicyAccessGranted()) {
|
||||
LOG.warn("Do not disturb permissions not granted");
|
||||
}
|
||||
|
||||
notificationManager.setInterruptionFilter(interruptionFilter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void handleGBDeviceEvent(GBDeviceEventSleepStateDetection event) {
|
||||
LOG.debug("Got SLEEP_STATE_DETECTION device event, detected sleep state = {}", event.sleepState);
|
||||
|
||||
if (event.sleepState == SleepState.UNKNOWN) {
|
||||
return;
|
||||
}
|
||||
|
||||
String actionPreferenceKey, messagePreferenceKey;
|
||||
int defaultBroadcastMessageResource;
|
||||
|
||||
switch (event.sleepState) {
|
||||
case AWAKE:
|
||||
actionPreferenceKey = DeviceSettingsPreferenceConst.PREF_DEVICE_ACTION_WOKE_UP_SELECTIONS;
|
||||
messagePreferenceKey = DeviceSettingsPreferenceConst.PREF_DEVICE_ACTION_WOKE_UP_BROADCAST;
|
||||
defaultBroadcastMessageResource = R.string.prefs_events_forwarding_wokeup_broadcast_default_value;
|
||||
break;
|
||||
case ASLEEP:
|
||||
actionPreferenceKey = DeviceSettingsPreferenceConst.PREF_DEVICE_ACTION_FELL_SLEEP_SELECTIONS;
|
||||
messagePreferenceKey = DeviceSettingsPreferenceConst.PREF_DEVICE_ACTION_FELL_SLEEP_BROADCAST;
|
||||
defaultBroadcastMessageResource = R.string.prefs_events_forwarding_fellsleep_broadcast_default_value;
|
||||
break;
|
||||
default:
|
||||
LOG.warn("Unable to deduce action and broadcast message preference key for sleep state {}", event.sleepState);
|
||||
return;
|
||||
}
|
||||
|
||||
Set<String> actions = getDevicePrefs().getStringSet(actionPreferenceKey, Collections.emptySet());
|
||||
|
||||
if (actions.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
String broadcastMessage = getDevicePrefs().getString(messagePreferenceKey, context.getString(defaultBroadcastMessageResource));
|
||||
handleDeviceAction(actions, broadcastMessage);
|
||||
}
|
||||
|
||||
private void handleGBDeviceEvent(GBDeviceEventWearState event) {
|
||||
LOG.debug("Got WEAR_STATE device event, wearingState = {}", event.wearingState);
|
||||
|
||||
if (event.wearingState == WearingState.UNKNOWN) {
|
||||
LOG.warn("WEAR_STATE state is UNKNOWN, aborting further evaluation");
|
||||
return;
|
||||
}
|
||||
|
||||
if (event.wearingState != WearingState.NOT_WEARING) {
|
||||
LOG.debug("WEAR_STATE state is not NOT_WEARING, aborting further evaluation");
|
||||
}
|
||||
|
||||
Set<String> actionOnUnwear = getDevicePrefs().getStringSet(
|
||||
DeviceSettingsPreferenceConst.PREF_DEVICE_ACTION_START_NON_WEAR_SELECTIONS,
|
||||
Collections.emptySet()
|
||||
);
|
||||
|
||||
// check if an action is set
|
||||
if (actionOnUnwear.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
String broadcastMessage = getDevicePrefs().getString(
|
||||
DeviceSettingsPreferenceConst.PREF_DEVICE_ACTION_START_NON_WEAR_BROADCAST,
|
||||
getContext().getString(R.string.prefs_events_forwarding_startnonwear_broadcast_default_value)
|
||||
);
|
||||
|
||||
handleDeviceAction(actionOnUnwear, broadcastMessage);
|
||||
}
|
||||
|
||||
private void handleGBDeviceEvent(GBDeviceMusicData deviceEvent) {
|
||||
Context context = getContext();
|
||||
LOG.info("Got event for ACTION_MUSIC_DATA");
|
||||
|
||||
Intent intent = new Intent(MusicManagerActivity.ACTION_MUSIC_DATA);
|
||||
|
||||
intent.putExtra("type", deviceEvent.type);
|
||||
|
||||
if(deviceEvent.list != null) {
|
||||
ArrayList<GBDeviceMusic> list = new ArrayList<>(deviceEvent.list);
|
||||
intent.putExtra("musicList", list);
|
||||
}
|
||||
|
||||
if(deviceEvent.playlists != null) {
|
||||
ArrayList<GBDeviceMusicPlaylist> list = new ArrayList<>(deviceEvent.playlists);
|
||||
intent.putExtra("musicPlaylist", list);
|
||||
}
|
||||
|
||||
if(!TextUtils.isEmpty(deviceEvent.deviceInfo)) {
|
||||
intent.putExtra("deviceInfo", deviceEvent.deviceInfo);
|
||||
}
|
||||
|
||||
if(deviceEvent.maxMusicCount > 0) {
|
||||
intent.putExtra("maxMusicCount", deviceEvent.maxMusicCount);
|
||||
}
|
||||
if(deviceEvent.maxPlaylistCount > 0) {
|
||||
intent.putExtra("maxPlaylistCount", deviceEvent.maxPlaylistCount);
|
||||
}
|
||||
|
||||
LocalBroadcastManager.getInstance(context).sendBroadcast(intent);
|
||||
}
|
||||
|
||||
private void handleGBDeviceEvent(GBDeviceMusicUpdate deviceEvent) {
|
||||
Context context = getContext();
|
||||
LOG.info("Got event for ACTION_MUSIC_UPDATE");
|
||||
|
||||
Intent intent = new Intent(MusicManagerActivity.ACTION_MUSIC_UPDATE);
|
||||
|
||||
intent.putExtra("success", deviceEvent.success);
|
||||
intent.putExtra("operation", deviceEvent.operation);
|
||||
intent.putExtra("playlistIndex", deviceEvent.playlistIndex);
|
||||
intent.putExtra("playlistName", deviceEvent.playlistName);
|
||||
intent.putExtra("musicIds", deviceEvent.musicIds);
|
||||
|
||||
LocalBroadcastManager.getInstance(context).sendBroadcast(intent);
|
||||
}
|
||||
|
||||
private StoreDataTask createStoreTask(String task, Context context, GBDeviceEventBatteryInfo deviceEvent) {
|
||||
return new StoreDataTask(task, context, deviceEvent);
|
||||
}
|
||||
|
||||
public class StoreDataTask extends DBAccess {
|
||||
GBDeviceEventBatteryInfo deviceEvent;
|
||||
|
||||
public StoreDataTask(String task, Context context, GBDeviceEventBatteryInfo deviceEvent) {
|
||||
super(task, context);
|
||||
this.deviceEvent = deviceEvent;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doInBackground(DBHandler handler) {
|
||||
DaoSession daoSession = handler.getDaoSession();
|
||||
Device device = DBHelper.getDevice(gbDevice, daoSession);
|
||||
int ts = (int) (System.currentTimeMillis() / 1000);
|
||||
BatteryLevel batteryLevel = new BatteryLevel();
|
||||
batteryLevel.setTimestamp(ts);
|
||||
batteryLevel.setBatteryIndex(deviceEvent.batteryIndex);
|
||||
batteryLevel.setDevice(device);
|
||||
batteryLevel.setLevel(deviceEvent.level);
|
||||
handler.getDaoSession().getBatteryLevelDao().insert(batteryLevel);
|
||||
}
|
||||
}
|
||||
|
||||
public void handleGBDeviceEvent(GBDeviceEventDisplayMessage message) {
|
||||
GB.log(message.message, message.severity, null);
|
||||
|
||||
Intent messageIntent = new Intent(GB.ACTION_DISPLAY_MESSAGE);
|
||||
messageIntent.putExtra(GB.DISPLAY_MESSAGE_MESSAGE, message.message);
|
||||
messageIntent.putExtra(GB.DISPLAY_MESSAGE_DURATION, message.duration);
|
||||
messageIntent.putExtra(GB.DISPLAY_MESSAGE_SEVERITY, message.severity);
|
||||
|
||||
LocalBroadcastManager.getInstance(context).sendBroadcast(messageIntent);
|
||||
public void handleGBDeviceEvent(final GBDeviceEvent deviceEvent) {
|
||||
LOG.debug("Handling event: {}", deviceEvent);
|
||||
deviceEvent.evaluate(getContext(), gbDevice);
|
||||
}
|
||||
|
||||
public DevicePrefs getDevicePrefs() {
|
||||
|
||||
+2
-2
@@ -338,9 +338,9 @@ public class GarminSupport extends AbstractBTLEDeviceSupport implements ICommuni
|
||||
if (!getKeepActivityDataOnDevice()) { // delete file from watch upon successful download
|
||||
sendOutgoingMessage("archive file " + entry.getFileIndex(), new SetFileFlagsMessage(entry.getFileIndex(), SetFileFlagsMessage.FileFlags.ARCHIVE));
|
||||
}
|
||||
} else {
|
||||
super.evaluateGBDeviceEvent(deviceEvent);
|
||||
}
|
||||
|
||||
super.evaluateGBDeviceEvent(deviceEvent);
|
||||
}
|
||||
|
||||
/** @noinspection BooleanMethodIsAlwaysInverted*/
|
||||
|
||||
+8
@@ -1,9 +1,12 @@
|
||||
package nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.deviceevents;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEvent;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.vivomovehr.GarminCapability;
|
||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||
|
||||
public class CapabilitiesDeviceEvent extends GBDeviceEvent {
|
||||
public Set<GarminCapability> capabilities;
|
||||
@@ -11,4 +14,9 @@ public class CapabilitiesDeviceEvent extends GBDeviceEvent {
|
||||
public CapabilitiesDeviceEvent(final Set<GarminCapability> capabilities) {
|
||||
this.capabilities = capabilities;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void evaluate(final Context context, final GBDevice device) {
|
||||
// Handled in support class
|
||||
}
|
||||
}
|
||||
|
||||
+8
@@ -1,9 +1,17 @@
|
||||
package nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.deviceevents;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEvent;
|
||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.FileTransferHandler;
|
||||
|
||||
public class FileDownloadedDeviceEvent extends GBDeviceEvent {
|
||||
public FileTransferHandler.DirectoryEntry directoryEntry;
|
||||
public String localPath;
|
||||
|
||||
@Override
|
||||
public void evaluate(final Context context, final GBDevice device) {
|
||||
// Handled in support class
|
||||
}
|
||||
}
|
||||
|
||||
+7
-1
@@ -1,9 +1,15 @@
|
||||
package nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.deviceevents;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEvent;
|
||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||
|
||||
public class NotificationSubscriptionDeviceEvent extends GBDeviceEvent {
|
||||
|
||||
public boolean enable;
|
||||
|
||||
@Override
|
||||
public void evaluate(final Context context, final GBDevice device) {
|
||||
// Handled in support class
|
||||
}
|
||||
}
|
||||
|
||||
+8
-1
@@ -1,12 +1,14 @@
|
||||
package nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.deviceevents;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEvent;
|
||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.FileType;
|
||||
|
||||
public class SupportedFileTypesDeviceEvent extends GBDeviceEvent {
|
||||
|
||||
private final List<FileType> supportedFileTypes;
|
||||
|
||||
public SupportedFileTypesDeviceEvent(List<FileType> fileTypes) {
|
||||
@@ -16,4 +18,9 @@ public class SupportedFileTypesDeviceEvent extends GBDeviceEvent {
|
||||
public List<FileType> getSupportedFileTypes() {
|
||||
return supportedFileTypes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void evaluate(final Context context, final GBDevice device) {
|
||||
// Handled in support class
|
||||
}
|
||||
}
|
||||
|
||||
+8
-1
@@ -1,12 +1,16 @@
|
||||
package nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.deviceevents;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEvent;
|
||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||
|
||||
public class WeatherRequestDeviceEvent extends GBDeviceEvent {
|
||||
private final int format;
|
||||
private final int latitude;
|
||||
private final int longitude;
|
||||
private final int hoursOfForecast;
|
||||
|
||||
public WeatherRequestDeviceEvent(int format, int latitude, int longitude, int hoursOfForecast) {
|
||||
this.format = format;
|
||||
this.latitude = latitude;
|
||||
@@ -14,5 +18,8 @@ public class WeatherRequestDeviceEvent extends GBDeviceEvent {
|
||||
this.hoursOfForecast = hoursOfForecast;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void evaluate(final Context context, final GBDevice device) {
|
||||
// Handled in support class
|
||||
}
|
||||
}
|
||||
|
||||
-5
@@ -740,11 +740,6 @@ public class QHybridSupport extends QHybridBaseSupport {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleGBDeviceEvent(GBDeviceEventBatteryInfo deviceEvent){
|
||||
super.handleGBDeviceEvent(deviceEvent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
|
||||
watchAdapter.onCharacteristicWrite(gatt, characteristic, status);
|
||||
|
||||
+2
@@ -52,6 +52,8 @@ public class SonyHeadphonesSupport extends AbstractHeadphoneDeviceSupport {
|
||||
SonyHeadphonesIoThread deviceIOThread = getDeviceIOThread();
|
||||
deviceIOThread.write(sonyProtocol.getFromQueue());
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
super.evaluateGBDeviceEvent(deviceEvent);
|
||||
|
||||
+8
@@ -16,11 +16,14 @@
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>. */
|
||||
package nodomain.freeyourgadget.gadgetbridge.service.devices.sony.headphones.deviceevents;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEvent;
|
||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.sony.headphones.protocol.Request;
|
||||
|
||||
public class SonyHeadphonesEnqueueRequestEvent extends GBDeviceEvent {
|
||||
@@ -37,4 +40,9 @@ public class SonyHeadphonesEnqueueRequestEvent extends GBDeviceEvent {
|
||||
public List<Request> getRequests() {
|
||||
return this.requests;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void evaluate(final Context context, final GBDevice device) {
|
||||
// Handled in support class
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user