diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 49ae1174..4c43d314 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -388,7 +388,10 @@
android:name=".activities.VibrationActivity"
android:label="@string/title_activity_vibration"
android:parentActivityName=".activities.ControlCenterv2" />
-
+
. */
+
+package nodomain.freeyourgadget.gadgetbridge.activities;
+
+import android.os.Bundle;
+import android.widget.SeekBar;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.UUID;
+
+import nodomain.freeyourgadget.gadgetbridge.GBApplication;
+import nodomain.freeyourgadget.gadgetbridge.R;
+import nodomain.freeyourgadget.gadgetbridge.devices.here.HereConstants;
+import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
+import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder;
+
+
+public class AudioActivity extends AbstractGBActivity {
+ private static final Logger LOG = LoggerFactory.getLogger(AudioActivity.class);
+ private SeekBar seekBar;
+ private int volume;
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.audio_settings);
+ LOG.info("Create");
+
+ seekBar = (SeekBar) findViewById(R.id.volume_seekbar);
+ seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
+ @Override
+ public void onProgressChanged(SeekBar seekBar, int position, boolean fromUser) {
+ // HERE's volume range is from 0xe3 (-22dB on their app) to 0xff (+6dB)
+ // 0xff - 0xe3 = 28 -> seekbar max value
+ // volume = seekbar + Min_volume (= 0xe3 = 227)
+ volume = position + 227;
+ LOG.debug("Volume = " + (byte)volume + " = " + volume + "= " + position);
+ GBApplication.deviceService().onSetAudioProperty(0, volume);
+ }
+
+ @Override
+ public void onStartTrackingTouch(SeekBar seekBar) {
+
+ }
+
+ @Override
+ public void onStopTrackingTouch(SeekBar seekBar) {
+ }
+ });
+ }
+}
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/adapter/GBDeviceAdapterv2.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/adapter/GBDeviceAdapterv2.java
index b8f6373c..26dafe35 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/adapter/GBDeviceAdapterv2.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/adapter/GBDeviceAdapterv2.java
@@ -5,17 +5,17 @@
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.
+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.
+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 . */
-package nodomain.freeyourgadget.gadgetbridge.adapter;
+You should have received a copy of the GNU Affero General Public License
+along with this program. If not, see . */
+ package nodomain.freeyourgadget.gadgetbridge.adapter;
import android.app.Activity;
import android.app.AlertDialog;
@@ -42,10 +42,12 @@ import android.widget.Toast;
import java.util.List;
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
+import nodomain.freeyourgadget.gadgetbridge.GBEnvironment;
import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.activities.ConfigureAlarms;
import nodomain.freeyourgadget.gadgetbridge.activities.VibrationActivity;
import nodomain.freeyourgadget.gadgetbridge.activities.charts.ChartsActivity;
+import nodomain.freeyourgadget.gadgetbridge.activities.AudioActivity;
import nodomain.freeyourgadget.gadgetbridge.devices.DeviceCoordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.DeviceManager;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
@@ -84,27 +86,27 @@ public class GBDeviceAdapterv2 extends RecyclerView.Adapter appsManagementActivity = coordinator.getAppsManagementActivity();
- if (appsManagementActivity != null) {
- Intent startIntent = new Intent(context, appsManagementActivity);
- startIntent.putExtra(GBDevice.EXTRA_DEVICE, device);
- context.startActivity(startIntent);
- }
- }
- }
- );
+ {
+ @Override
+ public void onClick(View v) {
+ DeviceCoordinator coordinator = DeviceHelper.getInstance().getCoordinator(device);
+ Class extends Activity> appsManagementActivity = coordinator.getAppsManagementActivity();
+ if (appsManagementActivity != null) {
+ Intent startIntent = new Intent(context, appsManagementActivity);
+ startIntent.putExtra(GBDevice.EXTRA_DEVICE, device);
+ context.startActivity(startIntent);
+ }
+ }
+ }
+ );
//set alarms
holder.setAlarmsView.setVisibility(coordinator.supportsAlarmConfiguration() ? View.VISIBLE : View.GONE);
holder.setAlarmsView.setOnClickListener(new View.OnClickListener()
- {
- @Override
- public void onClick(View v) {
- Intent startIntent;
- startIntent = new Intent(context, ConfigureAlarms.class);
- startIntent.putExtra(GBDevice.EXTRA_DEVICE, device);
- context.startActivity(startIntent);
- }
- }
- );
+ {
+ @Override
+ public void onClick(View v) {
+ Intent startIntent;
+ startIntent = new Intent(context, ConfigureAlarms.class);
+ startIntent.putExtra(GBDevice.EXTRA_DEVICE, device);
+ context.startActivity(startIntent);
+ }
+ }
+ );
//show graphs
holder.showActivityGraphs.setVisibility(coordinator.supportsActivityTracking() ? View.VISIBLE : View.GONE);
holder.showActivityGraphs.setOnClickListener(new View.OnClickListener()
- {
- @Override
- public void onClick(View v) {
- Intent startIntent;
- startIntent = new Intent(context, ChartsActivity.class);
- startIntent.putExtra(GBDevice.EXTRA_DEVICE, device);
- context.startActivity(startIntent);
- }
- }
- );
+ {
+ @Override
+ public void onClick(View v) {
+ Intent startIntent;
+ startIntent = new Intent(context, ChartsActivity.class);
+ startIntent.putExtra(GBDevice.EXTRA_DEVICE, device);
+ context.startActivity(startIntent);
+ }
+ }
+ );
+
+
+ // audio settings
+ holder.showAudioSettings.setVisibility(device.isInitialized() && coordinator.supportsAudioSettings() ? View.VISIBLE : View.GONE);
+ holder.showAudioSettings.setOnClickListener(new View.OnClickListener()
+ {
+ @Override
+ public void onClick(View v) {
+ showTransientSnackbar(R.string.controlcenter_snackbar_requested_screenshot);
+ Intent startIntent;
+ startIntent = new Intent(context, AudioActivity.class);
+ startIntent.putExtra(GBDevice.EXTRA_DEVICE, device);
+ context.startActivity(startIntent);
+ }
+ }
+ );
ItemWithDetailsAdapter infoAdapter = new ItemWithDetailsAdapter(context, device.getDeviceInfos());
infoAdapter.setHorizontalAlignment(true);
@@ -222,95 +240,96 @@ public class GBDeviceAdapterv2 extends RecyclerView.Adapter. */
+package nodomain.freeyourgadget.gadgetbridge.devices.here;
+
+import android.app.Activity;
+import android.content.Context;
+import android.net.Uri;
+import android.support.annotation.NonNull;
+
+import nodomain.freeyourgadget.gadgetbridge.GBException;
+import nodomain.freeyourgadget.gadgetbridge.R;
+import nodomain.freeyourgadget.gadgetbridge.activities.AudioActivity;
+import nodomain.freeyourgadget.gadgetbridge.devices.AbstractDeviceCoordinator;
+import nodomain.freeyourgadget.gadgetbridge.devices.InstallHandler;
+import nodomain.freeyourgadget.gadgetbridge.devices.SampleProvider;
+import nodomain.freeyourgadget.gadgetbridge.entities.DaoSession;
+import nodomain.freeyourgadget.gadgetbridge.entities.Device;
+import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
+import nodomain.freeyourgadget.gadgetbridge.impl.GBDeviceCandidate;
+import nodomain.freeyourgadget.gadgetbridge.model.ActivitySample;
+import nodomain.freeyourgadget.gadgetbridge.model.DeviceType;
+
+import java.util.regex.Pattern; // Regex match name
+import java.util.regex.Matcher; // Regex match name
+
+public class HereCoordinator extends AbstractDeviceCoordinator {
+ @Override
+ public DeviceType getSupportedType(GBDeviceCandidate candidate) {
+ String name = candidate.getDevice().getName();
+ Pattern pat = Pattern.compile("H([LR])[A-F0-9]+|HERE-([LR])-[A-F0-9]+");
+ Matcher mat = pat.matcher(name);
+ // Identify if device is Left or Right
+ if (mat.matches()) {
+ // get device type (L or R)
+ // disabled until we find differences we need to handle
+ // if (mat.group(1).equals("L")) {
+ // return DeviceType.HEREL;
+ // } else if (mat.group(1).equals("R")) {
+ // return DeviceType.HERER;
+ // } else {
+ // Could not detect if L or R
+ return DeviceType.HERE;
+ // }
+ }
+ return DeviceType.UNKNOWN;
+ }
+
+ @Override
+ public DeviceType getDeviceType() {
+ return DeviceType.HERE;
+ }
+
+ @Override
+ public Class extends Activity> getPairingActivity() {
+ return null;
+ }
+
+ @Override
+ public Class extends Activity> getPrimaryActivity() {
+ return AudioActivity.class;
+ }
+
+ @Override
+ public InstallHandler findInstallHandler(Uri uri, Context context) {
+ return null;
+ }
+
+ @Override
+ public boolean supportsActivityDataFetching() {
+ return false;
+ }
+
+ @Override
+ public boolean supportsActivityTracking() {
+ return false;
+ }
+
+ @Override
+ public boolean supportsAudioSettings() {
+ return true;
+ }
+
+ @Override
+ public SampleProvider extends ActivitySample> getSampleProvider(GBDevice device, DaoSession session) {
+ return null;
+ }
+
+ @Override
+ public boolean supportsScreenshots() {
+ return false;
+ }
+
+ @Override
+ public boolean supportsAlarmConfiguration() {
+ return false;
+ }
+
+ @Override
+ public boolean supportsSmartWakeup(GBDevice device) {
+ return false;
+ }
+
+ @Override
+ public boolean supportsHeartRateMeasurement(GBDevice device) {
+ return false;
+ }
+
+ @Override
+ public String getManufacturer() {
+ return "Doppler Labs";
+ }
+
+ @Override
+ public boolean supportsAppsManagement() {
+ return false;
+ }
+
+ @Override
+ public Class extends Activity> getAppsManagementActivity() {
+ return null;
+ }
+
+ @Override
+ public boolean supportsCalendarEvents() {
+ return false;
+ }
+
+ @Override
+ public boolean supportsRealtimeData() {
+ return false; // hmmm well, it has a temperature sensor :D
+ }
+
+ @Override
+ protected void deleteDevice(@NonNull GBDevice gbDevice, @NonNull Device device, @NonNull DaoSession session) throws GBException {
+ // nothing to delete, yet
+ }
+}
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/hplus/HPlusCoordinator.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/hplus/HPlusCoordinator.java
index 5093e878..055c5800 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/hplus/HPlusCoordinator.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/hplus/HPlusCoordinator.java
@@ -128,6 +128,11 @@ public class HPlusCoordinator extends AbstractDeviceCoordinator {
return true;
}
+ @Override
+ public boolean supportsAudioSettings() {
+ return false;
+ }
+
@Override
public SampleProvider extends ActivitySample> getSampleProvider(GBDevice device, DaoSession session) {
return new HPlusHealthSampleProvider(device, session);
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/jyou/TeclastH30Coordinator.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/jyou/TeclastH30Coordinator.java
index 993f425e..924a1641 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/jyou/TeclastH30Coordinator.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/jyou/TeclastH30Coordinator.java
@@ -114,6 +114,11 @@ public class TeclastH30Coordinator extends AbstractDeviceCoordinator {
return false;
}
+ @Override
+ public boolean supportsAudioSettings() {
+ return false;
+ }
+
@Override
public SampleProvider extends ActivitySample> getSampleProvider(GBDevice device, DaoSession session) {
return null;
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/liveview/LiveviewCoordinator.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/liveview/LiveviewCoordinator.java
index 3aa5aeb1..16f192bc 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/liveview/LiveviewCoordinator.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/liveview/LiveviewCoordinator.java
@@ -74,6 +74,11 @@ public class LiveviewCoordinator extends AbstractDeviceCoordinator {
return false;
}
+ @Override
+ public boolean supportsAudioSettings() {
+ return false;
+ }
+
@Override
public SampleProvider extends ActivitySample> getSampleProvider(GBDevice device, DaoSession session) {
return null;
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/miband/MiBandCoordinator.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/miband/MiBandCoordinator.java
index f982f484..0141a47f 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/miband/MiBandCoordinator.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/miband/MiBandCoordinator.java
@@ -151,6 +151,11 @@ public class MiBandCoordinator extends AbstractDeviceCoordinator {
return true;
}
+ @Override
+ public boolean supportsAudioSettings() {
+ return false;
+ }
+
@Override
public String getManufacturer() {
return "Xiaomi";
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/no1f1/No1F1Coordinator.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/no1f1/No1F1Coordinator.java
index 004715f8..87bd166b 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/no1f1/No1F1Coordinator.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/no1f1/No1F1Coordinator.java
@@ -98,6 +98,11 @@ public class No1F1Coordinator extends AbstractDeviceCoordinator {
return true;
}
+ @Override
+ public boolean supportsAudioSettings() {
+ return false;
+ }
+
@Override
public SampleProvider extends ActivitySample> getSampleProvider(GBDevice device, DaoSession session) {
return new No1F1SampleProvider(device, session);
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/pebble/PebbleCoordinator.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/pebble/PebbleCoordinator.java
index d6010c48..920c4bfe 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/pebble/PebbleCoordinator.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/pebble/PebbleCoordinator.java
@@ -117,6 +117,11 @@ public class PebbleCoordinator extends AbstractDeviceCoordinator {
return true;
}
+ @Override
+ public boolean supportsAudioSettings() {
+ return false;
+ }
+
@Override
public boolean supportsScreenshots() {
return true;
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/vibratissimo/VibratissimoCoordinator.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/vibratissimo/VibratissimoCoordinator.java
index aeeb6249..844ef5f1 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/vibratissimo/VibratissimoCoordinator.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/vibratissimo/VibratissimoCoordinator.java
@@ -75,6 +75,11 @@ public class VibratissimoCoordinator extends AbstractDeviceCoordinator {
return false;
}
+ @Override
+ public boolean supportsAudioSettings() {
+ return false;
+ }
+
@Override
public SampleProvider extends ActivitySample> getSampleProvider(GBDevice device, DaoSession session) {
return null;
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/impl/GBDeviceService.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/impl/GBDeviceService.java
index fff316d9..7229b215 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/impl/GBDeviceService.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/impl/GBDeviceService.java
@@ -24,6 +24,9 @@ import android.database.Cursor;
import android.net.Uri;
import android.provider.ContactsContract;
import android.support.annotation.Nullable;
+// FIXME: REMOVE
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.UUID;
@@ -46,6 +49,9 @@ import static nodomain.freeyourgadget.gadgetbridge.util.JavaExtensions.coalesce;
public class GBDeviceService implements DeviceService {
protected final Context mContext;
+ // FIXME: REMOVE
+ private static final Logger LOG = LoggerFactory.getLogger(DeviceCommunicationService.class);
+
private final Class extends Service> mServiceClass;
private final String[] transliterationExtras = new String[]{
EXTRA_NOTIFICATION_PHONENUMBER,
@@ -298,6 +304,14 @@ public class GBDeviceService implements DeviceService {
invokeService(intent);
}
+ @Override
+ public void onSetAudioProperty(int property, int intensity) {
+ // volume = 0
+ Intent intent = createIntent().setAction(ACTION_SET_AUDIO_PROPERTY)
+ .putExtra(EXTRA_AUDIO_PROPERTY, intensity);
+ invokeService(intent);
+ }
+
@Override
public void onScreenshotReq() {
Intent intent = createIntent().setAction(ACTION_REQUEST_SCREENSHOT);
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/DeviceService.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/DeviceService.java
index 2e2a1a6a..19524e3f 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/DeviceService.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/DeviceService.java
@@ -53,6 +53,7 @@ public interface DeviceService extends EventHandler {
String ACTION_DISCONNECT = PREFIX + ".action.disconnect";
String ACTION_FIND_DEVICE = PREFIX + ".action.find_device";
String ACTION_SET_CONSTANT_VIBRATION = PREFIX + ".action.set_constant_vibration";
+ String ACTION_SET_AUDIO_PROPERTY = PREFIX + ".action.set_audio_property";
String ACTION_SET_ALARMS = PREFIX + ".action.set_alarms";
String ACTION_ENABLE_REALTIME_STEPS = PREFIX + ".action.enable_realtime_steps";
String ACTION_REALTIME_SAMPLES = PREFIX + ".action.realtime_samples";
@@ -76,6 +77,7 @@ public interface DeviceService extends EventHandler {
String EXTRA_NOTIFICATION_PEBBLE_COLOR = "notification_pebble_color";
String EXTRA_FIND_START = "find_start";
String EXTRA_VIBRATION_INTENSITY = "vibration_intensity";
+ String EXTRA_AUDIO_PROPERTY = "audio_property";
String EXTRA_CALL_COMMAND = "call_command";
String EXTRA_CALL_PHONENUMBER = "call_phonenumber";
String EXTRA_CALL_DISPLAYNAME = "call_displayname";
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/DeviceType.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/DeviceType.java
index eca9e169..b5b412a5 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/DeviceType.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/DeviceType.java
@@ -40,6 +40,11 @@ public enum DeviceType {
EXRIZUK8(42, R.drawable.ic_device_hplus, R.drawable.ic_device_hplus_disabled),
NO1F1(50, R.drawable.ic_device_hplus, R.drawable.ic_device_hplus_disabled),
TECLASTH30(60, R.drawable.ic_device_h30_h10, R.drawable.ic_device_h30_h10_disabled),
+ // Single device made of L + R (71, 71)
+ // but each earbut can be controlled independently
+ HERE(70, R.drawable.ic_device_default, R.drawable.ic_device_default_disabled),
+ // HERER(71, R.drawable.ic_device_here, R.drawable.ic_device_here_disabled),
+ // HEREL(72, R.drawable.ic_device_here, R.drawable.ic_device_here_disabled),
TEST(1000, R.drawable.ic_device_default, R.drawable.ic_device_default_disabled);
private final int key;
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/DeviceCommunicationService.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/DeviceCommunicationService.java
index e6f84268..4c0750b3 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/DeviceCommunicationService.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/DeviceCommunicationService.java
@@ -100,10 +100,12 @@ import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.ACTION_SE
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.ACTION_SETTIME;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.ACTION_SET_ALARMS;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.ACTION_SET_CONSTANT_VIBRATION;
+import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.ACTION_SET_AUDIO_PROPERTY;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.ACTION_START;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.ACTION_STARTAPP;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.ACTION_TEST_NEW_FUNCTION;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_ALARMS;
+import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_AUDIO_PROPERTY;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_APP_CONFIG;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_APP_START;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_APP_UUID;
@@ -123,6 +125,7 @@ import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_CAN
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_CONFIG;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_CONNECT_FIRST_TIME;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_FIND_START;
+
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_MUSIC_ALBUM;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_MUSIC_ARTIST;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_MUSIC_DURATION;
@@ -426,6 +429,12 @@ public class DeviceCommunicationService extends Service implements SharedPrefere
mDeviceSupport.onSetConstantVibration(intensity);
break;
}
+ case ACTION_SET_AUDIO_PROPERTY: {
+ LOG.info(mDeviceSupport.getDevice().toString());
+ int volume = intent.getIntExtra(EXTRA_AUDIO_PROPERTY, 0);
+ mDeviceSupport.onSetAudioProperty(0, volume);
+ break;
+ }
case ACTION_CALLSTATE:
CallSpec callSpec = new CallSpec();
callSpec.command = intent.getIntExtra(EXTRA_CALL_COMMAND, CallSpec.CALL_UNDEFINED);
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/DeviceSupportFactory.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/DeviceSupportFactory.java
index 07b1f3b1..affecfea 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/DeviceSupportFactory.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/DeviceSupportFactory.java
@@ -38,10 +38,18 @@ import nodomain.freeyourgadget.gadgetbridge.service.devices.pebble.PebbleSupport
import nodomain.freeyourgadget.gadgetbridge.service.devices.vibratissimo.VibratissimoSupport;
import nodomain.freeyourgadget.gadgetbridge.service.devices.hplus.HPlusSupport;
import nodomain.freeyourgadget.gadgetbridge.service.devices.jyou.TeclastH30Support;
+import nodomain.freeyourgadget.gadgetbridge.service.devices.here.HereSupport;
import nodomain.freeyourgadget.gadgetbridge.util.GB;
+// delte both
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
public class DeviceSupportFactory {
+ // delete the following
+ private static final Logger LOG = LoggerFactory.getLogger(DeviceCommunicationService.class);
private final BluetoothAdapter mBtAdapter;
+
private final Context mContext;
public DeviceSupportFactory(Context context) {
@@ -134,6 +142,11 @@ public class DeviceSupportFactory {
case NO1F1:
deviceSupport = new ServiceDeviceSupport(new No1F1Support(), EnumSet.of(ServiceDeviceSupport.Flags.BUSY_CHECKING));
break;
+ case HERE:
+ // case HERER:
+ // case HEREL:
+ deviceSupport = new ServiceDeviceSupport(new HereSupport(), EnumSet.of(ServiceDeviceSupport.Flags.BUSY_CHECKING));
+ break;
case TECLASTH30:
deviceSupport = new ServiceDeviceSupport(new TeclastH30Support(), EnumSet.of(ServiceDeviceSupport.Flags.BUSY_CHECKING));
break;
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/ServiceDeviceSupport.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/ServiceDeviceSupport.java
index 26b01e20..281c71cd 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/ServiceDeviceSupport.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/ServiceDeviceSupport.java
@@ -152,6 +152,11 @@ public class ServiceDeviceSupport implements DeviceSupport {
delegate.onNotification(notificationSpec);
}
+ @Override
+ public void onSetAudioProperty(int property, int intensity) {
+ delegate.onSetAudioProperty(property, intensity);
+ }
+
@Override
public void onDeleteNotification(int id) {
delegate.onDeleteNotification(id);
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/here/HereSupport.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/here/HereSupport.java
new file mode 100644
index 00000000..bccc466b
--- /dev/null
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/here/HereSupport.java
@@ -0,0 +1,512 @@
+/* Copyright (C) 2017 Niclò Balzarotti
+
+ 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 . */
+package nodomain.freeyourgadget.gadgetbridge.service.devices.here;
+
+import android.bluetooth.BluetoothGatt;
+import android.bluetooth.BluetoothGattCharacteristic;
+
+import static nodomain.freeyourgadget.gadgetbridge.service.btle.AbstractBTLEDeviceSupport.BASE_UUID;
+
+import android.net.Uri;
+import android.widget.Toast;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.UUID;
+
+import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventBatteryInfo;
+import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventVersionInfo;
+import nodomain.freeyourgadget.gadgetbridge.devices.here.HereConstants;
+import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
+import nodomain.freeyourgadget.gadgetbridge.model.Alarm;
+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.WeatherSpec;
+import nodomain.freeyourgadget.gadgetbridge.service.btle.AbstractBTLEDeviceSupport;
+import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder;
+import nodomain.freeyourgadget.gadgetbridge.util.GB;
+import nodomain.freeyourgadget.gadgetbridge.util.StringUtils;
+
+public class HereSupport extends AbstractBTLEDeviceSupport {
+
+ private static final Logger LOG = LoggerFactory.getLogger(HereSupport.class);
+
+ public BluetoothGattCharacteristic batteryCharacteristic = null;
+ public BluetoothGattCharacteristic infoCharacteristic = null;
+ public BluetoothGattCharacteristic fwCharacteristic = null;
+ public BluetoothGattCharacteristic volumeCharacteristic = null;
+
+ private final GBDeviceEventVersionInfo versionCmd = new GBDeviceEventVersionInfo();
+ private final GBDeviceEventBatteryInfo batteryCmd = new GBDeviceEventBatteryInfo();
+
+ public HereSupport() {
+ super(LOG);
+ addSupportedService(HereConstants.UUID_BATTERY_VALUE);
+ addSupportedService(HereConstants.UUID_CHARACTERISTIC_INFO);
+ addSupportedService(HereConstants.UUID_AUDIO_SETTINGS);
+ }
+
+ @Override
+ protected TransactionBuilder initializeDevice(TransactionBuilder builder) {
+ LOG.info("Initializing");
+
+ gbDevice.setState(GBDevice.State.INITIALIZING);
+ gbDevice.sendDeviceUpdateIntent(getContext());
+
+ batteryCharacteristic = getCharacteristic(HereConstants.UUID_CHARACTERISTIC_BATTERY);
+ infoCharacteristic = getCharacteristic(HereConstants.UUID_CHARACTERISTIC_INFO);
+ fwCharacteristic = getCharacteristic(HereConstants.UUID_CHARACTERISTIC_INFO);
+ volumeCharacteristic = getCharacteristic(HereConstants.UUID_VOLUME);
+
+ builder.setGattCallback(this);
+ builder.notify(batteryCharacteristic, true);
+ builder.read(fwCharacteristic);
+ syncSettings(builder);
+
+ // fw = builder.read(infoCharacteristic);
+
+ gbDevice.setState(GBDevice.State.INITIALIZED);
+ gbDevice.sendDeviceUpdateIntent(getContext());
+
+ LOG.info("Initialization Done");
+
+ return builder;
+ }
+
+ @Override
+ public boolean onCharacteristicChanged(BluetoothGatt gatt,
+ BluetoothGattCharacteristic characteristic) {
+ super.onCharacteristicChanged(gatt, characteristic);
+
+ UUID characteristicUUID = characteristic.getUuid();
+
+ byte[] data = characteristic.getValue();
+ if (data.length == 0)
+ return true;
+
+ if (HereConstants.UUID_CHARACTERISTIC_BATTERY.equals(characteristicUUID)) {
+ LOG.info("Battery is: " + String.format("%s", data[0]));
+ batteryCmd.level = ((short) data[0]);
+ handleGBDeviceEvent(batteryCmd);
+ return true;
+ } else if (HereConstants.UUID_FW_VERSION.equals(characteristicUUID)) {
+ LOG.info("Device info: " + (short)data[0]);
+ LOG.info("Device info: " + data);
+
+ versionCmd.fwVersion = String.format("%s", data);
+ handleGBDeviceEvent(versionCmd);
+ } else {
+ return true;
+ }
+ return true;
+ }
+ private void syncDateAndTime(TransactionBuilder builder) {
+ // Calendar cal = Calendar.getInstance();
+ // String strYear = String.valueOf(cal.get(Calendar.YEAR));
+ // byte year1 = (byte)Integer.parseInt(strYear.substring(0, 2));
+ // byte year2 = (byte)Integer.parseInt(strYear.substring(2, 4));
+ // byte month = (byte)cal.get(Calendar.MONTH);
+ // byte day = (byte)cal.get(Calendar.DAY_OF_MONTH);
+ // byte hour = (byte)cal.get(Calendar.HOUR_OF_DAY);
+ // byte minute = (byte)cal.get(Calendar.MINUTE);
+ // byte second = (byte)cal.get(Calendar.SECOND);
+ // byte weekDay = (byte)cal.get(Calendar.DAY_OF_WEEK);
+
+ // builder.write(ctrlCharacteristic, commandWithChecksum(
+ // HereConstants.CMD_SET_DATE_AND_TIME,
+ // (year1 << 24) | (year2 << 16) | (month << 8) | day,
+ // (hour << 24) | (minute << 16) | (second << 8) | weekDay
+ // ));
+ }
+
+ private void syncSettings(TransactionBuilder builder) {
+ // syncDateAndTime(builder);
+
+ // // TODO: unhardcode and separate stuff
+ // builder.write(ctrlCharacteristic, commandWithChecksum(
+ // HereConstants.CMD_SET_HEARTRATE_WARNING_VALUE, 0, 152
+ // ));
+ // builder.write(ctrlCharacteristic, commandWithChecksum(
+ // HereConstants.CMD_SET_TARGET_STEPS, 0, 10000
+ // ));
+ // builder.write(ctrlCharacteristic, commandWithChecksum(
+ // HereConstants.CMD_GET_STEP_COUNT, 0, 0
+ // ));
+ // builder.write(ctrlCharacteristic, commandWithChecksum(
+ // HereConstants.CMD_GET_SLEEP_TIME, 0, 0
+ // ));
+ // builder.write(ctrlCharacteristic, commandWithChecksum(
+ // HereConstants.CMD_SET_NOON_TIME, 12 * 60 * 60, 14 * 60 * 60 // 12:00 - 14:00
+ // ));
+ // builder.write(ctrlCharacteristic, commandWithChecksum(
+ // HereConstants.CMD_SET_SLEEP_TIME, 21 * 60 * 60, 8 * 60 * 60 // 21:00 - 08:00
+ // ));
+ // builder.write(ctrlCharacteristic, commandWithChecksum(
+ // HereConstants.CMD_SET_INACTIVITY_WARNING_TIME, 0, 0
+ // ));
+
+ // // do not disturb and a couple more features
+ // byte dndStartHour = 22;
+ // byte dndStartMin = 0;
+ // byte dndEndHour = 8;
+ // byte dndEndMin = 0;
+ // boolean dndToggle = false;
+ // boolean vibrationToggle = true;
+ // boolean wakeOnRaiseToggle = true;
+ // builder.write(ctrlCharacteristic, commandWithChecksum(
+ // HereConstants.CMD_SET_DND_SETTINGS,
+ // (dndStartHour << 24) | (dndStartMin << 16) | (dndEndHour << 8) | dndEndMin,
+ // ((dndToggle ? 0 : 1) << 2) | ((vibrationToggle ? 1 : 0) << 1) | (wakeOnRaiseToggle ? 1 : 0)
+ // ));
+ }
+
+ private void showNotification(byte icon, String title, String message) {
+ // try {
+ // TransactionBuilder builder = performInitialized("ShowNotification");
+
+ // byte[] titleBytes = stringToUTF8Bytes(title, 16);
+ // byte[] messageBytes = stringToUTF8Bytes(message, 80);
+
+ // for (int i = 1; i <= 7; i++)
+ // {
+ // byte[] currentPacket = new byte[20];
+ // currentPacket[0] = HereConstants.CMD_ACTION_SHOW_NOTIFICATION;
+ // currentPacket[1] = 7;
+ // currentPacket[2] = (byte)i;
+ // switch(i) {
+ // case 1:
+ // currentPacket[4] = icon;
+ // break;
+ // case 2:
+ // if (titleBytes != null) {
+ // System.arraycopy(titleBytes, 0, currentPacket, 3, 6);
+ // System.arraycopy(titleBytes, 6, currentPacket, 10, 10);
+ // }
+ // break;
+ // default:
+ // if (messageBytes != null) {
+ // System.arraycopy(messageBytes, 16 * (i - 3), currentPacket, 3, 6);
+ // System.arraycopy(messageBytes, 6 + 16 * (i - 3), currentPacket, 10, 10);
+ // }
+ // break;
+ // }
+ // builder.write(ctrlCharacteristic, currentPacket);
+ // }
+ // performConnected(builder.getTransaction());
+ // } catch (IOException e) {
+ // LOG.warn(e.getMessage());
+ // }
+ }
+
+ @Override
+ public boolean useAutoConnect() {
+ return true;
+ }
+
+ @Override
+ public void onNotification(NotificationSpec notificationSpec) {
+ // String notificationTitle = StringUtils.getFirstOf(notificationSpec.sender, notificationSpec.title);
+ // byte icon;
+ // switch (notificationSpec.type) {
+ // case GENERIC_SMS:
+ // icon = HereConstants.ICON_SMS;
+ // break;
+ // case FACEBOOK:
+ // case FACEBOOK_MESSENGER:
+ // icon = HereConstants.ICON_FACEBOOK;
+ // break;
+ // case TWITTER:
+ // icon = HereConstants.ICON_TWITTER;
+ // break;
+ // case WHATSAPP:
+ // icon = HereConstants.ICON_WHATSAPP;
+ // break;
+ // default:
+ // icon = HereConstants.ICON_LINE;
+ // break;
+ // }
+ // showNotification(icon, notificationTitle, notificationSpec.body);
+ }
+
+ @Override
+ public void onDeleteNotification(int id) {
+
+ }
+
+ @Override
+ public void onSetAlarms(ArrayList extends Alarm> alarms) {
+ // try {
+ // TransactionBuilder builder = performInitialized("SetAlarms");
+
+ // for (int i = 0; i < alarms.size(); i++)
+ // {
+ // byte cmd;
+ // switch (i) {
+ // case 0:
+ // cmd = HereConstants.CMD_SET_ALARM_1;
+ // break;
+ // case 1:
+ // cmd = HereConstants.CMD_SET_ALARM_2;
+ // break;
+ // case 2:
+ // cmd = HereConstants.CMD_SET_ALARM_3;
+ // break;
+ // default:
+ // return;
+ // }
+ // Calendar cal = alarms.get(i).getAlarmCal();
+ // builder.write(ctrlCharacteristic, commandWithChecksum(
+ // cmd,
+ // alarms.get(i).isEnabled() ? cal.get(Calendar.HOUR_OF_DAY) : -1,
+ // alarms.get(i).isEnabled() ? cal.get(Calendar.MINUTE) : -1
+ // ));
+ // }
+ // performConnected(builder.getTransaction());
+ // GB.toast(getContext(), "Alarm settings applied - do note that the current device does not support day specification", Toast.LENGTH_LONG, GB.INFO);
+ // } catch(IOException e) {
+ // LOG.warn(e.getMessage());
+ // }
+ }
+
+ @Override
+ public void onSetTime() {
+ // try {
+ // TransactionBuilder builder = performInitialized("SetTime");
+ // syncDateAndTime(builder);
+ // performConnected(builder.getTransaction());
+ // } catch(IOException e) {
+ // LOG.warn(e.getMessage());
+ // }
+ }
+
+ @Override
+ public void onSetCallState(CallSpec callSpec) {
+ // switch (callSpec.command) {
+ // case CallSpec.CALL_INCOMING:
+ // showNotification(HereConstants.ICON_CALL, callSpec.name, callSpec.number);
+ // break;
+ // }
+ }
+
+ @Override
+ public void onSetCannedMessages(CannedMessagesSpec cannedMessagesSpec) {
+
+ }
+
+ @Override
+ public void onSetAudioProperty(int property, int volume) {
+ TransactionBuilder builder = new TransactionBuilder("volume");
+ LOG.info("setting audio");
+ switch (property) {
+ case 0: // volume
+ LOG.info("setting volume to "+volume);
+
+ builder.write(volumeCharacteristic, new byte[]{(byte) volume});
+ builder.queue(getQueue());
+ break;
+ }
+ }
+
+ @Override
+ public void onSetMusicState(MusicStateSpec stateSpec) {
+
+ }
+
+ @Override
+ public void onSetMusicInfo(MusicSpec musicSpec) {
+
+ }
+
+ @Override
+ public void onEnableRealtimeSteps(boolean enable) {
+ onEnableRealtimeHeartRateMeasurement(enable);
+ }
+
+ @Override
+ public void onInstallApp(Uri uri) {
+
+ }
+
+ @Override
+ public void onAppInfoReq() {
+
+ }
+
+ @Override
+ public void onAppStart(UUID uuid, boolean start) {
+
+ }
+
+ @Override
+ public void onAppDelete(UUID uuid) {
+
+ }
+
+ @Override
+ public void onAppConfiguration(UUID appUuid, String config) {
+
+ }
+
+ @Override
+ public void onAppReorder(UUID[] uuids) {
+
+ }
+
+ @Override
+ public void onFetchActivityData() {
+
+ }
+
+ @Override
+ public void onReboot() {
+ // try {
+ // TransactionBuilder builder = performInitialized("Reboot");
+ // builder.write(ctrlCharacteristic, commandWithChecksum(
+ // HereConstants.CMD_ACTION_REBOOT_DEVICE, 0, 0
+ // ));
+ // performConnected(builder.getTransaction());
+ // } catch(Exception e) {
+ // LOG.warn(e.getMessage());
+ // }
+ }
+
+ @Override
+ public void onHeartRateTest() {
+ // try {
+ // TransactionBuilder builder = performInitialized("HeartRateTest");
+ // builder.write(ctrlCharacteristic, commandWithChecksum(
+ // HereConstants.CMD_ACTION_HEARTRATE_SWITCH, 0, 1
+ // ));
+ // performConnected(builder.getTransaction());
+ // } catch(Exception e) {
+ // LOG.warn(e.getMessage());
+ // }
+ }
+
+ @Override
+ public void onEnableRealtimeHeartRateMeasurement(boolean enable) {
+ // // TODO: test
+ // try {
+ // TransactionBuilder builder = performInitialized("RealTimeHeartMeasurement");
+ // builder.write(ctrlCharacteristic, commandWithChecksum(
+ // HereConstants.CMD_SET_HEARTRATE_AUTO, 0, enable ? 1 : 0
+ // ));
+ // performConnected(builder.getTransaction());
+ // } catch(Exception e) {
+ // LOG.warn(e.getMessage());
+ // }
+ }
+
+ @Override
+ public void onFindDevice(boolean start) {
+ }
+
+ @Override
+ public void onSetConstantVibration(int integer) {
+
+ }
+
+ @Override
+ public void onScreenshotReq() {
+
+ }
+
+ @Override
+ public void onEnableHeartRateSleepSupport(boolean enable) {
+
+ }
+
+ @Override
+ public void onAddCalendarEvent(CalendarEventSpec calendarEventSpec) {
+
+ }
+
+ @Override
+ public void onDeleteCalendarEvent(byte type, long id) {
+
+ }
+
+ @Override
+ public void onSendConfiguration(String config) {
+
+ }
+
+ @Override
+ public void onTestNewFunction() {
+
+ }
+
+ @Override
+ public void onSendWeather(WeatherSpec weatherSpec) {
+
+ }
+
+ // private byte[] commandWithChecksum(byte cmd, int argSlot1, int argSlot2)
+ // {
+ // // ByteBuffer buf = ByteBuffer.allocate(10);
+ // // buf.put(cmd);
+ // // buf.putInt(argSlot1);
+ // // buf.putInt(argSlot2);
+
+ // // byte[] bytesToWrite = buf.array();
+
+ // // byte checksum = 0;
+ // // for (byte b : bytesToWrite) {
+ // // checksum += b;
+ // // }
+
+ // // bytesToWrite[9] = checksum;
+
+ // ByteBuffer buf = ByteBuffer.allocate(10);
+ // return buf;
+ // }
+
+ private byte[] stringToUTF8Bytes(String src, int byteCount) {
+ // try {
+ // if (src == null)
+ // return null;
+
+ // for (int i = src.length(); i > 0; i--) {
+ // String sub = src.substring(0, i);
+ // byte[] subUTF8 = sub.getBytes("UTF-8");
+
+ // if (subUTF8.length == byteCount) {
+ // return subUTF8;
+ // }
+
+ // if (subUTF8.length < byteCount) {
+ // byte[] largerSubUTF8 = new byte[byteCount];
+ // System.arraycopy(subUTF8, 0, largerSubUTF8, 0, subUTF8.length);
+ // return largerSubUTF8;
+ // }
+ // }
+ // } catch (UnsupportedEncodingException e) {
+ // LOG.warn(e.getMessage());
+ // }
+ return null;
+ }
+}
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/hplus/HPlusSupport.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/hplus/HPlusSupport.java
index dfb10868..5340b76b 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/hplus/HPlusSupport.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/hplus/HPlusSupport.java
@@ -431,6 +431,11 @@ public class HPlusSupport extends AbstractBTLEDeviceSupport {
}
+ @Override
+ public void onSetAudioProperty(int property, int volume) {
+
+ }
+
@Override
public void onSetTime() {
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/jyou/TeclastH30Support.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/jyou/TeclastH30Support.java
index d7482dd3..63fbb40f 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/jyou/TeclastH30Support.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/jyou/TeclastH30Support.java
@@ -316,6 +316,12 @@ public class TeclastH30Support extends AbstractBTLEDeviceSupport {
}
+ @Override
+ public void onSetAudioProperty(int property, int volume) {
+
+ }
+
+
@Override
public void onSetMusicState(MusicStateSpec stateSpec) {
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/liveview/LiveviewSupport.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/liveview/LiveviewSupport.java
index 5d6246b8..19d3739f 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/liveview/LiveviewSupport.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/liveview/LiveviewSupport.java
@@ -105,6 +105,10 @@ public class LiveviewSupport extends AbstractSerialDeviceSupport {
//nothing to do ATM
}
+ @Override
+ public void onSetAudioProperty(int property, int volume) {
+ }
+
@Override
public void onAddCalendarEvent(CalendarEventSpec calendarEventSpec) {
//nothing to do ATM
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband/MiBandSupport.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband/MiBandSupport.java
index 5b10ce04..e5175df2 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband/MiBandSupport.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband/MiBandSupport.java
@@ -452,6 +452,11 @@ public class MiBandSupport extends AbstractBTLEDeviceSupport {
// not supported
}
+ @Override
+ public void onSetAudioProperty(int property, int volume) {
+
+ }
+
/**
* Part of device initialization process. Do not call manually.
*
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband2/MiBand2Support.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband2/MiBand2Support.java
index b921db6f..1a18c749 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband2/MiBand2Support.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband2/MiBand2Support.java
@@ -663,6 +663,12 @@ public class MiBand2Support extends AbstractBTLEDeviceSupport {
public void onSetCannedMessages(CannedMessagesSpec cannedMessagesSpec) {
}
+ @Override
+ public void onSetAudioProperty(int property, int volume) {
+
+ }
+
+
private boolean isAlarmClockRinging() {
// don't synchronize, this is not really important
return alarmClockRinging;
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/no1f1/No1F1Support.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/no1f1/No1F1Support.java
index 8e3b1bb3..19f5db7a 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/no1f1/No1F1Support.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/no1f1/No1F1Support.java
@@ -355,6 +355,11 @@ public class No1F1Support extends AbstractBTLEDeviceSupport {
}
+ @Override
+ public void onSetAudioProperty(int property, int volume) {
+
+ }
+
@Override
public void onDeleteCalendarEvent(byte type, long id) {
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/pebble/PebbleSupport.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/pebble/PebbleSupport.java
index ffc88f26..0b18c608 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/pebble/PebbleSupport.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/pebble/PebbleSupport.java
@@ -127,6 +127,11 @@ public class PebbleSupport extends AbstractSerialDeviceSupport {
}
+ @Override
+ public void onSetAudioProperty(int property, int volume) {
+
+ }
+
@Override
public void onSetConstantVibration(int intensity) {
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/vibratissimo/VibratissimoSupport.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/vibratissimo/VibratissimoSupport.java
index 30d8ae36..c9b12f2b 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/vibratissimo/VibratissimoSupport.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/vibratissimo/VibratissimoSupport.java
@@ -185,6 +185,11 @@ public class VibratissimoSupport extends AbstractBTLEDeviceSupport {
}
+ @Override
+ public void onSetAudioProperty(int property, int volume) {
+
+ }
+
@Override
public void onAppStart(UUID uuid, boolean start) {
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/util/DeviceHelper.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/util/DeviceHelper.java
index c9342fa9..1694dd86 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/util/DeviceHelper.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/util/DeviceHelper.java
@@ -51,6 +51,7 @@ import nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandCoordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.no1f1.No1F1Coordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.pebble.PebbleCoordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.vibratissimo.VibratissimoCoordinator;
+import nodomain.freeyourgadget.gadgetbridge.devices.here.HereCoordinator;
import nodomain.freeyourgadget.gadgetbridge.entities.Device;
import nodomain.freeyourgadget.gadgetbridge.entities.DeviceAttributes;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
@@ -198,6 +199,7 @@ public class DeviceHelper {
result.add(new No1F1Coordinator());
result.add(new MakibesF68Coordinator());
result.add(new EXRIZUK8Coordinator());
+ result.add(new HereCoordinator());
result.add(new TeclastH30Coordinator());
return result;
diff --git a/app/src/main/res/layout/audio_settings.xml b/app/src/main/res/layout/audio_settings.xml
new file mode 100644
index 00000000..952574c0
--- /dev/null
+++ b/app/src/main/res/layout/audio_settings.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/device_itemv2.xml b/app/src/main/res/layout/device_itemv2.xml
index 517cd044..bafa4d33 100644
--- a/app/src/main/res/layout/device_itemv2.xml
+++ b/app/src/main/res/layout/device_itemv2.xml
@@ -231,12 +231,27 @@
card_view:srcCompat="@drawable/ic_activity_graphs" />
+
+ Target steps for each day
Error executing \'%1$s\'
Your activity (ALPHA)
+ Audio Settings
Cannot connect: %1$s
Unable to find a handler to install this file.
Unable to install the given file: %1$s
@@ -474,4 +475,5 @@
Open on phone
Mute
Reply
+ Audio Settings