2023-12-07 01:50:14 +01:00
|
|
|
/* Copyright (C) 2015-2023 Andreas Böhler, Andreas Shimokawa, Carsten
|
2021-01-10 23:37:09 +01:00
|
|
|
Pfeiffer, Daniele Gobbetti, José Rebelo, Pauli Salmenrinne, Sebastian Kranz,
|
2023-12-07 01:50:14 +01:00
|
|
|
Taavi Eomäe, Yoran Vulker
|
2017-03-10 14:53:19 +01:00
|
|
|
|
|
|
|
This file is part of Gadgetbridge.
|
|
|
|
|
|
|
|
Gadgetbridge is free software: you can redistribute it and/or modify
|
|
|
|
it under the terms of the GNU Affero General Public License as published
|
|
|
|
by the Free Software Foundation, either version 3 of the License, or
|
|
|
|
(at your option) any later version.
|
|
|
|
|
|
|
|
Gadgetbridge is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
GNU Affero General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU Affero General Public License
|
|
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
2015-08-03 23:09:49 +02:00
|
|
|
package nodomain.freeyourgadget.gadgetbridge.service;
|
2015-04-14 01:24:03 +02:00
|
|
|
|
2015-06-26 23:17:31 +02:00
|
|
|
import android.app.Notification;
|
2023-12-09 12:01:55 +01:00
|
|
|
import android.app.NotificationManager;
|
2015-06-27 00:21:30 +02:00
|
|
|
import android.app.PendingIntent;
|
2015-04-14 01:24:03 +02:00
|
|
|
import android.bluetooth.BluetoothAdapter;
|
2020-10-06 21:00:42 +02:00
|
|
|
import android.companion.CompanionDeviceManager;
|
2015-04-14 01:24:03 +02:00
|
|
|
import android.content.Context;
|
2015-05-23 00:54:14 +02:00
|
|
|
import android.content.Intent;
|
2020-10-13 00:25:43 +02:00
|
|
|
import android.content.SharedPreferences;
|
2015-06-26 23:17:31 +02:00
|
|
|
import android.graphics.Bitmap;
|
|
|
|
import android.graphics.BitmapFactory;
|
2023-01-05 12:36:11 +01:00
|
|
|
import android.location.Location;
|
2015-06-27 00:21:30 +02:00
|
|
|
import android.net.Uri;
|
2020-03-03 18:01:39 +01:00
|
|
|
import android.os.Build;
|
2015-12-15 00:26:06 +01:00
|
|
|
import android.telephony.SmsManager;
|
2015-05-23 00:54:14 +02:00
|
|
|
|
2020-10-06 21:00:42 +02:00
|
|
|
import androidx.annotation.RequiresApi;
|
2020-08-28 15:38:18 +02:00
|
|
|
import androidx.core.app.NotificationCompat;
|
|
|
|
import androidx.core.content.FileProvider;
|
|
|
|
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
|
|
|
|
|
2015-05-23 00:54:14 +02:00
|
|
|
import org.slf4j.Logger;
|
|
|
|
import org.slf4j.LoggerFactory;
|
|
|
|
|
2015-06-27 00:21:30 +02:00
|
|
|
import java.io.File;
|
2015-10-28 23:54:08 +01:00
|
|
|
import java.io.IOException;
|
2015-08-18 17:37:51 +02:00
|
|
|
import java.text.DateFormat;
|
2015-06-25 23:34:50 +02:00
|
|
|
import java.text.SimpleDateFormat;
|
2023-01-05 12:36:11 +01:00
|
|
|
import java.util.ArrayList;
|
2015-06-25 23:34:50 +02:00
|
|
|
import java.util.Date;
|
2017-03-10 23:10:40 +01:00
|
|
|
import java.util.Locale;
|
2016-01-11 15:29:12 +01:00
|
|
|
import java.util.Objects;
|
2023-01-05 12:36:11 +01:00
|
|
|
import java.util.UUID;
|
2015-06-25 23:34:50 +02:00
|
|
|
|
2015-12-14 23:31:31 +01:00
|
|
|
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
|
2015-08-31 17:25:58 +02:00
|
|
|
import nodomain.freeyourgadget.gadgetbridge.R;
|
2018-01-19 23:10:08 +01:00
|
|
|
import nodomain.freeyourgadget.gadgetbridge.activities.FindPhoneActivity;
|
2016-06-14 15:56:38 +02:00
|
|
|
import nodomain.freeyourgadget.gadgetbridge.activities.appmanager.AbstractAppManagerFragment;
|
2023-12-07 01:50:14 +01:00
|
|
|
import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst;
|
2023-07-04 00:19:19 +02:00
|
|
|
import nodomain.freeyourgadget.gadgetbridge.capabilities.loyaltycards.LoyaltyCard;
|
2021-03-05 07:49:19 +01:00
|
|
|
import nodomain.freeyourgadget.gadgetbridge.database.DBAccess;
|
2021-01-31 11:10:03 +01:00
|
|
|
import nodomain.freeyourgadget.gadgetbridge.database.DBHandler;
|
|
|
|
import nodomain.freeyourgadget.gadgetbridge.database.DBHelper;
|
2015-06-23 11:54:33 +02:00
|
|
|
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEvent;
|
|
|
|
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventAppInfo;
|
2015-08-31 17:25:58 +02:00
|
|
|
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventBatteryInfo;
|
2015-06-23 11:54:33 +02:00
|
|
|
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventCallControl;
|
2016-04-03 00:50:45 +02:00
|
|
|
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventDisplayMessage;
|
2018-01-19 23:10:08 +01:00
|
|
|
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventFindPhone;
|
2018-10-31 21:47:12 +01:00
|
|
|
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventFmFrequency;
|
2023-12-07 01:50:14 +01:00
|
|
|
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventSleepStateDetection;
|
2021-12-12 19:38:14 +01:00
|
|
|
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventUpdateDeviceInfo;
|
2018-07-28 17:23:58 +02:00
|
|
|
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventLEDColor;
|
2015-06-23 11:54:33 +02:00
|
|
|
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventMusicControl;
|
2015-08-31 22:27:25 +02:00
|
|
|
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventNotificationControl;
|
2021-12-12 19:38:14 +01:00
|
|
|
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventUpdateDeviceState;
|
|
|
|
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventUpdatePreferences;
|
2015-06-24 23:55:51 +02:00
|
|
|
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventScreenshot;
|
2015-06-23 11:54:33 +02:00
|
|
|
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventVersionInfo;
|
2023-12-07 01:50:14 +01:00
|
|
|
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventWearState;
|
2021-01-31 11:10:03 +01:00
|
|
|
import nodomain.freeyourgadget.gadgetbridge.entities.BatteryLevel;
|
|
|
|
import nodomain.freeyourgadget.gadgetbridge.entities.DaoSession;
|
|
|
|
import nodomain.freeyourgadget.gadgetbridge.entities.Device;
|
2015-07-21 01:25:22 +02:00
|
|
|
import nodomain.freeyourgadget.gadgetbridge.externalevents.NotificationListener;
|
2023-12-07 01:50:14 +01:00
|
|
|
import nodomain.freeyourgadget.gadgetbridge.externalevents.opentracks.OpenTracksController;
|
2015-08-31 17:25:58 +02:00
|
|
|
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
2023-01-05 12:36:11 +01:00
|
|
|
import nodomain.freeyourgadget.gadgetbridge.model.Alarm;
|
2015-08-31 17:25:58 +02:00
|
|
|
import nodomain.freeyourgadget.gadgetbridge.model.BatteryState;
|
2023-01-05 12:36:11 +01:00
|
|
|
import nodomain.freeyourgadget.gadgetbridge.model.CalendarEventSpec;
|
|
|
|
import nodomain.freeyourgadget.gadgetbridge.model.CallSpec;
|
|
|
|
import nodomain.freeyourgadget.gadgetbridge.model.CannedMessagesSpec;
|
2023-05-18 00:43:29 +02:00
|
|
|
import nodomain.freeyourgadget.gadgetbridge.model.Contact;
|
2023-01-05 12:36:11 +01:00
|
|
|
import nodomain.freeyourgadget.gadgetbridge.model.MusicSpec;
|
|
|
|
import nodomain.freeyourgadget.gadgetbridge.model.MusicStateSpec;
|
|
|
|
import nodomain.freeyourgadget.gadgetbridge.model.NotificationSpec;
|
|
|
|
import nodomain.freeyourgadget.gadgetbridge.model.Reminder;
|
2023-12-07 01:50:14 +01:00
|
|
|
import nodomain.freeyourgadget.gadgetbridge.model.SleepState;
|
|
|
|
import nodomain.freeyourgadget.gadgetbridge.model.WearingState;
|
2023-01-05 12:36:11 +01:00
|
|
|
import nodomain.freeyourgadget.gadgetbridge.model.WeatherSpec;
|
|
|
|
import nodomain.freeyourgadget.gadgetbridge.model.WorldClock;
|
2021-10-20 22:37:23 +02:00
|
|
|
import nodomain.freeyourgadget.gadgetbridge.model.NavigationInfoSpec;
|
2015-08-31 17:25:58 +02:00
|
|
|
import nodomain.freeyourgadget.gadgetbridge.service.receivers.GBCallControlReceiver;
|
|
|
|
import nodomain.freeyourgadget.gadgetbridge.service.receivers.GBMusicControlReceiver;
|
|
|
|
import nodomain.freeyourgadget.gadgetbridge.util.GB;
|
2022-10-09 14:53:04 +02:00
|
|
|
import nodomain.freeyourgadget.gadgetbridge.util.PendingIntentUtils;
|
2023-10-06 10:32:22 +02:00
|
|
|
import nodomain.freeyourgadget.gadgetbridge.util.Prefs;
|
2015-04-14 01:24:03 +02:00
|
|
|
|
2020-03-03 18:01:39 +01:00
|
|
|
import static nodomain.freeyourgadget.gadgetbridge.util.GB.NOTIFICATION_CHANNEL_HIGH_PRIORITY_ID;
|
2018-02-14 21:27:24 +01:00
|
|
|
|
2015-04-19 02:37:29 +02:00
|
|
|
// 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.
|
2015-08-02 00:12:21 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Abstract implementation of DeviceSupport with some implementations for
|
|
|
|
* common functionality. Still transport independent.
|
|
|
|
*/
|
2015-04-14 01:24:03 +02:00
|
|
|
public abstract class AbstractDeviceSupport implements DeviceSupport {
|
2015-05-23 00:54:14 +02:00
|
|
|
private static final Logger LOG = LoggerFactory.getLogger(AbstractDeviceSupport.class);
|
2015-06-26 23:17:31 +02:00
|
|
|
private static final int NOTIFICATION_ID_SCREENSHOT = 8000;
|
2015-05-23 00:54:14 +02:00
|
|
|
|
2015-05-22 20:20:33 +02:00
|
|
|
protected GBDevice gbDevice;
|
2015-04-14 01:24:03 +02:00
|
|
|
private BluetoothAdapter btAdapter;
|
|
|
|
private Context context;
|
2016-04-28 23:17:13 +02:00
|
|
|
private boolean autoReconnect;
|
2015-04-14 01:24:03 +02:00
|
|
|
|
2020-03-03 18:01:39 +01:00
|
|
|
|
|
|
|
|
2016-09-10 10:52:02 +02:00
|
|
|
@Override
|
2015-08-02 00:12:21 +02:00
|
|
|
public void setContext(GBDevice gbDevice, BluetoothAdapter btAdapter, Context context) {
|
2015-04-14 01:24:03 +02:00
|
|
|
this.gbDevice = gbDevice;
|
|
|
|
this.btAdapter = btAdapter;
|
|
|
|
this.context = context;
|
|
|
|
}
|
2015-04-14 10:29:09 +02:00
|
|
|
|
2017-04-12 21:33:19 +02:00
|
|
|
/**
|
|
|
|
* Default implementation just calls #connect()
|
|
|
|
*/
|
|
|
|
@Override
|
|
|
|
public boolean connectFirstTime() {
|
|
|
|
return connect();
|
|
|
|
}
|
|
|
|
|
2015-04-19 02:37:29 +02:00
|
|
|
@Override
|
|
|
|
public boolean isConnected() {
|
|
|
|
return gbDevice.isConnected();
|
|
|
|
}
|
2015-04-19 11:28:03 +02:00
|
|
|
|
2015-08-02 00:12:21 +02:00
|
|
|
/**
|
|
|
|
* Returns true if the device is not only connected, but also
|
|
|
|
* initialized.
|
2015-08-31 17:25:58 +02:00
|
|
|
*
|
2015-08-02 00:12:21 +02:00
|
|
|
* @see GBDevice#isInitialized()
|
|
|
|
*/
|
2015-04-19 02:37:29 +02:00
|
|
|
protected boolean isInitialized() {
|
|
|
|
return gbDevice.isInitialized();
|
|
|
|
}
|
2015-04-19 11:28:03 +02:00
|
|
|
|
2016-04-28 23:17:13 +02:00
|
|
|
@Override
|
|
|
|
public void setAutoReconnect(boolean enable) {
|
|
|
|
autoReconnect = enable;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public boolean getAutoReconnect() {
|
|
|
|
return autoReconnect;
|
|
|
|
}
|
|
|
|
|
2022-10-22 23:00:01 +02:00
|
|
|
@Override
|
|
|
|
public boolean getImplicitCallbackModify() {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2015-04-14 01:24:03 +02:00
|
|
|
@Override
|
|
|
|
public GBDevice getDevice() {
|
|
|
|
return gbDevice;
|
|
|
|
}
|
2015-04-14 10:29:09 +02:00
|
|
|
|
2015-04-14 01:24:03 +02:00
|
|
|
@Override
|
|
|
|
public BluetoothAdapter getBluetoothAdapter() {
|
|
|
|
return btAdapter;
|
|
|
|
}
|
2015-04-14 10:29:09 +02:00
|
|
|
|
2015-04-14 01:24:03 +02:00
|
|
|
@Override
|
|
|
|
public Context getContext() {
|
|
|
|
return context;
|
|
|
|
}
|
2015-05-23 00:54:14 +02:00
|
|
|
|
2015-06-23 11:54:33 +02:00
|
|
|
public void evaluateGBDeviceEvent(GBDeviceEvent deviceEvent) {
|
2015-08-31 17:25:58 +02:00
|
|
|
if (deviceEvent instanceof GBDeviceEventMusicControl) {
|
|
|
|
handleGBDeviceEvent((GBDeviceEventMusicControl) deviceEvent);
|
|
|
|
} else if (deviceEvent instanceof GBDeviceEventCallControl) {
|
|
|
|
handleGBDeviceEvent((GBDeviceEventCallControl) 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);
|
2015-08-31 22:27:25 +02:00
|
|
|
} else if (deviceEvent instanceof GBDeviceEventNotificationControl) {
|
|
|
|
handleGBDeviceEvent((GBDeviceEventNotificationControl) deviceEvent);
|
2015-08-31 17:25:58 +02:00
|
|
|
} else if (deviceEvent instanceof GBDeviceEventBatteryInfo) {
|
|
|
|
handleGBDeviceEvent((GBDeviceEventBatteryInfo) deviceEvent);
|
2018-01-19 23:10:08 +01:00
|
|
|
} else if (deviceEvent instanceof GBDeviceEventFindPhone) {
|
|
|
|
handleGBDeviceEvent((GBDeviceEventFindPhone) deviceEvent);
|
2018-07-28 17:23:58 +02:00
|
|
|
} else if (deviceEvent instanceof GBDeviceEventLEDColor) {
|
|
|
|
handleGBDeviceEvent((GBDeviceEventLEDColor) deviceEvent);
|
2021-12-12 19:38:14 +01:00
|
|
|
} else if (deviceEvent instanceof GBDeviceEventUpdateDeviceInfo) {
|
|
|
|
handleGBDeviceEvent((GBDeviceEventUpdateDeviceInfo) deviceEvent);
|
|
|
|
} else if (deviceEvent instanceof GBDeviceEventUpdatePreferences) {
|
|
|
|
handleGBDeviceEvent((GBDeviceEventUpdatePreferences) deviceEvent);
|
|
|
|
} else if (deviceEvent instanceof GBDeviceEventUpdateDeviceState) {
|
|
|
|
handleGBDeviceEvent((GBDeviceEventUpdateDeviceState) deviceEvent);
|
2018-07-28 17:23:58 +02:00
|
|
|
} else if (deviceEvent instanceof GBDeviceEventFmFrequency) {
|
|
|
|
handleGBDeviceEvent((GBDeviceEventFmFrequency) deviceEvent);
|
2023-12-07 01:50:14 +01:00
|
|
|
} else if (deviceEvent instanceof GBDeviceEventWearState) {
|
|
|
|
handleGBDeviceEvent((GBDeviceEventWearState) deviceEvent);
|
|
|
|
} else if (deviceEvent instanceof GBDeviceEventSleepStateDetection) {
|
|
|
|
handleGBDeviceEvent((GBDeviceEventSleepStateDetection) deviceEvent);
|
2018-01-19 23:10:08 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-10-22 21:53:45 +02:00
|
|
|
private void handleGBDeviceEvent(final GBDeviceEventFindPhone deviceEvent) {
|
|
|
|
final Context context = getContext();
|
|
|
|
LOG.info("Got GBDeviceEventFindPhone: {}", deviceEvent.event);
|
2018-01-19 23:10:08 +01:00
|
|
|
switch (deviceEvent.event) {
|
|
|
|
case START:
|
2022-10-22 21:53:45 +02:00
|
|
|
handleGBDeviceEventFindPhoneStart(true);
|
|
|
|
break;
|
|
|
|
case START_VIBRATE:
|
|
|
|
handleGBDeviceEventFindPhoneStart(false);
|
|
|
|
break;
|
|
|
|
case VIBRATE:
|
|
|
|
final Intent intentVibrate = new Intent(FindPhoneActivity.ACTION_VIBRATE);
|
|
|
|
LocalBroadcastManager.getInstance(context).sendBroadcast(intentVibrate);
|
|
|
|
break;
|
|
|
|
case RING:
|
|
|
|
final Intent intentRing = new Intent(FindPhoneActivity.ACTION_RING);
|
|
|
|
LocalBroadcastManager.getInstance(context).sendBroadcast(intentRing);
|
2018-01-19 23:10:08 +01:00
|
|
|
break;
|
|
|
|
case STOP:
|
2022-10-22 21:53:45 +02:00
|
|
|
final Intent intentStop = new Intent(FindPhoneActivity.ACTION_FOUND);
|
|
|
|
LocalBroadcastManager.getInstance(context).sendBroadcast(intentStop);
|
2018-01-19 23:10:08 +01:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
LOG.warn("unknown GBDeviceEventFindPhone");
|
2015-05-23 00:54:14 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-10-22 21:53:45 +02:00
|
|
|
private void handleGBDeviceEventFindPhoneStart(final boolean ring) {
|
2020-08-28 15:38:18 +02:00
|
|
|
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) { // this could be used if app in foreground // TODO: Below Q?
|
2020-03-03 18:01:39 +01:00
|
|
|
Intent startIntent = new Intent(getContext(), FindPhoneActivity.class);
|
|
|
|
startIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
2022-10-22 21:53:45 +02:00
|
|
|
startIntent.putExtra(FindPhoneActivity.EXTRA_RING, ring);
|
2020-03-03 18:01:39 +01:00
|
|
|
context.startActivity(startIntent);
|
2020-08-28 15:38:18 +02:00
|
|
|
} else {
|
2022-10-22 21:53:45 +02:00
|
|
|
handleGBDeviceEventFindPhoneStartNotification(ring);
|
2020-03-03 18:01:39 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-10-06 21:00:42 +02:00
|
|
|
@RequiresApi(Build.VERSION_CODES.Q)
|
2022-10-22 21:53:45 +02:00
|
|
|
private void handleGBDeviceEventFindPhoneStartNotification(final boolean ring) {
|
2020-03-03 18:01:39 +01:00
|
|
|
LOG.info("Got handleGBDeviceEventFindPhoneStartNotification");
|
|
|
|
Intent intent = new Intent(context, FindPhoneActivity.class);
|
2022-10-22 21:53:45 +02:00
|
|
|
intent.putExtra(FindPhoneActivity.EXTRA_RING, ring);
|
2020-10-06 19:35:26 +02:00
|
|
|
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
2020-03-03 18:01:39 +01:00
|
|
|
|
2022-10-09 14:53:04 +02:00
|
|
|
PendingIntent pi = PendingIntentUtils.getActivity(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT, false);
|
2020-10-06 21:00:42 +02:00
|
|
|
|
|
|
|
NotificationCompat.Builder notification = new NotificationCompat.Builder(context, NOTIFICATION_CHANNEL_HIGH_PRIORITY_ID )
|
2020-03-03 18:01:39 +01:00
|
|
|
.setSmallIcon(R.drawable.ic_notification)
|
|
|
|
.setOngoing(false)
|
|
|
|
.setFullScreenIntent(pi, true)
|
|
|
|
.setPriority(NotificationCompat.PRIORITY_HIGH)
|
|
|
|
.setAutoCancel(true)
|
|
|
|
.setContentTitle( context.getString( R.string.find_my_phone_notification ) );
|
2020-10-06 21:00:42 +02:00
|
|
|
|
2020-03-03 18:01:39 +01:00
|
|
|
notification.setGroup("BackgroundService");
|
|
|
|
|
2020-10-06 21:00:42 +02:00
|
|
|
CompanionDeviceManager manager = (CompanionDeviceManager) context.getSystemService(Context.COMPANION_DEVICE_SERVICE);
|
|
|
|
if (manager.getAssociations().size() > 0) {
|
2021-05-14 18:30:54 +02:00
|
|
|
GB.notify(GB.NOTIFICATION_ID_PHONE_FIND, notification.build(), context);
|
2020-10-06 21:00:42 +02:00
|
|
|
context.startActivity(intent);
|
|
|
|
LOG.debug("CompanionDeviceManager associations were found, starting intent");
|
|
|
|
} else {
|
2021-05-14 18:30:54 +02:00
|
|
|
GB.notify(GB.NOTIFICATION_ID_PHONE_FIND, notification.build(), context);
|
2023-10-13 20:00:53 +02:00
|
|
|
LOG.warn("CompanionDeviceManager associations were not found, can't start intent");
|
2020-10-06 21:00:42 +02:00
|
|
|
}
|
2020-03-03 18:01:39 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-03-10 23:10:40 +01:00
|
|
|
private void handleGBDeviceEvent(GBDeviceEventMusicControl musicEvent) {
|
2015-05-23 00:54:14 +02:00
|
|
|
Context context = getContext();
|
2015-06-23 11:54:33 +02:00
|
|
|
LOG.info("Got event for MUSIC_CONTROL");
|
2015-05-23 00:54:14 +02:00
|
|
|
Intent musicIntent = new Intent(GBMusicControlReceiver.ACTION_MUSICCONTROL);
|
2015-06-23 11:54:33 +02:00
|
|
|
musicIntent.putExtra("event", musicEvent.event.ordinal());
|
2015-05-23 00:54:14 +02:00
|
|
|
musicIntent.setPackage(context.getPackageName());
|
|
|
|
context.sendBroadcast(musicIntent);
|
|
|
|
}
|
|
|
|
|
2017-03-10 23:10:40 +01:00
|
|
|
private void handleGBDeviceEvent(GBDeviceEventCallControl callEvent) {
|
2015-05-23 00:54:14 +02:00
|
|
|
Context context = getContext();
|
2015-06-23 11:54:33 +02:00
|
|
|
LOG.info("Got event for CALL_CONTROL");
|
2019-05-25 15:56:21 +02:00
|
|
|
if(callEvent.event == GBDeviceEventCallControl.Event.IGNORE) {
|
|
|
|
LOG.info("Sending intent for mute");
|
2020-08-28 15:38:18 +02:00
|
|
|
Intent broadcastIntent = new Intent(context.getPackageName() + ".MUTE_CALL");
|
2019-05-25 15:56:21 +02:00
|
|
|
broadcastIntent.setPackage(context.getPackageName());
|
|
|
|
context.sendBroadcast(broadcastIntent);
|
|
|
|
return;
|
|
|
|
}
|
2015-05-23 00:54:14 +02:00
|
|
|
Intent callIntent = new Intent(GBCallControlReceiver.ACTION_CALLCONTROL);
|
2015-06-23 11:54:33 +02:00
|
|
|
callIntent.putExtra("event", callEvent.event.ordinal());
|
2015-05-23 00:54:14 +02:00
|
|
|
callIntent.setPackage(context.getPackageName());
|
|
|
|
context.sendBroadcast(callIntent);
|
|
|
|
}
|
|
|
|
|
2017-03-10 23:10:40 +01:00
|
|
|
protected void handleGBDeviceEvent(GBDeviceEventVersionInfo infoEvent) {
|
2015-05-23 00:54:14 +02:00
|
|
|
Context context = getContext();
|
2018-08-06 20:20:54 +02:00
|
|
|
LOG.info("Got event for VERSION_INFO: " + infoEvent);
|
2015-05-23 00:54:14 +02:00
|
|
|
if (gbDevice == null) {
|
|
|
|
return;
|
|
|
|
}
|
2023-10-15 15:37:41 +02:00
|
|
|
if (infoEvent.fwVersion != null) {
|
|
|
|
gbDevice.setFirmwareVersion(infoEvent.fwVersion);
|
|
|
|
}
|
2023-07-26 00:26:04 +02:00
|
|
|
if (infoEvent.fwVersion2 != null) {
|
|
|
|
gbDevice.setFirmwareVersion2(infoEvent.fwVersion2);
|
|
|
|
}
|
2016-08-26 20:57:59 +02:00
|
|
|
gbDevice.setModel(infoEvent.hwVersion);
|
2015-05-23 00:54:14 +02:00
|
|
|
gbDevice.sendDeviceUpdateIntent(context);
|
|
|
|
}
|
|
|
|
|
2018-07-28 17:23:58 +02:00
|
|
|
protected void handleGBDeviceEvent(GBDeviceEventLEDColor colorEvent) {
|
|
|
|
Context context = getContext();
|
2023-09-11 11:17:04 +02:00
|
|
|
LOG.info("Got event for LED Color: #" + Integer.toHexString(colorEvent.color).toUpperCase(Locale.ROOT));
|
2018-07-28 17:23:58 +02:00
|
|
|
if (gbDevice == null) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
gbDevice.setExtraInfo("led_color", colorEvent.color);
|
|
|
|
gbDevice.sendDeviceUpdateIntent(context);
|
|
|
|
}
|
|
|
|
|
2021-12-12 19:38:14 +01:00
|
|
|
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()));
|
2022-10-22 21:53:45 +02:00
|
|
|
gbDevice.sendDeviceUpdateIntent(context);
|
2021-12-12 19:38:14 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
protected void handleGBDeviceEvent(GBDeviceEventUpdateDeviceState updateDeviceState) {
|
|
|
|
if (gbDevice == null) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
gbDevice.setState(updateDeviceState.state);
|
|
|
|
gbDevice.sendDeviceUpdateIntent(getContext());
|
|
|
|
}
|
|
|
|
|
2018-07-28 17:23:58 +02:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2017-03-10 23:10:40 +01:00
|
|
|
private void handleGBDeviceEvent(GBDeviceEventAppInfo appInfoEvent) {
|
2015-05-23 00:54:14 +02:00
|
|
|
Context context = getContext();
|
2015-06-23 11:54:33 +02:00
|
|
|
LOG.info("Got event for APP_INFO");
|
2015-05-23 00:54:14 +02:00
|
|
|
|
2016-06-14 15:56:38 +02:00
|
|
|
Intent appInfoIntent = new Intent(AbstractAppManagerFragment.ACTION_REFRESH_APPLIST);
|
2015-06-23 11:54:33 +02:00
|
|
|
int appCount = appInfoEvent.apps.length;
|
2015-05-23 00:54:14 +02:00
|
|
|
appInfoIntent.putExtra("app_count", appCount);
|
2018-09-15 23:56:44 +02:00
|
|
|
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());
|
2022-07-04 17:12:41 +02:00
|
|
|
appInfoIntent.putExtra("app_version" + i, appInfoEvent.apps[i].getVersion());
|
2018-09-15 23:56:44 +02:00
|
|
|
appInfoIntent.putExtra("app_uuid" + i, appInfoEvent.apps[i].getUUID().toString());
|
|
|
|
appInfoIntent.putExtra("app_type" + i, appInfoEvent.apps[i].getType().ordinal());
|
2015-05-23 00:54:14 +02:00
|
|
|
}
|
|
|
|
LocalBroadcastManager.getInstance(context).sendBroadcast(appInfoIntent);
|
|
|
|
}
|
|
|
|
|
2015-06-24 23:55:51 +02:00
|
|
|
private void handleGBDeviceEvent(GBDeviceEventScreenshot screenshot) {
|
2023-06-11 17:54:50 +02:00
|
|
|
if (screenshot.getData() == null) {
|
|
|
|
LOG.warn("Screnshot data is null");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2017-03-10 23:10:40 +01:00
|
|
|
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd-hhmmss", Locale.US);
|
2015-06-26 23:17:31 +02:00
|
|
|
String filename = "screenshot_" + dateFormat.format(new Date()) + ".bmp";
|
|
|
|
|
2015-10-28 23:54:08 +01:00
|
|
|
try {
|
|
|
|
String fullpath = GB.writeScreenshot(screenshot, filename);
|
2015-06-27 00:21:30 +02:00
|
|
|
Bitmap bmp = BitmapFactory.decodeFile(fullpath);
|
|
|
|
Intent intent = new Intent();
|
|
|
|
intent.setAction(android.content.Intent.ACTION_VIEW);
|
2017-03-10 23:10:40 +01:00
|
|
|
Uri screenshotURI = FileProvider.getUriForFile(context, context.getApplicationContext().getPackageName() + ".screenshot_provider", new File(fullpath));
|
|
|
|
intent.setDataAndType(screenshotURI, "image/*");
|
2023-07-17 01:09:10 +02:00
|
|
|
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
2015-06-27 00:21:30 +02:00
|
|
|
|
2022-10-09 14:53:04 +02:00
|
|
|
PendingIntent pIntent = PendingIntentUtils.getActivity(context, 0, intent, 0, false);
|
2015-06-26 23:17:31 +02:00
|
|
|
|
2015-06-27 18:09:49 +02:00
|
|
|
Intent shareIntent = new Intent(Intent.ACTION_SEND);
|
|
|
|
shareIntent.setType("image/*");
|
2017-09-03 14:11:51 +02:00
|
|
|
shareIntent.putExtra(Intent.EXTRA_STREAM, screenshotURI);
|
2015-06-27 18:09:49 +02:00
|
|
|
|
2023-06-11 18:35:34 +02:00
|
|
|
PendingIntent pendingShareIntent = PendingIntentUtils.getActivity(context, 0, Intent.createChooser(shareIntent, context.getString(R.string.share_screenshot)),
|
2022-10-09 14:53:04 +02:00
|
|
|
PendingIntent.FLAG_UPDATE_CURRENT, false);
|
2015-06-27 18:09:49 +02:00
|
|
|
|
2023-06-11 18:35:34 +02:00
|
|
|
NotificationCompat.Action action = new NotificationCompat.Action.Builder(android.R.drawable.ic_menu_share, context.getString(R.string.share), pendingShareIntent).build();
|
2017-03-10 23:10:40 +01:00
|
|
|
|
2023-06-11 18:31:12 +02:00
|
|
|
Notification notif = new NotificationCompat.Builder(context, NOTIFICATION_CHANNEL_HIGH_PRIORITY_ID)
|
2023-06-11 18:35:34 +02:00
|
|
|
.setContentTitle(context.getString(R.string.screenshot_taken))
|
|
|
|
.setTicker(context.getString(R.string.screenshot_taken))
|
2015-06-26 23:17:31 +02:00
|
|
|
.setContentText(filename)
|
|
|
|
.setSmallIcon(R.drawable.ic_notification)
|
2017-03-10 23:10:40 +01:00
|
|
|
.setStyle(new NotificationCompat.BigPictureStyle()
|
2015-06-26 23:17:31 +02:00
|
|
|
.bigPicture(bmp))
|
2015-06-27 00:21:30 +02:00
|
|
|
.setContentIntent(pIntent)
|
2017-03-10 23:10:40 +01:00
|
|
|
.addAction(action)
|
|
|
|
.setAutoCancel(true)
|
2015-06-26 23:17:31 +02:00
|
|
|
.build();
|
2015-06-27 18:09:49 +02:00
|
|
|
|
2021-05-14 18:30:54 +02:00
|
|
|
GB.notify(NOTIFICATION_ID_SCREENSHOT, notif, context);
|
2015-10-28 23:54:08 +01:00
|
|
|
} catch (IOException ex) {
|
|
|
|
LOG.error("Error writing screenshot", ex);
|
2015-06-26 23:17:31 +02:00
|
|
|
}
|
2015-06-24 23:55:51 +02:00
|
|
|
}
|
2015-07-21 01:25:22 +02:00
|
|
|
|
2015-08-31 22:27:25 +02:00
|
|
|
private void handleGBDeviceEvent(GBDeviceEventNotificationControl deviceEvent) {
|
2015-07-21 01:25:22 +02:00
|
|
|
Context context = getContext();
|
2015-08-31 22:27:25 +02:00
|
|
|
LOG.info("Got NOTIFICATION CONTROL device event");
|
|
|
|
String action = null;
|
|
|
|
switch (deviceEvent.event) {
|
|
|
|
case DISMISS:
|
|
|
|
action = NotificationListener.ACTION_DISMISS;
|
|
|
|
break;
|
2015-09-01 21:58:36 +02:00
|
|
|
case DISMISS_ALL:
|
|
|
|
action = NotificationListener.ACTION_DISMISS_ALL;
|
|
|
|
break;
|
2015-08-31 22:27:25 +02:00
|
|
|
case OPEN:
|
|
|
|
action = NotificationListener.ACTION_OPEN;
|
|
|
|
break;
|
2015-09-25 00:53:40 +02:00
|
|
|
case MUTE:
|
|
|
|
action = NotificationListener.ACTION_MUTE;
|
|
|
|
break;
|
2015-12-13 22:43:53 +01:00
|
|
|
case REPLY:
|
2016-06-21 00:31:53 +02:00
|
|
|
if (deviceEvent.phoneNumber == null) {
|
2018-11-01 19:12:43 +01:00
|
|
|
deviceEvent.phoneNumber = (String) GBApplication.getIDSenderLookup().lookup((int) (deviceEvent.handle >> 4));
|
2016-06-21 00:31:53 +02:00
|
|
|
}
|
|
|
|
if (deviceEvent.phoneNumber != null) {
|
2018-03-22 22:47:40 +01:00
|
|
|
LOG.info("Got notification reply for SMS from " + deviceEvent.phoneNumber + " : " + deviceEvent.reply);
|
2016-06-21 00:31:53 +02:00
|
|
|
SmsManager.getDefault().sendTextMessage(deviceEvent.phoneNumber, null, deviceEvent.reply, null, null);
|
2016-01-09 17:54:17 +01:00
|
|
|
} else {
|
2018-03-22 22:47:40 +01:00
|
|
|
LOG.info("Got notification reply for notification id " + deviceEvent.handle + " : " + deviceEvent.reply);
|
2016-01-09 17:54:17 +01:00
|
|
|
action = NotificationListener.ACTION_REPLY;
|
2015-12-14 23:31:31 +01:00
|
|
|
}
|
2015-12-13 22:43:53 +01:00
|
|
|
break;
|
2015-08-31 22:27:25 +02:00
|
|
|
}
|
|
|
|
if (action != null) {
|
|
|
|
Intent notificationListenerIntent = new Intent(action);
|
|
|
|
notificationListenerIntent.putExtra("handle", deviceEvent.handle);
|
2018-10-31 21:47:12 +01:00
|
|
|
notificationListenerIntent.putExtra("title", deviceEvent.title);
|
2016-01-09 17:54:17 +01:00
|
|
|
if (deviceEvent.reply != null) {
|
2020-10-13 00:25:43 +02:00
|
|
|
SharedPreferences prefs = GBApplication.getDeviceSpecificSharedPrefs(gbDevice.getAddress());
|
2016-04-25 23:39:03 +02:00
|
|
|
String suffix = prefs.getString("canned_reply_suffix", null);
|
2016-01-11 15:29:12 +01:00
|
|
|
if (suffix != null && !Objects.equals(suffix, "")) {
|
|
|
|
deviceEvent.reply += suffix;
|
|
|
|
}
|
2016-01-09 17:54:17 +01:00
|
|
|
notificationListenerIntent.putExtra("reply", deviceEvent.reply);
|
|
|
|
}
|
2015-08-31 22:27:25 +02:00
|
|
|
LocalBroadcastManager.getInstance(context).sendBroadcast(notificationListenerIntent);
|
|
|
|
}
|
2015-07-21 01:25:22 +02:00
|
|
|
}
|
2015-08-18 17:37:51 +02:00
|
|
|
|
2017-03-10 23:10:40 +01:00
|
|
|
protected void handleGBDeviceEvent(GBDeviceEventBatteryInfo deviceEvent) {
|
2015-08-18 17:37:51 +02:00
|
|
|
Context context = getContext();
|
|
|
|
LOG.info("Got BATTERY_INFO device event");
|
2021-10-16 22:40:30 +02:00
|
|
|
gbDevice.setBatteryLevel(deviceEvent.level, deviceEvent.batteryIndex);
|
2015-08-21 08:41:57 +02:00
|
|
|
gbDevice.setBatteryState(deviceEvent.state);
|
2021-10-16 22:40:30 +02:00
|
|
|
gbDevice.setBatteryVoltage(deviceEvent.voltage, deviceEvent.batteryIndex);
|
2015-08-18 17:37:51 +02:00
|
|
|
|
2018-09-04 22:28:45 +02:00
|
|
|
if (deviceEvent.level == GBDevice.BATTERY_UNKNOWN) {
|
|
|
|
// no level available, just "high" or "low"
|
|
|
|
if (BatteryState.BATTERY_LOW.equals(deviceEvent.state)) {
|
2023-11-10 00:14:38 +01:00
|
|
|
GB.updateBatteryNotification(context.getString(R.string.notif_battery_low, gbDevice.getAliasOrName()),
|
2018-09-04 22:28:45 +02:00
|
|
|
deviceEvent.extendedInfoAvailable() ?
|
2023-11-10 00:14:38 +01:00
|
|
|
context.getString(R.string.notif_battery_low_extended, gbDevice.getAliasOrName(),
|
2018-09-04 22:28:45 +02:00
|
|
|
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 {
|
|
|
|
GB.removeBatteryNotification(context);
|
|
|
|
}
|
2017-04-24 09:53:48 +02:00
|
|
|
} else {
|
2021-03-05 07:49:19 +01:00
|
|
|
createStoreTask("Storing battery data", context, deviceEvent).execute();
|
2021-01-31 11:10:03 +01:00
|
|
|
|
2018-09-04 22:28:45 +02:00
|
|
|
//show the notification if the battery level is below threshold and only if not connected to charger
|
|
|
|
if (deviceEvent.level <= gbDevice.getBatteryThresholdPercent() &&
|
|
|
|
(BatteryState.BATTERY_LOW.equals(deviceEvent.state) ||
|
|
|
|
BatteryState.BATTERY_NORMAL.equals(deviceEvent.state))
|
|
|
|
) {
|
2023-11-10 00:14:38 +01:00
|
|
|
GB.updateBatteryNotification(context.getString(R.string.notif_battery_low_percent, gbDevice.getAliasOrName(), String.valueOf(deviceEvent.level)),
|
2018-09-04 22:28:45 +02:00
|
|
|
deviceEvent.extendedInfoAvailable() ?
|
2023-11-10 00:14:38 +01:00
|
|
|
context.getString(R.string.notif_battery_low_percent, gbDevice.getAliasOrName(), String.valueOf(deviceEvent.level)) + "\n" +
|
2018-09-04 22:28:45 +02:00
|
|
|
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 {
|
|
|
|
GB.removeBatteryNotification(context);
|
|
|
|
}
|
2015-08-18 17:37:51 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
gbDevice.sendDeviceUpdateIntent(context);
|
|
|
|
}
|
|
|
|
|
2023-12-07 01:50:14 +01:00
|
|
|
/**
|
|
|
|
* Helper method to run specific actions configured in the device preferences, upon wear state
|
|
|
|
* or awake/asleep events.
|
|
|
|
*
|
|
|
|
* @param action
|
|
|
|
* @param message
|
|
|
|
*/
|
|
|
|
private void handleDeviceAction(String action, String message) {
|
|
|
|
String actionDisabled = getContext().getString(R.string.pref_button_action_disabled_value);
|
|
|
|
|
|
|
|
if (actionDisabled.equals(action)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
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);
|
2023-12-09 12:01:55 +01:00
|
|
|
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);
|
2023-12-07 01:50:14 +01:00
|
|
|
|
|
|
|
if (actionBroadcast.equals(action)) {
|
|
|
|
if (message != null) {
|
|
|
|
Intent in = new Intent();
|
|
|
|
in.setAction(message);
|
|
|
|
LOG.info("Sending broadcast " + message);
|
|
|
|
getContext().getApplicationContext().sendBroadcast(in);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (actionFitnessControlStart.equals(action)) {
|
|
|
|
OpenTracksController.startRecording(getContext());
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (actionFitnessControlStop.equals(action)) {
|
|
|
|
OpenTracksController.stopRecording(getContext());
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (actionFitnessControlToggle.equals(action)) {
|
|
|
|
OpenTracksController.toggleRecording(getContext());
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (actionMediaPlay.equals(action) ||
|
|
|
|
actionMediaPause.equals(action) ||
|
|
|
|
actionMediaPlayPause.equals(action)
|
|
|
|
) {
|
|
|
|
GBDeviceEventMusicControl deviceEventMusicControl = new GBDeviceEventMusicControl();
|
|
|
|
deviceEventMusicControl.event = GBDeviceEventMusicControl.Event.valueOf(action);
|
|
|
|
evaluateGBDeviceEvent(deviceEventMusicControl);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2023-12-09 12:01:55 +01:00
|
|
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
|
|
|
final NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
|
|
|
|
|
|
|
|
final int interruptionFilter;
|
|
|
|
if (actionDndOff.equals(action)) {
|
|
|
|
interruptionFilter = NotificationManager.INTERRUPTION_FILTER_ALL;
|
|
|
|
} else if (actionDndpriority.equals(action)) {
|
|
|
|
interruptionFilter = NotificationManager.INTERRUPTION_FILTER_PRIORITY;
|
|
|
|
} else if (actionDndAlarms.equals(action)) {
|
|
|
|
interruptionFilter = NotificationManager.INTERRUPTION_FILTER_ALARMS;
|
|
|
|
} else if (actionDndOn.equals(action)) {
|
|
|
|
interruptionFilter = NotificationManager.INTERRUPTION_FILTER_NONE;
|
|
|
|
} else {
|
|
|
|
interruptionFilter = NotificationManager.INTERRUPTION_FILTER_UNKNOWN;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (interruptionFilter != NotificationManager.INTERRUPTION_FILTER_UNKNOWN) {
|
|
|
|
LOG.debug("Setting do not disturb to {} for {}", interruptionFilter, action);
|
|
|
|
|
|
|
|
if (!notificationManager.isNotificationPolicyAccessGranted()) {
|
|
|
|
LOG.warn("Do not disturb permissions not granted");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
notificationManager.setInterruptionFilter(interruptionFilter);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-12-07 01:50:14 +01:00
|
|
|
LOG.warn("Unhandled device state change action (action: {}, message: {})", action, message);
|
|
|
|
}
|
|
|
|
|
|
|
|
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 actionDisabled = getContext().getString(R.string.pref_button_action_disabled_value);
|
|
|
|
String actionPreferenceKey, messagePreferenceKey;
|
|
|
|
int defaultBroadcastMessageResource;
|
|
|
|
|
|
|
|
switch (event.sleepState) {
|
|
|
|
case AWAKE:
|
|
|
|
actionPreferenceKey = DeviceSettingsPreferenceConst.PREF_DEVICE_ACTION_WOKE_UP_SELECTION;
|
|
|
|
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_SELECTION;
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
String action = getDevicePrefs().getString(actionPreferenceKey, actionDisabled);
|
|
|
|
|
|
|
|
if (actionDisabled.equals(action)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
String broadcastMessage = getDevicePrefs().getString(messagePreferenceKey, context.getString(defaultBroadcastMessageResource));
|
|
|
|
handleDeviceAction(action, 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");
|
|
|
|
}
|
|
|
|
|
|
|
|
String valueDisabled = getContext().getString(R.string.pref_button_action_disabled_value);
|
|
|
|
String actionOnUnwear = getDevicePrefs().getString(
|
|
|
|
DeviceSettingsPreferenceConst.PREF_DEVICE_ACTION_START_NON_WEAR_SELECTION,
|
|
|
|
valueDisabled
|
|
|
|
);
|
|
|
|
|
|
|
|
// check if an action is set
|
|
|
|
if (actionOnUnwear.equals(valueDisabled)) {
|
|
|
|
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);
|
|
|
|
}
|
2021-03-05 07:49:19 +01:00
|
|
|
|
|
|
|
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);
|
2021-10-16 22:40:30 +02:00
|
|
|
batteryLevel.setBatteryIndex(deviceEvent.batteryIndex);
|
2021-03-05 07:49:19 +01:00
|
|
|
batteryLevel.setDevice(device);
|
|
|
|
batteryLevel.setLevel(deviceEvent.level);
|
|
|
|
handler.getDaoSession().getBatteryLevelDao().insert(batteryLevel);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-04-03 00:50:45 +02:00
|
|
|
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);
|
|
|
|
}
|
2019-09-14 00:05:39 +02:00
|
|
|
|
2023-10-06 10:32:22 +02:00
|
|
|
protected Prefs getDevicePrefs() {
|
|
|
|
return new Prefs(GBApplication.getDeviceSpecificSharedPrefs(gbDevice.getAddress()));
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2019-09-14 00:05:39 +02:00
|
|
|
public String customStringFilter(String inputString) {
|
|
|
|
return inputString;
|
|
|
|
}
|
2023-01-05 12:36:11 +01:00
|
|
|
|
|
|
|
|
|
|
|
// Empty functions following, leaving optional implementation up to child classes
|
|
|
|
|
|
|
|
/**
|
|
|
|
* If the device supports a "find phone" functionality, this method can
|
|
|
|
* be overridden and implemented by the device support class.
|
|
|
|
* @param start true if starting the search, false if stopping
|
|
|
|
*/
|
|
|
|
@Override
|
|
|
|
public void onFindPhone(boolean start) {
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* If the device supports a "find device" functionality, this method can
|
|
|
|
* be overridden and implemented by the device support class.
|
|
|
|
* @param start true if starting the search, false if stopping
|
|
|
|
*/
|
|
|
|
@Override
|
|
|
|
public void onFindDevice(boolean start) {
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* If the device supports a "set FM frequency" functionality, this method
|
|
|
|
* can be overridden and implemented by the device support class.
|
|
|
|
* @param frequency the FM frequency to set
|
|
|
|
*/
|
|
|
|
@Override
|
|
|
|
public void onSetFmFrequency(float frequency) {
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* If the device supports a "set LED color" functionality, this method
|
|
|
|
* can be overridden and implemented by the device support class.
|
|
|
|
* @param color the new color, in ARGB, with alpha = 255
|
|
|
|
*/
|
|
|
|
@Override
|
|
|
|
public void onSetLedColor(int color) {
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* If the device can be turned off by sending a command, this method
|
|
|
|
* can be overridden and implemented by the device support class.
|
|
|
|
*/
|
|
|
|
@Override
|
|
|
|
public void onPowerOff() {
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* If the device has a functionality to set the phone volume, this method
|
|
|
|
* can be overridden and implemented by the device support class.
|
|
|
|
* @param volume the volume percentage (0 to 100).
|
|
|
|
*/
|
|
|
|
@Override
|
|
|
|
public void onSetPhoneVolume(final float volume) {
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* If the device can receive the GPS location from the phone, this method
|
|
|
|
* can be overridden and implemented by the device support class.
|
|
|
|
* @param location {@link android.location.Location} object containing the current GPS coordinates
|
|
|
|
*/
|
|
|
|
@Override
|
|
|
|
public void onSetGpsLocation(Location location) {
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* If reminders can be set on the device, this method can be
|
|
|
|
* overridden and implemented by the device support class.
|
|
|
|
* @param reminders {@link java.util.ArrayList} containing {@link nodomain.freeyourgadget.gadgetbridge.model.Reminder} instances
|
|
|
|
*/
|
|
|
|
@Override
|
|
|
|
public void onSetReminders(ArrayList<? extends Reminder> reminders) {
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2023-07-04 00:19:19 +02:00
|
|
|
/**
|
|
|
|
* If loyalty cards can be set on the device, this method can be
|
|
|
|
* overridden and implemented by the device support class.
|
|
|
|
* @param cards {@link java.util.ArrayList} containing {@link LoyaltyCard} instances
|
|
|
|
*/
|
|
|
|
@Override
|
|
|
|
public void onSetLoyaltyCards(ArrayList<LoyaltyCard> cards) {
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2023-01-05 12:36:11 +01:00
|
|
|
/**
|
|
|
|
* If world clocks can be configured on the device, this method can be
|
|
|
|
* overridden and implemented by the device support class.
|
|
|
|
* @param clocks {@link java.util.ArrayList} containing {@link nodomain.freeyourgadget.gadgetbridge.model.WorldClock} instances
|
|
|
|
*/
|
|
|
|
@Override
|
|
|
|
public void onSetWorldClocks(ArrayList<? extends WorldClock> clocks) {
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2023-05-18 00:43:29 +02:00
|
|
|
/**
|
|
|
|
* If contacts can be configured on the device, this method can be
|
|
|
|
* overridden and implemented by the device support class.
|
|
|
|
* @param contacts {@link java.util.ArrayList} containing {@link nodomain.freeyourgadget.gadgetbridge.model.Contact} instances
|
|
|
|
*/
|
|
|
|
@Override
|
|
|
|
public void onSetContacts(ArrayList<? extends Contact> contacts) {
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2023-01-05 12:36:11 +01:00
|
|
|
/**
|
|
|
|
* If the device can receive and display notifications, this method
|
|
|
|
* can be overridden and implemented by the device support class.
|
|
|
|
* @param notificationSpec notification details
|
|
|
|
*/
|
|
|
|
@Override
|
|
|
|
public void onNotification(NotificationSpec notificationSpec) {
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* If notifications can be deleted from the device, this method can be
|
|
|
|
* overridden and implemented by the device support class.
|
|
|
|
* @param id the unique notification identifier
|
|
|
|
*/
|
|
|
|
@Override
|
|
|
|
public void onDeleteNotification(int id) {
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* If the time can be set on the device, this method can be
|
|
|
|
* overridden and implemented by the device support class.
|
|
|
|
*/
|
|
|
|
@Override
|
|
|
|
public void onSetTime() {
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* If alarms can be set on the device, this method can be
|
|
|
|
* overridden and implemented by the device support class.
|
|
|
|
* @param alarms {@link java.util.ArrayList} containing {@link nodomain.freeyourgadget.gadgetbridge.model.Alarm} instances
|
|
|
|
*/
|
|
|
|
@Override
|
|
|
|
public void onSetAlarms(ArrayList<? extends Alarm> alarms) {
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* If the device can receive and show or handle phone call details, this
|
|
|
|
* method can be overridden and implemented by the device support class.
|
|
|
|
* @param callSpec the call state details
|
|
|
|
*/
|
|
|
|
@Override
|
|
|
|
public void onSetCallState(CallSpec callSpec) {
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* If the device has a "canned messages" functionality, this method
|
|
|
|
* can be overridden and implemented by the device support class.
|
|
|
|
* @param cannedMessagesSpec the canned messages to send to the device
|
|
|
|
*/
|
|
|
|
@Override
|
|
|
|
public void onSetCannedMessages(CannedMessagesSpec cannedMessagesSpec) {
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* If the music play state can be set on the device, this method
|
|
|
|
* can be overridden and implemented by the device support class.
|
|
|
|
* @param stateSpec the current state of music playback
|
|
|
|
*/
|
|
|
|
@Override
|
|
|
|
public void onSetMusicState(MusicStateSpec stateSpec) {
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* If the music information can be shown on the device, this method can be
|
|
|
|
* overridden and implemented by the device support class.
|
|
|
|
* @param musicSpec the current music information, like track name and artist
|
|
|
|
*/
|
|
|
|
@Override
|
|
|
|
public void onSetMusicInfo(MusicSpec musicSpec) {
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* If apps can be installed on the device, this method can be
|
|
|
|
* overridden and implemented by the device support class.
|
|
|
|
* @param uri reference to a watch app file
|
|
|
|
*/
|
|
|
|
@Override
|
|
|
|
public void onInstallApp(Uri uri) {
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* If the list of apps on the device can be retrieved, this method
|
|
|
|
* can be overridden and implemented by the device support class.
|
|
|
|
*/
|
|
|
|
@Override
|
|
|
|
public void onAppInfoReq() {
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* If the device supports starting an app with a command, this method
|
|
|
|
* can be overridden and implemented by the device support class.
|
|
|
|
* @param uuid the Gadgetbridge internal UUID of the app
|
|
|
|
* @param start true to start, false to stop the app (if supported)
|
|
|
|
*/
|
|
|
|
@Override
|
|
|
|
public void onAppStart(UUID uuid, boolean start) {
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2023-01-04 22:40:38 +01:00
|
|
|
/**
|
|
|
|
* If apps can be downloaded from the device, this method can be
|
|
|
|
* overridden and implemented by the device support class.
|
|
|
|
* @param uuid the Gadgetbridge internal UUID of the app
|
|
|
|
*/
|
|
|
|
@Override
|
|
|
|
public void onAppDownload(UUID uuid) {
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2023-01-05 12:36:11 +01:00
|
|
|
/**
|
|
|
|
* If apps on the device can be deleted with a command, this method
|
|
|
|
* can be overridden and implemented by the device support class.
|
|
|
|
* @param uuid the Gadgetbridge internal UUID of the app
|
|
|
|
*/
|
|
|
|
@Override
|
|
|
|
public void onAppDelete(UUID uuid) {
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* If apps on the device can be configured, this method can be
|
|
|
|
* overridden and implemented by the device support class.
|
|
|
|
* @param appUuid the Gadgetbridge internal UUID of the app
|
|
|
|
* @param config the configuration of the app
|
|
|
|
* @param id
|
|
|
|
*/
|
|
|
|
@Override
|
|
|
|
public void onAppConfiguration(UUID appUuid, String config, Integer id) {
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* If apps on the device can be reordered, this method can be
|
|
|
|
* overridden and implemented by the device support class.
|
|
|
|
* @param uuids array of Gadgetbridge internal UUIDs of the apps
|
|
|
|
*/
|
|
|
|
@Override
|
|
|
|
public void onAppReorder(UUID[] uuids) {
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* If recorded data can be fetched from the device, this method
|
|
|
|
* can be overridden and implemented by the device support class.
|
|
|
|
* @param dataTypes which data types to fetch
|
|
|
|
*/
|
|
|
|
@Override
|
|
|
|
public void onFetchRecordedData(int dataTypes) {
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* If a device can be reset with a command, this method can be
|
|
|
|
* overridden and implemented by the device support class.
|
|
|
|
* @param flags can be used to pass flags with the reset command
|
|
|
|
*/
|
|
|
|
@Override
|
|
|
|
public void onReset(int flags) {
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* If the device can perform a heart rate measurement on request, this
|
|
|
|
* method can be overridden and implemented by the device support class.
|
|
|
|
*/
|
|
|
|
@Override
|
|
|
|
public void onHeartRateTest() {
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* If the device has the functionality to enable/disable realtime heart rate measurement,
|
|
|
|
* this method can be overridden and implemented by the device support class.
|
|
|
|
* @param enable true to enable, false to disable realtime heart rate measurement
|
|
|
|
*/
|
|
|
|
@Override
|
|
|
|
public void onEnableRealtimeHeartRateMeasurement(boolean enable) {
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* If the device has the functionality to enable/disable realtime steps information,
|
|
|
|
* this method can be overridden and implemented by the device support class.
|
|
|
|
* @param enable true to enable, false to disable realtime steps
|
|
|
|
*/
|
|
|
|
@Override
|
|
|
|
public void onEnableRealtimeSteps(boolean enable) {
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* If the device has a functionality to enable constant vibration, this
|
|
|
|
* method can be overridden and implemented by the device support class.
|
|
|
|
* @param integer the vibration intensity
|
|
|
|
*/
|
|
|
|
@Override
|
|
|
|
public void onSetConstantVibration(int integer) {
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* If the device supports taking screenshots of the screen, this method can
|
|
|
|
* be overridden and implemented by the device support class.
|
|
|
|
*/
|
|
|
|
@Override
|
|
|
|
public void onScreenshotReq() {
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* If the device has a toggle to enable the use of heart rate for sleep detection,
|
|
|
|
* this method can be overridden and implemented by the device support class.
|
|
|
|
* @param enable true to enable, false to disable using heart rate for sleep detection
|
|
|
|
*/
|
|
|
|
@Override
|
|
|
|
public void onEnableHeartRateSleepSupport(boolean enable) {
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* If the heart rate measurement interval can be changed on the device,
|
|
|
|
* this method can be overridden and implemented by the device support class.
|
|
|
|
* @param seconds the interval to configure on the device
|
|
|
|
*/
|
|
|
|
@Override
|
|
|
|
public void onSetHeartRateMeasurementInterval(int seconds) {
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* If calendar events can be sent to the device, this method can be
|
|
|
|
* overridden and implemented by the device support class.
|
|
|
|
* @param calendarEventSpec calendar event details
|
|
|
|
*/
|
|
|
|
@Override
|
|
|
|
public void onAddCalendarEvent(CalendarEventSpec calendarEventSpec) {
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* If calendar events can be deleted from the device, this method can
|
|
|
|
* be overridden and implemented by the device support class.
|
|
|
|
* @param type type of calendar event
|
|
|
|
* @param id id of calendar event
|
|
|
|
*/
|
|
|
|
@Override
|
|
|
|
public void onDeleteCalendarEvent(byte type, long id) {
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* If configuration options can be set on the device, this method
|
|
|
|
* can be overridden and implemented by the device support class.
|
|
|
|
* @param config the device specific option to set on the device
|
|
|
|
*/
|
|
|
|
@Override
|
|
|
|
public void onSendConfiguration(String config) {
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* If the configuration can be retrieved from the device, this method
|
|
|
|
* can be overridden and implemented by the device support class.
|
|
|
|
* @param config the device specific option to get from the device
|
|
|
|
*/
|
|
|
|
@Override
|
|
|
|
public void onReadConfiguration(String config) {
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* If the device can receive weather information, this method can be
|
|
|
|
* overridden and implemented by the device support class.
|
|
|
|
* @param weatherSpec weather information
|
|
|
|
*/
|
|
|
|
@Override
|
|
|
|
public void onSendWeather(WeatherSpec weatherSpec) {
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* For testing new features, this method can be overridden and
|
|
|
|
* implemented by the device support class.
|
|
|
|
* It's called by clicking the "test new functionality" button
|
|
|
|
* in the Debug menu.
|
|
|
|
*/
|
|
|
|
@Override
|
|
|
|
public void onTestNewFunction() {
|
|
|
|
|
|
|
|
}
|
2021-10-20 22:37:23 +02:00
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onSetNavigationInfo(NavigationInfoSpec navigationInfoSpec) {
|
|
|
|
|
|
|
|
}
|
2015-04-14 01:24:03 +02:00
|
|
|
}
|