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 34dd7f66b..1fd696893 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/DeviceCommunicationService.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/DeviceCommunicationService.java
@@ -44,14 +44,12 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
-import java.util.Random;
import java.util.UUID;
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.activities.HeartRateUtils;
import nodomain.freeyourgadget.gadgetbridge.devices.DeviceCoordinator;
-import nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiCoordinator;
import nodomain.freeyourgadget.gadgetbridge.externalevents.AlarmClockReceiver;
import nodomain.freeyourgadget.gadgetbridge.externalevents.AlarmReceiver;
import nodomain.freeyourgadget.gadgetbridge.externalevents.BluetoothConnectReceiver;
@@ -75,13 +73,13 @@ import nodomain.freeyourgadget.gadgetbridge.model.MusicStateSpec;
import nodomain.freeyourgadget.gadgetbridge.model.NotificationSpec;
import nodomain.freeyourgadget.gadgetbridge.model.NotificationType;
import nodomain.freeyourgadget.gadgetbridge.model.WeatherSpec;
+import nodomain.freeyourgadget.gadgetbridge.service.receivers.AutoConnectIntervalReceiver;
import nodomain.freeyourgadget.gadgetbridge.service.receivers.GBAutoFetchReceiver;
import nodomain.freeyourgadget.gadgetbridge.util.DeviceHelper;
import nodomain.freeyourgadget.gadgetbridge.util.EmojiConverter;
import nodomain.freeyourgadget.gadgetbridge.util.GB;
import nodomain.freeyourgadget.gadgetbridge.util.GBPrefs;
import nodomain.freeyourgadget.gadgetbridge.util.Prefs;
-import nodomain.freeyourgadget.gadgetbridge.util.StringUtils;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.ACTION_ADD_CALENDAREVENT;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.ACTION_APP_CONFIGURE;
@@ -193,6 +191,7 @@ public class DeviceCommunicationService extends Service implements SharedPrefere
private BluetoothPairingRequestReceiver mBlueToothPairingRequestReceiver = null;
private AlarmClockReceiver mAlarmClockReceiver = null;
private GBAutoFetchReceiver mGBAutoFetchReceiver = null;
+ private AutoConnectIntervalReceiver mAutoConnectInvervalReceiver= null;
private AlarmReceiver mAlarmReceiver = null;
private CalendarReceiver mCalendarReceiver = null;
@@ -760,6 +759,10 @@ public class DeviceCommunicationService extends Service implements SharedPrefere
mGBAutoFetchReceiver = new GBAutoFetchReceiver();
registerReceiver(mGBAutoFetchReceiver, new IntentFilter("android.intent.action.USER_PRESENT"));
}
+ if (mAutoConnectInvervalReceiver == null) {
+ mAutoConnectInvervalReceiver= new AutoConnectIntervalReceiver(this);
+ registerReceiver(mAutoConnectInvervalReceiver, new IntentFilter("GB_RECONNECT"));
+ }
} else {
if (mPhoneCallReceiver != null) {
unregisterReceiver(mPhoneCallReceiver);
@@ -809,6 +812,10 @@ public class DeviceCommunicationService extends Service implements SharedPrefere
unregisterReceiver(mGBAutoFetchReceiver);
mGBAutoFetchReceiver = null;
}
+ if (mAutoConnectInvervalReceiver != null) {
+ unregisterReceiver(mAutoConnectInvervalReceiver);
+ mAutoConnectInvervalReceiver = null;
+ }
}
}
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/BtLEQueue.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/BtLEQueue.java
index 92b56bb33..03d0d7488 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/BtLEQueue.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/BtLEQueue.java
@@ -49,6 +49,7 @@ import nodomain.freeyourgadget.gadgetbridge.Logging;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice.State;
import nodomain.freeyourgadget.gadgetbridge.service.DeviceSupport;
+import nodomain.freeyourgadget.gadgetbridge.service.receivers.AutoConnectIntervalReceiver;
/**
* One queue/thread per connectable device.
@@ -301,8 +302,6 @@ public final class BtLEQueue {
mWaitForServerActionResultLatch.countDown();
}
- boolean wasInitialized = mGbDevice.isInitialized();
-
setDeviceConnectionState(State.NOT_CONNECTED);
// either we've been disconnected because the device is out of range
@@ -312,7 +311,7 @@ public final class BtLEQueue {
// reconnecting automatically, so we try to fix this by re-creating mBluetoothGatt.
// Not sure if this actually works without re-initializing the device...
if (mBluetoothGatt != null) {
- if (!wasInitialized || !maybeReconnect()) {
+ if (!maybeReconnect()) {
disconnect(); // ensure that we start over cleanly next time
}
}
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/actions/SetDeviceStateAction.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/actions/SetDeviceStateAction.java
index bac898926..334e7432f 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/actions/SetDeviceStateAction.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/actions/SetDeviceStateAction.java
@@ -19,6 +19,8 @@ package nodomain.freeyourgadget.gadgetbridge.service.btle.actions;
import android.bluetooth.BluetoothGatt;
import android.content.Context;
+import androidx.annotation.NonNull;
+
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
public class SetDeviceStateAction extends PlainAction {
@@ -43,6 +45,7 @@ public class SetDeviceStateAction extends PlainAction {
return context;
}
+ @NonNull
@Override
public String toString() {
return super.toString() + " to " + deviceState;
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/pebble/PebbleIoThread.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/pebble/PebbleIoThread.java
index 7c1ba63c0..ec6fc8052 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/pebble/PebbleIoThread.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/pebble/PebbleIoThread.java
@@ -28,6 +28,8 @@ import android.webkit.ValueCallback;
import android.webkit.WebView;
import androidx.annotation.NonNull;
+import androidx.localbroadcastmanager.content.LocalBroadcastManager;
+
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -44,7 +46,6 @@ import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.UUID;
-import androidx.localbroadcastmanager.content.LocalBroadcastManager;
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.activities.ExternalPebbleJSActivity;
@@ -110,7 +111,7 @@ class PebbleIoThread extends GBDeviceIoThread {
}
}
- public static void sendAppMessage(GBDeviceEventAppMessage message) {
+ private static void sendAppMessage(GBDeviceEventAppMessage message) {
final String jsEvent;
try {
WebViewSingleton.getInstance().checkAppRunning(message.appUUID);
@@ -190,7 +191,7 @@ class PebbleIoThread extends GBDeviceIoThread {
mOutStream = new PipedOutputStream();
mPebbleLESupport = new PebbleLESupport(this.getContext(), btDevice, (PipedInputStream) mInStream, (PipedOutputStream) mOutStream);
} else {
- ParcelUuid uuids[] = btDevice.getUuids();
+ ParcelUuid[] uuids = btDevice.getUuids();
if (uuids == null) {
return false;
}
@@ -364,7 +365,7 @@ class PebbleIoThread extends GBDeviceIoThread {
mInStream.skip(2);
}
- GBDeviceEvent deviceEvents[] = mPebbleProtocol.decodeResponse(buffer);
+ GBDeviceEvent[] deviceEvents = mPebbleProtocol.decodeResponse(buffer);
if (deviceEvents == null) {
LOG.info("unhandled message to endpoint " + endpoint + " (" + length + " bytes)");
} else {
@@ -386,31 +387,9 @@ class PebbleIoThread extends GBDeviceIoThread {
if (e.getMessage() != null && (e.getMessage().equals("broken pipe") || e.getMessage().contains("socket closed"))) { //FIXME: this does not feel right
LOG.info(e.getMessage());
mIsConnected = false;
- int reconnectAttempts = prefs.getInt("pebble_reconnect_attempts", 10);
- if (!mQuit && GBApplication.getGBPrefs().getAutoReconnect() && reconnectAttempts > 0) {
- gbDevice.setState(GBDevice.State.WAITING_FOR_RECONNECT);
- gbDevice.sendDeviceUpdateIntent(getContext());
-
- long delaySeconds = 1;
- while (reconnectAttempts-- > 0 && !mQuit && !mIsConnected) {
- LOG.info("Trying to reconnect (attempts left " + reconnectAttempts + ")");
- mIsConnected = connect();
- if (!mIsConnected) {
- try {
- Thread.sleep(delaySeconds * 1000);
- } catch (InterruptedException ignored) {
- }
- if (delaySeconds < 64) {
- delaySeconds *= 2;
- }
- }
- }
- }
- if (!mIsConnected) {
- mBtSocket = null;
- LOG.info("Bluetooth socket closed, will quit IO Thread");
- break;
- }
+ mBtSocket = null;
+ LOG.info("Bluetooth socket closed, will quit IO Thread");
+ break;
}
}
}
@@ -426,7 +405,7 @@ class PebbleIoThread extends GBDeviceIoThread {
enablePebbleKitSupport(false);
- if (mQuit) {
+ if (mQuit || !GBApplication.getGBPrefs().getAutoReconnect()) {
gbDevice.setState(GBDevice.State.NOT_CONNECTED);
} else {
gbDevice.setState(GBDevice.State.WAITING_FOR_RECONNECT);
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/receivers/AutoConnectIntervalReceiver.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/receivers/AutoConnectIntervalReceiver.java
new file mode 100644
index 000000000..dad443888
--- /dev/null
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/receivers/AutoConnectIntervalReceiver.java
@@ -0,0 +1,106 @@
+/* Copyright (C) 2019 Andreas Shimokawa
+
+ 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.receivers;
+
+import android.app.AlarmManager;
+import android.app.PendingIntent;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.Build;
+
+import androidx.localbroadcastmanager.content.LocalBroadcastManager;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Calendar;
+
+import nodomain.freeyourgadget.gadgetbridge.BuildConfig;
+import nodomain.freeyourgadget.gadgetbridge.GBApplication;
+import nodomain.freeyourgadget.gadgetbridge.devices.DeviceManager;
+import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
+import nodomain.freeyourgadget.gadgetbridge.service.DeviceCommunicationService;
+
+public class AutoConnectIntervalReceiver extends BroadcastReceiver {
+
+ final DeviceCommunicationService service;
+ static int mDelay = 4;
+ private static final Logger LOG = LoggerFactory.getLogger(AutoConnectIntervalReceiver.class);
+
+ public AutoConnectIntervalReceiver(DeviceCommunicationService service) {
+ this.service = service;
+ IntentFilter filterLocal = new IntentFilter();
+ filterLocal.addAction(DeviceManager.ACTION_DEVICES_CHANGED);
+ LocalBroadcastManager.getInstance(service).registerReceiver(this, filterLocal);
+ }
+
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ String action = intent.getAction();
+ if (action == null) {
+ return;
+ }
+
+ GBDevice gbDevice = service.getGBDevice();
+ if (gbDevice == null) {
+ return;
+ }
+
+ if (action.equals(DeviceManager.ACTION_DEVICES_CHANGED)) {
+ if (gbDevice.isInitialized()) {
+ LOG.info("will reset connection delay, device is initialized!");
+ mDelay = 4;
+ }
+ else if (gbDevice.getState() == GBDevice.State.WAITING_FOR_RECONNECT) {
+ scheduleReconnect();
+ }
+ }
+ else if (action.equals("GB_RECONNECT")) {
+ if (gbDevice.getState() == GBDevice.State.WAITING_FOR_RECONNECT) {
+ LOG.info("Will re-connect to " + gbDevice.getAddress() + "(" + gbDevice.getName() + ")");
+ GBApplication.deviceService().connect();
+ }
+ }
+ }
+
+ public void scheduleReconnect() {
+ mDelay*=2;
+ if (mDelay > 64) {
+ mDelay = 64;
+ }
+ scheduleReconnect(mDelay);
+ }
+
+ public void scheduleReconnect(int delay) {
+ LOG.info("scheduling reconnect in " + delay + " seconds");
+ AlarmManager am = (AlarmManager) (GBApplication.getContext().getSystemService(Context.ALARM_SERVICE));
+ Intent intent = new Intent("GB_RECONNECT");
+ intent.setPackage(BuildConfig.APPLICATION_ID);
+ PendingIntent pendingIntent = PendingIntent.getBroadcast(GBApplication.getContext(), 0, intent, 0);
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
+ am.setAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, Calendar.getInstance().
+ getTimeInMillis() + delay * 1000, pendingIntent);
+ } else {
+ am.set(AlarmManager.RTC_WAKEUP, Calendar.getInstance().
+ getTimeInMillis() + delay * 1000, pendingIntent);
+ }
+ }
+
+}
diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml
index 3b5005954..b57b657b8 100644
--- a/app/src/main/res/values-es/strings.xml
+++ b/app/src/main/res/values-es/strings.xml
@@ -108,7 +108,7 @@
Soporte para llamadas salientes
Desactivar esto evitará que el Pebble 2/LE vibre en llamadas salientes
Permitir el acceso a aplicaciones Android de terceros
- habilitar el soporte experimental para aplicaciones Android que usan PebbleKit
+ Habilitar el soporte experimental para aplicaciones Android que usan PebbleKit
Timeline Pebble
Salida y puesta de Sol
Enviar las horas de salida y puesta de Sol basándose en la localización a la timeline del Pebble
@@ -231,7 +231,7 @@
Pasos por minuto
Encuentra un dispositivo perdido
Cancelar para detener la vibración.
- Tu actividad
+ Actividad y sueño
Configurar alarmas
Configurar alarmas
Detalles de alarma
@@ -259,11 +259,11 @@
A %1$s le queda: %2$s%% batería
Última carga: %s \n
Número de cargas: %s
- Tu sueño
+ Sueño
Sueño por semana
Sueño hoy, objetivo: %1$s
Pasos por semana
- Tu actividad y sueño
+ Actividad
Instalando firmware…
El archivo no puede ser instalado, el dispositivo no está listo.
%1$s: %2$s %3$s
@@ -291,7 +291,7 @@
Si los datos no son marcados como descargados, no serán borrados de tu Mi Band. Útil si Gadgetbridge se usa conjuntamente con otras apps.
Mantendrá los datos de actividad en la Mi Band incluso después de la sincronización. Útil si GB se usa junto con otras apps.
Usa el modo de baja latencia para las instalaciones de firmware
- Esto podría ayudar en dispositivos donde las instalaciones de firmware fallan
+ Esto podría ayudar en dispositivos donde las instalaciones de firmware fallan.
Historial de pasos
Pasos/min actuales
Pasos totales
@@ -348,7 +348,7 @@
Ritmo cardíaco
Ritmo cardíaco
Almacenar datos en bruto en la base de datos
- Una vez seleccionado, los datos archivados se guardan en bruto y están disponibles para ser interpretados más tarde. Nota: ¡La base de datos será más grande!
+ Guarda los datos en bruto para poder ser interpretados más tarde, esto incrementa el tamaño de la base de datos.
Administración de bases de datos
Administración de bases de datos
La base de datos usa la siguiente ubicación en su dispositivo.\nEsta ubicación está accesible para otras aplicaciones Android y para su ordenador.\nEncontrará sus bases de datos exportadas (o la que quiere importar) aquí:
@@ -377,7 +377,7 @@
Vibración
Emparejando con Pebble
- En su dispositivo Android aparecerá un mensaje para emparejar. Si no aparece, mira en el cajón de notificaciones y acepta la propuesta de emparejamiento. Después acepta también en tu Pebble
+ En su dispositivo Android aparecerá un mensaje para emparejar. Si no aparece, mira en el cajón de notificaciones y acepta la propuesta de emparejamiento. Después acepta también en tu Pebble.
Asegúrate de que este tema esté activado en la aplicación de notificación del tiempo para obtener la información en tu Pebble.\n\nNo se requiere configuración.\n\nPuedes activar la aplicación del tiempo del sistema desde la configuración de la app.\n\nLas watchfaces soportadas mostrarán la información del tiempo automáticamente.
Activar el emparejamiento Bluetooth
Desactiva esto si tienes problemas de conexión
@@ -663,15 +663,15 @@
Configuraciones específicas del dispositivo
Clave de autenticación
Cambie la clave de autenticación a una clave común en todos sus dispositivos Android desde los que desea conectarse. La clave predeterminada anterior para todos los dispositivos es 0123456789@ABCDE
- Está a punto de instalar el «firmware» %s en su Amazfit Cor 2.
-\n
-\nAsegúrese de instalar el archivo .fw y, a continuación, el archivo .res. Se reiniciará la pulsera tras instalar el archivo .fw.
-\n
+ Está a punto de instalar el firmware %s en su Amazfit Cor 2.
+\n
+\nAsegúrese de instalar el archivo .fw y, a continuación, el archivo .res. La pulsera se reiniciará despues de instalar el archivo .fw.
+\n
\nNota: no es necesario instalar el archivo .res si es idéntico al instalado previamente.
-\n
-\nPROCEDA BAJO SU PROPIA CUENTA Y RIESGO.
-\n
-\nNO SE HA REALIZADO NINGUNA PRUEBA. QUIZÁ NECESITE INSTALAR UN «FIRMWARE» BEATS_W SI EL NOMBRE DE SU DISPOSITIVO ES «Amazfit Band 2»
+\n
+\nPROCEDA BAJO SU PROPIO RIESGO.
+\n
+\nNO SE HA REALIZADO NINGUNA PRUEBA. QUIZÁ NECESITE INSTALAR UN FIRMWARE BEATS_W SI EL NOMBRE DE SU DISPOSITIVO ES \"Amazfit Band 2\"
Está a punto de instalar el «firmware» %s en su Mi Band 4.
\n
\nAsegúrese de instalar el archivo .fw y, a continuación, el archivo .res. Se reiniciará la pulsera tras instalar el archivo .fw.
@@ -774,4 +774,18 @@
Intervalo de sueño
Últimas 24 horas
De mediodía a mediodía
+ Alarma de sueño
+ Sueño: %1$s
+ Botón de añadir nuevo dispositivo
+ Makibes HR3
+ Amazfit Bip Lite
+ Amazfit GTR
+ Amazfit GTS
+ Está a punto de instalar el firmware %s en su Amazfit GTS.
+\n
+\nPor favor, asegúrese de instalar el archivo .fw primero, el archivo .res a continuación y por ultimo el archivo .gps. Su reloj se reiniciara después de instalar el archivo .fw.
+\n
+\nNota: No hace falta instalar los archivos .res y .gps si los archivos son idénticos a los previamente instalados.
+\n
+\n¡PROCEDE BAJO TU PROPIO RIESGO!
\ No newline at end of file