diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/AbstractBTDeviceSupport.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/AbstractBTDeviceSupport.java
index dd7ecbc61..047f1677a 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/AbstractBTDeviceSupport.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/AbstractBTDeviceSupport.java
@@ -161,4 +161,10 @@ public abstract class AbstractBTDeviceSupport extends AbstractDeviceSupport {
byte[] bytes = gbDeviceProtocol.encodeReboot();
sendToDevice(bytes);
}
+
+ @Override
+ public void onFindDevice(boolean start) {
+ byte[] bytes = gbDeviceProtocol.encodeLocateDevice(start);
+ sendToDevice(bytes);
+ }
}
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/BluetoothCommunicationService.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/BluetoothCommunicationService.java
index 5ed8980fe..52da0a439 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/BluetoothCommunicationService.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/BluetoothCommunicationService.java
@@ -59,6 +59,7 @@ public class BluetoothCommunicationService extends Service {
public static final String ACTION_REBOOT = "nodomain.freeyourgadget.gadgetbride.bluetoothcommunicationservice.action.reboot";
public static final String ACTION_FETCH_ACTIVITY_DATA = "nodomain.freeyourgadget.gadgetbride.bluetoothcommunicationservice.action.fetch_activity_data";
public static final String ACTION_DISCONNECT = "nodomain.freeyourgadget.gadgetbride.bluetoothcommunicationservice.action.disconnect";
+ public static final String ACTION_FIND_DEVICE = "nodomain.freeyourgadget.gadgetbride.bluetoothcommunicationservice.action.find_device";
public static final String EXTRA_PERFORM_PAIR = "perform_pair";
@@ -208,6 +209,11 @@ public class BluetoothCommunicationService extends Service {
mDeviceSupport = null;
break;
}
+ case ACTION_FIND_DEVICE: {
+ boolean start = intent.getBooleanExtra("find_start", false);
+ mDeviceSupport.onFindDevice(start);
+ break;
+ }
case ACTION_CALLSTATE:
GBCommand command = GBCommand.values()[intent.getIntExtra("call_command", 0)]; // UGLY
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/ControlCenter.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/ControlCenter.java
index ff977aedc..64a6b6f7d 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/ControlCenter.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/ControlCenter.java
@@ -1,10 +1,13 @@
package nodomain.freeyourgadget.gadgetbridge;
import android.app.Activity;
+import android.app.AlertDialog;
+import android.app.ProgressDialog;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.content.BroadcastReceiver;
import android.content.Context;
+import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
@@ -198,11 +201,32 @@ public class ControlCenter extends Activity {
startService(startIntent);
}
return true;
+ case R.id.controlcenter_find_device:
+ if (selectedDevice != null) {
+ findDevice(true);
+ ProgressDialog dialog = ProgressDialog.show(
+ this,
+ getString(R.string.control_center_find_lost_device),
+ getString(R.string.control_center_cancel_to_stop_vibration),
+ true, true,
+ new DialogInterface.OnCancelListener() {
+ @Override
+ public void onCancel(DialogInterface dialog) {
+ findDevice(false);
+ }
+ });
+ }
default:
return super.onContextItemSelected(item);
}
}
+ private void findDevice(boolean start) {
+ Intent startIntent = new Intent(this, BluetoothCommunicationService.class);
+ startIntent.putExtra("find_start", start);
+ startIntent.setAction(BluetoothCommunicationService.ACTION_FIND_DEVICE);
+ startService(startIntent);
+ }
@Override
public boolean onCreateOptionsMenu(Menu menu) {
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/EventHandler.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/EventHandler.java
index 4ce49b153..8dbcf63c6 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/EventHandler.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/EventHandler.java
@@ -34,4 +34,6 @@ public interface EventHandler {
void onFetchActivityData();
void onReboot();
+
+ void onFindDevice(boolean start);
}
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/ServiceDeviceSupport.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/ServiceDeviceSupport.java
index f929274d4..1574a5d79 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/ServiceDeviceSupport.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/ServiceDeviceSupport.java
@@ -210,4 +210,12 @@ public class ServiceDeviceSupport implements DeviceSupport {
}
delegate.onReboot();
}
+
+ @Override
+ public void onFindDevice(boolean start) {
+ if (checkBusy("find device")) {
+ return;
+ }
+ delegate.onFindDevice(start);
+ }
}
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/miband/MiBandSupport.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/miband/MiBandSupport.java
index b0dd21a6c..9054b0867 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/miband/MiBandSupport.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/miband/MiBandSupport.java
@@ -69,6 +69,7 @@ public class MiBandSupport extends AbstractBTLEDeviceSupport {
//same as above, but remains untouched for the ack message
private GregorianCalendar activityDataTimestampToAck = null;
private volatile boolean telephoneRinging;
+ private volatile boolean isLocatingDevice;
public MiBandSupport() {
@@ -135,10 +136,15 @@ public class MiBandSupport extends AbstractBTLEDeviceSupport {
return getNotification(vibrateDuration, vibrateTimes, flashTimes, flashColour, originalColour, flashDuration);
}
- private void sendDefaultNotification(TransactionBuilder builder) {
+ private void sendDefaultNotification(TransactionBuilder builder, short repeat, BtLEAction extraAction) {
BluetoothGattCharacteristic characteristic = getCharacteristic(MiBandService.UUID_CHARACTERISTIC_CONTROL_POINT);
- LOG.info("Sending notification to MiBand: " + characteristic);
- builder.write(characteristic, getDefaultNotification()).queue(getQueue());
+ LOG.info("Sending notification to MiBand: " + characteristic + " (" + repeat + " times)");
+ byte[] defaultNotification = getDefaultNotification();
+ for (short i = 0; i < repeat; i++) {
+ builder.write(characteristic, defaultNotification);
+ builder.add(extraAction);
+ }
+ builder.queue(getQueue());
}
/**
@@ -153,7 +159,7 @@ public class MiBandSupport extends AbstractBTLEDeviceSupport {
*/
private void sendCustomNotification(VibrationProfile vibrationProfile, int flashTimes, int flashColour, int originalColour, long flashDuration, BtLEAction extraAction, TransactionBuilder builder) {
BluetoothGattCharacteristic controlPoint = getCharacteristic(MiBandService.UUID_CHARACTERISTIC_CONTROL_POINT);
- for (byte i = 0; i < vibrationProfile.getRepeat(); i++) {
+ for (short i = 0; i < vibrationProfile.getRepeat(); i++) {
int[] onOffSequence = vibrationProfile.getOnOffSequence();
for (int j = 0; j < onOffSequence.length; j++) {
int on = onOffSequence[j];
@@ -245,10 +251,10 @@ public class MiBandSupport extends AbstractBTLEDeviceSupport {
return this;
}
- private void performDefaultNotification(String task) {
+ private void performDefaultNotification(String task, short repeat, BtLEAction extraAction) {
try {
TransactionBuilder builder = performInitialized(task);
- sendDefaultNotification(builder);
+ sendDefaultNotification(builder, repeat, extraAction);
} catch (IOException ex) {
LOG.error("Unable to send notification to MI device", ex);
}
@@ -314,7 +320,7 @@ public class MiBandSupport extends AbstractBTLEDeviceSupport {
private VibrationProfile getPreferredVibrateProfile(String notificationOrigin, SharedPreferences prefs, int repeat) {
String profileId = getNotificationPrefStringValue(VIBRATION_PROFILE, notificationOrigin, prefs, DEFAULT_VALUE_VIBRATION_PROFILE);
- return VibrationProfile.getProfile(profileId, (byte) repeat);
+ return VibrationProfile.getProfile(profileId, (byte) (repeat & 0xfff));
}
@Override
@@ -432,6 +438,21 @@ public class MiBandSupport extends AbstractBTLEDeviceSupport {
}
}
+ @Override
+ public void onFindDevice(boolean start) {
+ isLocatingDevice = start;
+
+ if (start) {
+ AbortTransactionAction abortAction = new AbortTransactionAction() {
+ @Override
+ protected boolean shouldAbort() {
+ return !isLocatingDevice;
+ }
+ };
+ performDefaultNotification("locating device", (short) 255, abortAction);
+ }
+ }
+
@Override
public void onFetchActivityData() {
try {
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/miband/VibrationProfile.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/miband/VibrationProfile.java
index 7144f80ca..5596a0a1a 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/miband/VibrationProfile.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/miband/VibrationProfile.java
@@ -41,7 +41,7 @@ public class VibrationProfile {
private final String id;
private int[] onOffSequence;
- private byte repeat; // 1-10
+ private short repeat;
/**
* Creates a new profile instance.
@@ -49,7 +49,7 @@ public class VibrationProfile {
* @param onOffSequence a sequence of alternating on and off durations, in milliseconds
* @param repeat how ofoften the sequence shall be repeated
*/
- public VibrationProfile(String id, int[] onOffSequence, byte repeat) {
+ public VibrationProfile(String id, int[] onOffSequence, short repeat) {
this.id = id;
this.repeat = repeat;
this.onOffSequence = onOffSequence;
@@ -63,7 +63,7 @@ public class VibrationProfile {
return onOffSequence;
}
- public byte getRepeat() {
+ public short getRepeat() {
return repeat;
}
}
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/protocol/GBDeviceProtocol.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/protocol/GBDeviceProtocol.java
index f91e777cf..c1fe6a21e 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/protocol/GBDeviceProtocol.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/protocol/GBDeviceProtocol.java
@@ -62,6 +62,10 @@ public abstract class GBDeviceProtocol {
return null;
}
+ public byte[] encodeLocateDevice(boolean start) {
+ return null;
+ }
+
public GBDeviceCommand decodeResponse(byte[] responseData) {
return null;
}
diff --git a/app/src/main/res/menu/controlcenter_context.xml b/app/src/main/res/menu/controlcenter_context.xml
index 9322d26b7..cbfd60100 100644
--- a/app/src/main/res/menu/controlcenter_context.xml
+++ b/app/src/main/res/menu/controlcenter_context.xml
@@ -6,6 +6,9 @@
+
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 23b6a6d9f..5f5ab3141 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -133,5 +133,8 @@
Pebble Notification
K9 Mail Notification
Incoming Call Notification
+ Find Deviceā¦
+ Find lost Device
+ Cancel to stop vibration.