2021-01-10 23:37:09 +01:00
|
|
|
/* Copyright (C) 2015-2021 Andreas Böhler, Andreas Shimokawa, Carsten
|
|
|
|
Pfeiffer, Daniele Gobbetti, José Rebelo, Pauli Salmenrinne, Sebastian Kranz,
|
|
|
|
Taavi Eomäe
|
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;
|
2015-06-27 00:21:30 +02:00
|
|
|
import android.app.PendingIntent;
|
2015-04-14 01:24:03 +02:00
|
|
|
import android.bluetooth.BluetoothAdapter;
|
2023-01-05 12:36:11 +01:00
|
|
|
import android.bluetooth.BluetoothDevice;
|
|
|
|
import android.bluetooth.BluetoothGatt;
|
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;
|
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;
|
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;
|
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;
|
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;
|
|
|
|
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.WeatherSpec;
|
|
|
|
import nodomain.freeyourgadget.gadgetbridge.model.WorldClock;
|
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;
|
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
|
|
|
import static nodomain.freeyourgadget.gadgetbridge.util.GB.NOTIFICATION_CHANNEL_ID;
|
|
|
|
|
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);
|
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
|
|
|
|
|
|
|
PendingIntent pi = PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
|
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);
|
2020-10-06 21:00:42 +02:00
|
|
|
LOG.warn("CompanionDeviceManager associations were not found, can't start intent");
|
|
|
|
}
|
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;
|
|
|
|
}
|
2015-06-23 11:54:33 +02:00
|
|
|
gbDevice.setFirmwareVersion(infoEvent.fwVersion);
|
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();
|
2018-09-28 16:50:11 +02:00
|
|
|
LOG.info("Got event for LED Color: #" + Integer.toHexString(colorEvent.color).toUpperCase());
|
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) {
|
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/*");
|
2015-06-27 00:21:30 +02:00
|
|
|
|
|
|
|
PendingIntent pIntent = PendingIntent.getActivity(context, 0, intent, 0);
|
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
|
|
|
|
|
|
|
PendingIntent pendingShareIntent = PendingIntent.getActivity(context, 0, Intent.createChooser(shareIntent, "share screenshot"),
|
|
|
|
PendingIntent.FLAG_UPDATE_CURRENT);
|
|
|
|
|
2017-03-10 23:10:40 +01:00
|
|
|
NotificationCompat.Action action = new NotificationCompat.Action.Builder(android.R.drawable.ic_menu_share, "share", pendingShareIntent).build();
|
|
|
|
|
2018-02-14 21:27:24 +01:00
|
|
|
Notification notif = new NotificationCompat.Builder(context, NOTIFICATION_CHANNEL_ID)
|
2015-06-26 23:17:31 +02:00
|
|
|
.setContentTitle("Screenshot taken")
|
|
|
|
.setTicker("Screenshot taken")
|
|
|
|
.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)) {
|
|
|
|
GB.updateBatteryNotification(context.getString(R.string.notif_battery_low, gbDevice.getName()),
|
|
|
|
deviceEvent.extendedInfoAvailable() ?
|
|
|
|
context.getString(R.string.notif_battery_low_extended, gbDevice.getName(),
|
|
|
|
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))
|
|
|
|
) {
|
|
|
|
GB.updateBatteryNotification(context.getString(R.string.notif_battery_low_percent, gbDevice.getName(), String.valueOf(deviceEvent.level)),
|
|
|
|
deviceEvent.extendedInfoAvailable() ?
|
|
|
|
context.getString(R.string.notif_battery_low_percent, gbDevice.getName(), 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 {
|
|
|
|
GB.removeBatteryNotification(context);
|
|
|
|
}
|
2015-08-18 17:37:51 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
gbDevice.sendDeviceUpdateIntent(context);
|
|
|
|
}
|
|
|
|
|
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
|
|
|
|
|
|
|
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) {
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* 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) {
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* 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) {
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* 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() {
|
|
|
|
|
|
|
|
}
|
2015-04-14 01:24:03 +02:00
|
|
|
}
|