mirror of
https://codeberg.org/Freeyourgadget/Gadgetbridge
synced 2024-11-29 05:16:51 +01:00
Merge branch 'master' into feature-weather
This commit is contained in:
commit
ec154c9041
@ -1,4 +1,12 @@
|
||||
###Changelog
|
||||
####Version 0.9.8
|
||||
* Pebble: fix more reconnnect issues
|
||||
* Pebble: fix deep sleep not being detected with Firmware 3.12 when using Pebble Health
|
||||
* Pebble: option in AppManager to delete files from cache
|
||||
* Pebble: enable pbw cache and watchface configuration for Firmware 2.x
|
||||
* Pebble: allow enabling of Pebble Health without "untested features" being enabled
|
||||
* Honour "Do Not Disturb" for phone calls and SMS
|
||||
|
||||
####Version 0.9.7
|
||||
* Pebble: hopefully fix some reconnect issues
|
||||
* Mi Band: fix live activity monitoring running forever if back button pressed
|
||||
|
28
CONTRIBUTORS.md
Normal file
28
CONTRIBUTORS.md
Normal file
@ -0,0 +1,28 @@
|
||||
Andreas Shimokawa <shimokawa@fsfe.org>
|
||||
cpfeiffer <cpfeiffer@users.noreply.github.com>
|
||||
Daniele Gobbetti <daniele+github@gobbetti.name>
|
||||
Daniele Gobbetti <daniele@gobbetti.name>
|
||||
danielegobbetti <daniele+github@gobbetti.name>
|
||||
Carsten Pfeiffer <cpfeiffer@users.noreply.github.com>
|
||||
Julien Pivotto <roidelapluie@inuits.eu>
|
||||
Lem Dulfo <lemuel.dulfo@gmail.com>
|
||||
Sergey Trofimov <sarg@sarg.org.ru>
|
||||
Daniele Gobbetti <daniele.gobbetti@gmail.com>
|
||||
cpfeiffer <cpfeiffer@users.github.com>
|
||||
0nse <0nse@users.noreply.github.com>
|
||||
Christian Fischer <sw-dev@computerlyrik.de>
|
||||
Normano64 <per.bergqwist@gmail.com>
|
||||
Ⲇⲁⲛⲓ Φi <daniphii@outlook.com>
|
||||
xphnx <xphnx@users.noreply.github.com>
|
||||
Tarik Sekmen <tarik@ilixi.org>
|
||||
rober <rober@prtl.nodomain.net>
|
||||
Nicolò Balzarotti <anothersms@gmail.com>
|
||||
Marc Schlaich <marc.schlaich@googlemail.com>
|
||||
kevlarcade <kevlarcade@gmail.com>
|
||||
Kasha <kasha_malaga@hotmail.com>
|
||||
Chris Perelstein <chris.perelstein@gmail.com>
|
||||
Alexey Afanasev <avafanasiev@gmail.com>
|
||||
|
||||
And all the Transifex translators, which I cannot automatically list, at the moment.
|
||||
|
||||
git log --raw | grep "^Author: " | sort | uniq -c | sort -k 1 -n -r | cut -f 2- -d: > CONTRIBUTORS.md
|
@ -16,8 +16,8 @@ android {
|
||||
targetSdkVersion 23
|
||||
|
||||
// note: always bump BOTH versionCode and versionName!
|
||||
versionName "0.9.7"
|
||||
versionCode 51
|
||||
versionName "0.9.8"
|
||||
versionCode 52
|
||||
}
|
||||
buildTypes {
|
||||
release {
|
||||
|
@ -1,15 +1,21 @@
|
||||
package nodomain.freeyourgadget.gadgetbridge;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.app.Application;
|
||||
import android.app.NotificationManager;
|
||||
import android.app.NotificationManager.Policy;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.res.Resources;
|
||||
import android.database.Cursor;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Build.VERSION;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.provider.ContactsContract.PhoneLookup;
|
||||
import android.support.v4.content.LocalBroadcastManager;
|
||||
import android.util.Log;
|
||||
import android.util.TypedValue;
|
||||
@ -59,6 +65,10 @@ public class GBApplication extends Application {
|
||||
private static Appender<ILoggingEvent> fileLogger;
|
||||
private static Prefs prefs;
|
||||
private static GBPrefs gbPrefs;
|
||||
/**
|
||||
* Note: is null on Lollipop and Kitkat
|
||||
*/
|
||||
private static NotificationManager notificationManager;
|
||||
|
||||
public static final String ACTION_QUIT
|
||||
= "nodomain.freeyourgadget.gadgetbridge.gbapplication.action.quit";
|
||||
@ -119,6 +129,10 @@ public class GBApplication extends Application {
|
||||
filterLocal.addAction(ACTION_QUIT);
|
||||
LocalBroadcastManager.getInstance(this).registerReceiver(mReceiver, filterLocal);
|
||||
|
||||
if (isRunningMarshmallowOrLater()) {
|
||||
notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
}
|
||||
|
||||
// for testing DB stuff
|
||||
// SQLiteDatabase db = mActivityDatabaseHandler.getWritableDatabase();
|
||||
// db.close();
|
||||
@ -247,6 +261,63 @@ public class GBApplication extends Application {
|
||||
return VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP;
|
||||
}
|
||||
|
||||
public static boolean isRunningMarshmallowOrLater() {
|
||||
return VERSION.SDK_INT >= Build.VERSION_CODES.M;
|
||||
}
|
||||
|
||||
private static boolean isPrioritySender(int prioritySenders, String number) {
|
||||
if (prioritySenders == Policy.PRIORITY_SENDERS_ANY) {
|
||||
return true;
|
||||
} else {
|
||||
Uri uri = Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, Uri.encode(number));
|
||||
String[] projection = new String[]{PhoneLookup._ID, PhoneLookup.STARRED};
|
||||
Cursor cursor = context.getContentResolver().query(uri, projection, null, null, null);
|
||||
boolean exists = false;
|
||||
int starred = 0;
|
||||
try {
|
||||
if (cursor != null && cursor.moveToFirst()) {
|
||||
exists = true;
|
||||
starred = cursor.getInt(cursor.getColumnIndexOrThrow(PhoneLookup.STARRED));
|
||||
}
|
||||
} finally {
|
||||
if (cursor != null) {
|
||||
cursor.close();
|
||||
}
|
||||
}
|
||||
if (prioritySenders == Policy.PRIORITY_SENDERS_CONTACTS && exists) {
|
||||
return true;
|
||||
} else if (prioritySenders == Policy.PRIORITY_SENDERS_STARRED && starred == 1) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.M)
|
||||
public static boolean isPriorityNumber(int priorityType, String number) {
|
||||
NotificationManager.Policy notificationPolicy = notificationManager.getNotificationPolicy();
|
||||
if(priorityType == Policy.PRIORITY_CATEGORY_MESSAGES) {
|
||||
if ((notificationPolicy.priorityCategories & Policy.PRIORITY_CATEGORY_MESSAGES) == Policy.PRIORITY_CATEGORY_MESSAGES) {
|
||||
return isPrioritySender(notificationPolicy.priorityMessageSenders, number);
|
||||
}
|
||||
} else if (priorityType == Policy.PRIORITY_CATEGORY_CALLS) {
|
||||
if ((notificationPolicy.priorityCategories & Policy.PRIORITY_CATEGORY_CALLS) == Policy.PRIORITY_CATEGORY_CALLS) {
|
||||
return isPrioritySender(notificationPolicy.priorityCallSenders, number);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.M)
|
||||
public static int getGrantedInterruptionFilter() {
|
||||
if (prefs.getBoolean("notification_filter", false) && GBApplication.isRunningMarshmallowOrLater()) {
|
||||
if (notificationManager.isNotificationPolicyAccessGranted()) {
|
||||
return notificationManager.getCurrentInterruptionFilter();
|
||||
}
|
||||
}
|
||||
return NotificationManager.INTERRUPTION_FILTER_ALL;
|
||||
}
|
||||
|
||||
public static HashSet<String> blacklist = null;
|
||||
|
||||
private static void loadBlackList() {
|
||||
|
@ -22,6 +22,7 @@ import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.ListIterator;
|
||||
import java.util.UUID;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
|
||||
@ -47,7 +48,6 @@ public class AppManagerActivity extends GBActivity {
|
||||
if (action.equals(GBApplication.ACTION_QUIT)) {
|
||||
finish();
|
||||
} else if (action.equals(ACTION_REFRESH_APPLIST)) {
|
||||
appList.clear();
|
||||
int appCount = intent.getIntExtra("app_count", 0);
|
||||
for (Integer i = 0; i < appCount; i++) {
|
||||
String appName = intent.getStringExtra("app_name" + i.toString());
|
||||
@ -55,11 +55,21 @@ public class AppManagerActivity extends GBActivity {
|
||||
UUID uuid = UUID.fromString(intent.getStringExtra("app_uuid" + i.toString()));
|
||||
GBDeviceApp.Type appType = GBDeviceApp.Type.values()[intent.getIntExtra("app_type" + i.toString(), 0)];
|
||||
|
||||
appList.add(new GBDeviceApp(uuid, appName, appCreator, "", appType));
|
||||
boolean found = false;
|
||||
for (final ListIterator<GBDeviceApp> iter = appList.listIterator(); iter.hasNext(); ) {
|
||||
final GBDeviceApp app = iter.next();
|
||||
if (app.getUUID().equals(uuid)) {
|
||||
app.setOnDevice(true);
|
||||
iter.set(app);
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
GBDeviceApp app = new GBDeviceApp(uuid, appName, appCreator, "", appType);
|
||||
app.setOnDevice(true);
|
||||
appList.add(app);
|
||||
}
|
||||
|
||||
if (prefs.getBoolean("pebble_force_untested", false)) {
|
||||
appList.addAll(getSystemApps());
|
||||
}
|
||||
|
||||
mGBDeviceAppAdapter.notifyDataSetChanged();
|
||||
@ -76,8 +86,10 @@ public class AppManagerActivity extends GBActivity {
|
||||
|
||||
private List<GBDeviceApp> getSystemApps() {
|
||||
List<GBDeviceApp> systemApps = new ArrayList<>();
|
||||
if (prefs.getBoolean("pebble_force_untested", false)) {
|
||||
systemApps.add(new GBDeviceApp(UUID.fromString("4dab81a6-d2fc-458a-992c-7a1f3b96a970"), "Sports (System)", "Pebble Inc.", "", GBDeviceApp.Type.APP_SYSTEM));
|
||||
systemApps.add(new GBDeviceApp(UUID.fromString("cf1e816a-9db0-4511-bbb8-f60c48ca8fac"), "Golf (System)", "Pebble Inc.", "", GBDeviceApp.Type.APP_SYSTEM));
|
||||
}
|
||||
if (mGBDevice != null && !"aplite".equals(PebbleUtils.getPlatformName(mGBDevice.getHardwareVersion()))) {
|
||||
systemApps.add(new GBDeviceApp(PebbleProtocol.UUID_PEBBLE_HEALTH, "Health (System)", "Pebble Inc.", "", GBDeviceApp.Type.APP_SYSTEM));
|
||||
}
|
||||
@ -149,9 +161,7 @@ public class AppManagerActivity extends GBActivity {
|
||||
|
||||
appList.addAll(getCachedApps());
|
||||
|
||||
if (prefs.getBoolean("pebble_force_untested", false)) {
|
||||
appList.addAll(getSystemApps());
|
||||
}
|
||||
|
||||
IntentFilter filter = new IntentFilter();
|
||||
filter.addAction(GBApplication.ACTION_QUIT);
|
||||
@ -171,11 +181,13 @@ public class AppManagerActivity extends GBActivity {
|
||||
|
||||
if (!selectedApp.isInCache()) {
|
||||
menu.removeItem(R.id.appmanager_app_reinstall);
|
||||
menu.removeItem(R.id.appmanager_app_delete_cache);
|
||||
}
|
||||
if (!PebbleProtocol.UUID_PEBBLE_HEALTH.equals(selectedApp.getUUID())) {
|
||||
menu.removeItem(R.id.appmanager_health_activate);
|
||||
menu.removeItem(R.id.appmanager_health_deactivate);
|
||||
} else if (PebbleProtocol.UUID_PEBBLE_HEALTH.equals(selectedApp.getUUID())) {
|
||||
}
|
||||
if (selectedApp.getType() == GBDeviceApp.Type.APP_SYSTEM) {
|
||||
menu.removeItem(R.id.appmanager_app_delete);
|
||||
}
|
||||
if (!selectedApp.isConfigurable()) {
|
||||
@ -184,10 +196,42 @@ public class AppManagerActivity extends GBActivity {
|
||||
menu.setHeaderTitle(selectedApp.getName());
|
||||
}
|
||||
|
||||
private void removeAppFromList(UUID uuid) {
|
||||
for (final ListIterator<GBDeviceApp> iter = appList.listIterator(); iter.hasNext(); ) {
|
||||
final GBDeviceApp app = iter.next();
|
||||
if (app.getUUID().equals(uuid)) {
|
||||
iter.remove();
|
||||
mGBDeviceAppAdapter.notifyDataSetChanged();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onContextItemSelected(MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
case R.id.appmanager_health_deactivate:
|
||||
case R.id.appmanager_app_delete_cache:
|
||||
String baseName;
|
||||
try {
|
||||
baseName = FileUtils.getExternalFilesDir().getPath() + "/pbw-cache/" + selectedApp.getUUID();
|
||||
} catch (IOException e) {
|
||||
LOG.warn("could not get external dir while trying to access pbw cache.");
|
||||
return true;
|
||||
}
|
||||
|
||||
String[] suffixToDelete = new String[]{".pbw", ".json", "_config.js"};
|
||||
|
||||
for (String suffix : suffixToDelete) {
|
||||
File fileToDelete = new File(baseName + suffix);
|
||||
if (!fileToDelete.delete()) {
|
||||
LOG.warn("could not delete file from pbw cache: " + fileToDelete.toString());
|
||||
} else {
|
||||
LOG.info("deleted file: " + fileToDelete.toString());
|
||||
}
|
||||
}
|
||||
removeAppFromList(selectedApp.getUUID());
|
||||
// fall through
|
||||
case R.id.appmanager_app_delete:
|
||||
GBApplication.deviceService().onAppDelete(selectedApp.getUUID());
|
||||
return true;
|
||||
@ -196,7 +240,7 @@ public class AppManagerActivity extends GBActivity {
|
||||
try {
|
||||
cachePath = new File(FileUtils.getExternalFilesDir().getPath() + "/pbw-cache/" + selectedApp.getUUID() + ".pbw");
|
||||
} catch (IOException e) {
|
||||
LOG.warn("could not get external dir while reading pbw cache.");
|
||||
LOG.warn("could not get external dir while trying to access pbw cache.");
|
||||
return true;
|
||||
}
|
||||
GBApplication.deviceService().onInstallApp(Uri.fromFile(cachePath));
|
||||
|
@ -6,6 +6,7 @@ import android.content.pm.ResolveInfo;
|
||||
import android.os.Bundle;
|
||||
import android.preference.ListPreference;
|
||||
import android.preference.Preference;
|
||||
import android.preference.PreferenceCategory;
|
||||
import android.support.v4.content.LocalBroadcastManager;
|
||||
import android.widget.Toast;
|
||||
|
||||
@ -107,6 +108,12 @@ public class SettingsActivity extends AbstractSettingsActivity {
|
||||
|
||||
});
|
||||
|
||||
if (!GBApplication.isRunningMarshmallowOrLater()) {
|
||||
pref = findPreference("notification_filter");
|
||||
PreferenceCategory category = (PreferenceCategory) findPreference("pref_key_notifications");
|
||||
category.removePreference(pref);
|
||||
}
|
||||
|
||||
// Get all receivers of Media Buttons
|
||||
Intent mediaButtonIntent = new Intent(Intent.ACTION_MEDIA_BUTTON);
|
||||
|
||||
|
@ -41,7 +41,15 @@ public class GBDeviceAppAdapter extends ArrayAdapter<GBDeviceApp> {
|
||||
ImageView deviceImageView = (ImageView) view.findViewById(R.id.item_image);
|
||||
|
||||
deviceAppVersionAuthorLabel.setText(getContext().getString(R.string.appversion_by_creator, deviceApp.getVersion(), deviceApp.getCreator()));
|
||||
deviceAppNameLabel.setText(deviceApp.getName());
|
||||
|
||||
// FIXME: replace with small icons
|
||||
String appNameLabelText = deviceApp.getName();
|
||||
if (deviceApp.isInCache() || deviceApp.isOnDevice()) {
|
||||
appNameLabelText += " (" + (deviceApp.isInCache() ? "C" : "")
|
||||
+ (deviceApp.isOnDevice() ? "D" : "") + ")";
|
||||
}
|
||||
deviceAppNameLabel.setText(appNameLabelText);
|
||||
|
||||
switch (deviceApp.getType()) {
|
||||
case APP_GENERIC:
|
||||
deviceImageView.setImageResource(R.drawable.ic_watchapp);
|
||||
|
@ -129,10 +129,6 @@ public class PBWInstallHandler implements InstallHandler {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!device.getFirmwareVersion().startsWith("v3")) {
|
||||
return;
|
||||
}
|
||||
|
||||
File destDir;
|
||||
GBDeviceApp app = mPBWReader.getGBDeviceApp();
|
||||
try {
|
||||
|
@ -0,0 +1,43 @@
|
||||
package nodomain.freeyourgadget.gadgetbridge.externalevents;
|
||||
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
|
||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.DeviceCommunicationService;
|
||||
|
||||
public class BluetoothConnectReceiver extends BroadcastReceiver {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(DeviceCommunicationService.class);
|
||||
|
||||
final DeviceCommunicationService service;
|
||||
|
||||
public BluetoothConnectReceiver(DeviceCommunicationService service) {
|
||||
this.service = service;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
String action = intent.getAction();
|
||||
if (!action.equals(BluetoothDevice.ACTION_ACL_CONNECTED)) {
|
||||
return;
|
||||
}
|
||||
LOG.info("got connection attempt");
|
||||
GBDevice gbDevice = service.getGBDevice();
|
||||
if (gbDevice != null) {
|
||||
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
|
||||
if (device.getAddress().equals(gbDevice.getAddress())) {
|
||||
LOG.info("will connect to " + gbDevice.getName());
|
||||
GBApplication.deviceService().connect();
|
||||
} else {
|
||||
LOG.info("won't connect to " + device.getAddress() + "(" + device.getName() + ")");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
package nodomain.freeyourgadget.gadgetbridge.externalevents;
|
||||
|
||||
import android.app.NotificationManager;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
@ -33,6 +34,14 @@ public class K9Receiver extends BroadcastReceiver {
|
||||
return;
|
||||
}
|
||||
}
|
||||
switch (GBApplication.getGrantedInterruptionFilter()) {
|
||||
case NotificationManager.INTERRUPTION_FILTER_ALL:
|
||||
break;
|
||||
case NotificationManager.INTERRUPTION_FILTER_ALARMS:
|
||||
case NotificationManager.INTERRUPTION_FILTER_NONE:
|
||||
case NotificationManager.INTERRUPTION_FILTER_PRIORITY:
|
||||
return;
|
||||
}
|
||||
|
||||
String uriWanted = intent.getData().toString();
|
||||
|
||||
|
@ -3,6 +3,7 @@ package nodomain.freeyourgadget.gadgetbridge.externalevents;
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.ActivityManager;
|
||||
import android.app.Notification;
|
||||
import android.app.NotificationManager;
|
||||
import android.app.PendingIntent;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
@ -167,6 +168,16 @@ public class NotificationListener extends NotificationListenerService {
|
||||
return;
|
||||
}
|
||||
}
|
||||
switch (GBApplication.getGrantedInterruptionFilter()) {
|
||||
case NotificationManager.INTERRUPTION_FILTER_ALL:
|
||||
break;
|
||||
case NotificationManager.INTERRUPTION_FILTER_ALARMS:
|
||||
case NotificationManager.INTERRUPTION_FILTER_NONE:
|
||||
return;
|
||||
case NotificationManager.INTERRUPTION_FILTER_PRIORITY:
|
||||
// FIXME: Handle Reminders and Events if they are enabled in Do Not Disturb
|
||||
return;
|
||||
}
|
||||
|
||||
String source = sbn.getPackageName();
|
||||
Notification notification = sbn.getNotification();
|
||||
|
@ -1,5 +1,7 @@
|
||||
package nodomain.freeyourgadget.gadgetbridge.externalevents;
|
||||
|
||||
import android.app.NotificationManager;
|
||||
import android.app.NotificationManager.Policy;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
@ -67,6 +69,19 @@ public class PhoneCallReceiver extends BroadcastReceiver {
|
||||
if ("never".equals(prefs.getString("notification_mode_calls", "always"))) {
|
||||
return;
|
||||
}
|
||||
switch (GBApplication.getGrantedInterruptionFilter()) {
|
||||
case NotificationManager.INTERRUPTION_FILTER_ALL:
|
||||
break;
|
||||
case NotificationManager.INTERRUPTION_FILTER_ALARMS:
|
||||
case NotificationManager.INTERRUPTION_FILTER_NONE:
|
||||
return;
|
||||
case NotificationManager.INTERRUPTION_FILTER_PRIORITY:
|
||||
if (GBApplication.isPriorityNumber(Policy.PRIORITY_CATEGORY_CALLS, mSavedNumber)) {
|
||||
break;
|
||||
}
|
||||
// FIXME: Handle Repeat callers if it is enabled in Do Not Disturb
|
||||
return;
|
||||
}
|
||||
CallSpec callSpec = new CallSpec();
|
||||
callSpec.number = mSavedNumber;
|
||||
callSpec.command = callCommand;
|
||||
|
@ -1,5 +1,7 @@
|
||||
package nodomain.freeyourgadget.gadgetbridge.externalevents;
|
||||
|
||||
import android.app.NotificationManager;
|
||||
import android.app.NotificationManager.Policy;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
@ -41,6 +43,18 @@ public class SMSReceiver extends BroadcastReceiver {
|
||||
notificationSpec.body = message.getDisplayMessageBody();
|
||||
notificationSpec.phoneNumber = message.getOriginatingAddress();
|
||||
if (notificationSpec.phoneNumber != null) {
|
||||
switch (GBApplication.getGrantedInterruptionFilter()) {
|
||||
case NotificationManager.INTERRUPTION_FILTER_ALL:
|
||||
break;
|
||||
case NotificationManager.INTERRUPTION_FILTER_ALARMS:
|
||||
case NotificationManager.INTERRUPTION_FILTER_NONE:
|
||||
return;
|
||||
case NotificationManager.INTERRUPTION_FILTER_PRIORITY:
|
||||
if (GBApplication.isPriorityNumber(Policy.PRIORITY_CATEGORY_MESSAGES, notificationSpec.phoneNumber)) {
|
||||
break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
GBApplication.deviceService().onNotification(notificationSpec);
|
||||
}
|
||||
}
|
||||
|
@ -12,6 +12,7 @@ public class GBDeviceApp {
|
||||
private final UUID uuid;
|
||||
private final Type type;
|
||||
private final boolean inCache;
|
||||
private boolean isOnDevice;
|
||||
private final boolean configurable;
|
||||
|
||||
public GBDeviceApp(UUID uuid, String name, String creator, String version, Type type) {
|
||||
@ -23,6 +24,7 @@ public class GBDeviceApp {
|
||||
//FIXME: do not assume
|
||||
this.inCache = false;
|
||||
this.configurable = false;
|
||||
this.isOnDevice = false;
|
||||
}
|
||||
|
||||
public GBDeviceApp(JSONObject json, boolean configurable) {
|
||||
@ -52,10 +54,18 @@ public class GBDeviceApp {
|
||||
this.configurable = configurable;
|
||||
}
|
||||
|
||||
public void setOnDevice(boolean isOnDevice) {
|
||||
this.isOnDevice = isOnDevice;
|
||||
}
|
||||
|
||||
public boolean isInCache() {
|
||||
return inCache;
|
||||
}
|
||||
|
||||
public boolean isOnDevice() {
|
||||
return isOnDevice;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ package nodomain.freeyourgadget.gadgetbridge.service;
|
||||
|
||||
import android.app.NotificationManager;
|
||||
import android.app.Service;
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
@ -24,6 +25,7 @@ import java.util.UUID;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
|
||||
import nodomain.freeyourgadget.gadgetbridge.R;
|
||||
import nodomain.freeyourgadget.gadgetbridge.externalevents.BluetoothConnectReceiver;
|
||||
import nodomain.freeyourgadget.gadgetbridge.externalevents.K9Receiver;
|
||||
import nodomain.freeyourgadget.gadgetbridge.externalevents.MusicPlaybackReceiver;
|
||||
import nodomain.freeyourgadget.gadgetbridge.externalevents.PebbleReceiver;
|
||||
@ -105,6 +107,7 @@ public class DeviceCommunicationService extends Service implements SharedPrefere
|
||||
private PebbleReceiver mPebbleReceiver = null;
|
||||
private MusicPlaybackReceiver mMusicPlaybackReceiver = null;
|
||||
private TimeChangeReceiver mTimeChangeReceiver = null;
|
||||
private BluetoothConnectReceiver mBlueToothConnectReceiver = null;
|
||||
|
||||
private Random mRandom = new Random();
|
||||
|
||||
@ -279,6 +282,11 @@ public class DeviceCommunicationService extends Service implements SharedPrefere
|
||||
}
|
||||
case ACTION_DISCONNECT: {
|
||||
mDeviceSupport.dispose();
|
||||
if (mGBDevice != null && mGBDevice.getState() == GBDevice.State.WAITING_FOR_RECONNECT) {
|
||||
setReceiversEnableState(false);
|
||||
mGBDevice.setState(GBDevice.State.NOT_CONNECTED);
|
||||
mGBDevice.sendDeviceUpdateIntent(this);
|
||||
}
|
||||
mDeviceSupport = null;
|
||||
break;
|
||||
}
|
||||
@ -457,6 +465,10 @@ public class DeviceCommunicationService extends Service implements SharedPrefere
|
||||
filter.addAction("android.intent.action.TIMEZONE_CHANGED");
|
||||
registerReceiver(mTimeChangeReceiver, filter);
|
||||
}
|
||||
if (mBlueToothConnectReceiver == null) {
|
||||
mBlueToothConnectReceiver = new BluetoothConnectReceiver(this);
|
||||
registerReceiver(mBlueToothConnectReceiver, new IntentFilter(BluetoothDevice.ACTION_ACL_CONNECTED));
|
||||
}
|
||||
} else {
|
||||
if (mPhoneCallReceiver != null) {
|
||||
unregisterReceiver(mPhoneCallReceiver);
|
||||
@ -482,6 +494,10 @@ public class DeviceCommunicationService extends Service implements SharedPrefere
|
||||
unregisterReceiver(mTimeChangeReceiver);
|
||||
mTimeChangeReceiver = null;
|
||||
}
|
||||
if (mBlueToothConnectReceiver != null) {
|
||||
unregisterReceiver(mBlueToothConnectReceiver);
|
||||
mBlueToothConnectReceiver = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -549,4 +565,8 @@ public class DeviceCommunicationService extends Service implements SharedPrefere
|
||||
public GBPrefs getGBPrefs() {
|
||||
return GBApplication.getGBPrefs();
|
||||
}
|
||||
|
||||
public GBDevice getGBDevice() {
|
||||
return mGBDevice;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,99 @@
|
||||
package nodomain.freeyourgadget.gadgetbridge.service.devices.pebble;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.UUID;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
|
||||
import nodomain.freeyourgadget.gadgetbridge.database.DBHandler;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.SampleProvider;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.pebble.HealthSampleProvider;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.ActivityKind;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.GB;
|
||||
|
||||
class DatalogSessionHealthOverlayData extends DatalogSession {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(DatalogSessionHealthOverlayData.class);
|
||||
|
||||
public DatalogSessionHealthOverlayData(byte id, UUID uuid, int tag, byte item_type, short item_size) {
|
||||
super(id, uuid, tag, item_type, item_size);
|
||||
taginfo = "(health - overlay data " + tag + " )";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handleMessage(ByteBuffer datalogMessage, int length) {
|
||||
LOG.info("DATALOG " + taginfo + GB.hexdump(datalogMessage.array(), datalogMessage.position(), length));
|
||||
|
||||
int initialPosition = datalogMessage.position();
|
||||
int beginOfRecordPosition;
|
||||
short recordVersion; //probably
|
||||
short recordType; //probably: 1=sleep, 2=deep sleep, 5=??run??ignored for now
|
||||
|
||||
if (0 != (length % itemSize))
|
||||
return false;//malformed message?
|
||||
|
||||
int recordCount = length / itemSize;
|
||||
OverlayRecord[] overlayRecords = new OverlayRecord[recordCount];
|
||||
|
||||
for (int recordIdx = 0; recordIdx < recordCount; recordIdx++) {
|
||||
beginOfRecordPosition = initialPosition + recordIdx * itemSize;
|
||||
datalogMessage.position(beginOfRecordPosition);//we may not consume all the bytes of a record
|
||||
recordVersion = datalogMessage.getShort();
|
||||
if ((recordVersion != 1) && (recordVersion != 3))
|
||||
return false;//we don't know how to deal with the data TODO: this is not ideal because we will get the same message again and again since we NACK it
|
||||
|
||||
datalogMessage.getShort();//throwaway, unknown
|
||||
recordType = datalogMessage.getShort();
|
||||
|
||||
overlayRecords[recordIdx] = new OverlayRecord(recordType, datalogMessage.getInt(), datalogMessage.getInt(), datalogMessage.getInt());
|
||||
}
|
||||
|
||||
return store(overlayRecords);//NACK if we cannot store the data yet, the watch will send the overlay records again.
|
||||
}
|
||||
|
||||
private boolean store(OverlayRecord[] overlayRecords) {
|
||||
DBHandler dbHandler = null;
|
||||
SampleProvider sampleProvider = new HealthSampleProvider();
|
||||
try {
|
||||
dbHandler = GBApplication.acquireDB();
|
||||
int latestTimestamp = dbHandler.fetchLatestTimestamp(sampleProvider);
|
||||
for (OverlayRecord overlayRecord : overlayRecords) {
|
||||
if (latestTimestamp < (overlayRecord.timestampStart + overlayRecord.durationSeconds))
|
||||
return false;
|
||||
switch (overlayRecord.type) {
|
||||
case 1:
|
||||
dbHandler.changeStoredSamplesType(overlayRecord.timestampStart, (overlayRecord.timestampStart + overlayRecord.durationSeconds), sampleProvider.toRawActivityKind(ActivityKind.TYPE_ACTIVITY), sampleProvider.toRawActivityKind(ActivityKind.TYPE_LIGHT_SLEEP), sampleProvider);
|
||||
break;
|
||||
case 2:
|
||||
dbHandler.changeStoredSamplesType(overlayRecord.timestampStart, (overlayRecord.timestampStart + overlayRecord.durationSeconds), sampleProvider.toRawActivityKind(ActivityKind.TYPE_DEEP_SLEEP), sampleProvider);
|
||||
break;
|
||||
default:
|
||||
//TODO: other values refer to unknown activity types.
|
||||
}
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
LOG.debug(ex.getMessage());
|
||||
} finally {
|
||||
if (dbHandler != null) {
|
||||
dbHandler.release();
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private class OverlayRecord {
|
||||
int type; //1=sleep, 2=deep sleep
|
||||
int offsetUTC; //probably
|
||||
int timestampStart;
|
||||
int durationSeconds;
|
||||
|
||||
public OverlayRecord(int type, int offsetUTC, int timestampStart, int durationSeconds) {
|
||||
this.type = type;
|
||||
this.offsetUTC = offsetUTC;
|
||||
this.timestampStart = timestampStart;
|
||||
this.durationSeconds = durationSeconds;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,7 +1,5 @@
|
||||
package nodomain.freeyourgadget.gadgetbridge.service.devices.pebble;
|
||||
|
||||
import android.widget.Toast;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@ -27,71 +25,6 @@ class DatalogSessionHealthSleep extends DatalogSession {
|
||||
@Override
|
||||
public boolean handleMessage(ByteBuffer datalogMessage, int length) {
|
||||
LOG.info("DATALOG " + taginfo + GB.hexdump(datalogMessage.array(), datalogMessage.position(), length));
|
||||
switch (this.tag) {
|
||||
case 83:
|
||||
return handleMessage83(datalogMessage, length);
|
||||
case 84:
|
||||
return handleMessage84(datalogMessage, length);
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean handleMessage84(ByteBuffer datalogMessage, int length) {
|
||||
int initialPosition = datalogMessage.position();
|
||||
int beginOfRecordPosition;
|
||||
short recordVersion; //probably
|
||||
short recordType; //probably: 1=sleep, 2=deep sleep
|
||||
|
||||
if (0 != (length % itemSize))
|
||||
return false;//malformed message?
|
||||
|
||||
int recordCount = length / itemSize;
|
||||
SleepRecord84[] sleepRecords = new SleepRecord84[recordCount];
|
||||
|
||||
for (int recordIdx = 0; recordIdx < recordCount; recordIdx++) {
|
||||
beginOfRecordPosition = initialPosition + recordIdx * itemSize;
|
||||
datalogMessage.position(beginOfRecordPosition);//we may not consume all the bytes of a record
|
||||
recordVersion = datalogMessage.getShort();
|
||||
if (recordVersion != 1)
|
||||
return false;//we don't know how to deal with the data TODO: this is not ideal because we will get the same message again and again since we NACK it
|
||||
|
||||
datalogMessage.getShort();//throwaway, unknown
|
||||
recordType = datalogMessage.getShort();
|
||||
|
||||
sleepRecords[recordIdx] = new SleepRecord84(recordType, datalogMessage.getInt(), datalogMessage.getInt(), datalogMessage.getInt());
|
||||
}
|
||||
|
||||
return store84(sleepRecords);//NACK if we cannot store the data yet, the watch will send the sleep records again.
|
||||
}
|
||||
|
||||
private boolean store84(SleepRecord84[] sleepRecords) {
|
||||
DBHandler dbHandler = null;
|
||||
SampleProvider sampleProvider = new HealthSampleProvider();
|
||||
try {
|
||||
dbHandler = GBApplication.acquireDB();
|
||||
int latestTimestamp = dbHandler.fetchLatestTimestamp(sampleProvider);
|
||||
for (SleepRecord84 sleepRecord : sleepRecords) {
|
||||
if (latestTimestamp < (sleepRecord.timestampStart + sleepRecord.durationSeconds))
|
||||
return false;
|
||||
if (sleepRecord.type == 2) {
|
||||
dbHandler.changeStoredSamplesType(sleepRecord.timestampStart, (sleepRecord.timestampStart + sleepRecord.durationSeconds), sampleProvider.toRawActivityKind(ActivityKind.TYPE_DEEP_SLEEP), sampleProvider);
|
||||
} else {
|
||||
dbHandler.changeStoredSamplesType(sleepRecord.timestampStart, (sleepRecord.timestampStart + sleepRecord.durationSeconds), sampleProvider.toRawActivityKind(ActivityKind.TYPE_ACTIVITY), sampleProvider.toRawActivityKind(ActivityKind.TYPE_LIGHT_SLEEP), sampleProvider);
|
||||
}
|
||||
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
LOG.debug(ex.getMessage());
|
||||
} finally {
|
||||
if (dbHandler != null) {
|
||||
dbHandler.release();
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean handleMessage83(ByteBuffer datalogMessage, int length) {
|
||||
int initialPosition = datalogMessage.position();
|
||||
int beginOfRecordPosition;
|
||||
short recordVersion; //probably
|
||||
@ -100,7 +33,7 @@ class DatalogSessionHealthSleep extends DatalogSession {
|
||||
return false;//malformed message?
|
||||
|
||||
int recordCount = length / itemSize;
|
||||
SleepRecord83[] sleepRecords = new SleepRecord83[recordCount];
|
||||
SleepRecord[] sleepRecords = new SleepRecord[recordCount];
|
||||
|
||||
for (int recordIdx = 0; recordIdx < recordCount; recordIdx++) {
|
||||
beginOfRecordPosition = initialPosition + recordIdx * itemSize;
|
||||
@ -109,23 +42,22 @@ class DatalogSessionHealthSleep extends DatalogSession {
|
||||
if (recordVersion != 1)
|
||||
return false;//we don't know how to deal with the data TODO: this is not ideal because we will get the same message again and again since we NACK it
|
||||
|
||||
sleepRecords[recordIdx] = new SleepRecord83(datalogMessage.getInt(),
|
||||
sleepRecords[recordIdx] = new SleepRecord(datalogMessage.getInt(),
|
||||
datalogMessage.getInt(),
|
||||
datalogMessage.getInt(),
|
||||
datalogMessage.getInt());
|
||||
}
|
||||
|
||||
return store83(sleepRecords);//NACK if we cannot store the data yet, the watch will send the sleep records again.
|
||||
return store(sleepRecords);//NACK if we cannot store the data yet, the watch will send the sleep records again.
|
||||
}
|
||||
|
||||
private boolean store83(SleepRecord83[] sleepRecords) {
|
||||
private boolean store(SleepRecord[] sleepRecords) {
|
||||
DBHandler dbHandler = null;
|
||||
SampleProvider sampleProvider = new HealthSampleProvider();
|
||||
GB.toast("Deep sleep is supported only from firmware 3.11 onwards.", Toast.LENGTH_LONG, GB.INFO);
|
||||
try {
|
||||
dbHandler = GBApplication.acquireDB();
|
||||
int latestTimestamp = dbHandler.fetchLatestTimestamp(sampleProvider);
|
||||
for (SleepRecord83 sleepRecord : sleepRecords) {
|
||||
for (SleepRecord sleepRecord : sleepRecords) {
|
||||
if (latestTimestamp < sleepRecord.bedTimeEnd)
|
||||
return false;
|
||||
dbHandler.changeStoredSamplesType(sleepRecord.bedTimeStart, sleepRecord.bedTimeEnd, sampleProvider.toRawActivityKind(ActivityKind.TYPE_ACTIVITY), sampleProvider.toRawActivityKind(ActivityKind.TYPE_LIGHT_SLEEP), sampleProvider);
|
||||
@ -140,13 +72,13 @@ class DatalogSessionHealthSleep extends DatalogSession {
|
||||
return true;
|
||||
}
|
||||
|
||||
private class SleepRecord83 {
|
||||
private class SleepRecord {
|
||||
int offsetUTC; //probably
|
||||
int bedTimeStart;
|
||||
int bedTimeEnd;
|
||||
int deepSleepSeconds;
|
||||
|
||||
public SleepRecord83(int offsetUTC, int bedTimeStart, int bedTimeEnd, int deepSleepSeconds) {
|
||||
public SleepRecord(int offsetUTC, int bedTimeStart, int bedTimeEnd, int deepSleepSeconds) {
|
||||
this.offsetUTC = offsetUTC;
|
||||
this.bedTimeStart = bedTimeStart;
|
||||
this.bedTimeEnd = bedTimeEnd;
|
||||
@ -154,17 +86,4 @@ class DatalogSessionHealthSleep extends DatalogSession {
|
||||
}
|
||||
}
|
||||
|
||||
private class SleepRecord84 {
|
||||
int type; //1=sleep, 2=deep sleep
|
||||
int offsetUTC; //probably
|
||||
int timestampStart;
|
||||
int durationSeconds;
|
||||
|
||||
public SleepRecord84(int type, int offsetUTC, int timestampStart, int durationSeconds) {
|
||||
this.type = type;
|
||||
this.offsetUTC = offsetUTC;
|
||||
this.timestampStart = timestampStart;
|
||||
this.durationSeconds = durationSeconds;
|
||||
}
|
||||
}
|
||||
}
|
@ -2,7 +2,6 @@ package nodomain.freeyourgadget.gadgetbridge.service.devices.pebble;
|
||||
|
||||
import android.bluetooth.BluetoothAdapter;
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
import android.bluetooth.BluetoothServerSocket;
|
||||
import android.bluetooth.BluetoothSocket;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
@ -48,9 +47,6 @@ import nodomain.freeyourgadget.gadgetbridge.util.Prefs;
|
||||
public class PebbleIoThread extends GBDeviceIoThread {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(PebbleIoThread.class);
|
||||
|
||||
private static final UUID PEBBLE_UUID_RECONNECT = UUID.fromString("00000000-deca-fade-deca-deafdecacafe");
|
||||
private static final UUID PEBBLE_UUID_RECONNECT3X = UUID.fromString("a924496e-cc7c-4dff-8a9f-9a76cc2e9d50");
|
||||
|
||||
public static final String PEBBLEKIT_ACTION_PEBBLE_CONNECTED = "com.getpebble.action.PEBBLE_CONNECTED";
|
||||
public static final String PEBBLEKIT_ACTION_PEBBLE_DISCONNECTED = "com.getpebble.action.PEBBLE_DISCONNECTED";
|
||||
public static final String PEBBLEKIT_ACTION_APP_ACK = "com.getpebble.action.app.ACK";
|
||||
@ -71,7 +67,6 @@ public class PebbleIoThread extends GBDeviceIoThread {
|
||||
private boolean mIsTCP = false;
|
||||
private BluetoothAdapter mBtAdapter = null;
|
||||
private BluetoothSocket mBtSocket = null;
|
||||
private BluetoothServerSocket mBtServerSocket = null;
|
||||
private Socket mTCPSocket = null; // for emulator
|
||||
private InputStream mInStream = null;
|
||||
private OutputStream mOutStream = null;
|
||||
@ -365,7 +360,7 @@ public class PebbleIoThread extends GBDeviceIoThread {
|
||||
LOG.info(e.getMessage());
|
||||
mIsConnected = false;
|
||||
int reconnectAttempts = prefs.getInt("pebble_reconnect_attempts", 10);
|
||||
if (GBApplication.getGBPrefs().getAutoReconnect() && reconnectAttempts > 0) {
|
||||
if (!mQuit && GBApplication.getGBPrefs().getAutoReconnect() && reconnectAttempts > 0) {
|
||||
gbDevice.setState(GBDevice.State.CONNECTING);
|
||||
gbDevice.sendDeviceUpdateIntent(getContext());
|
||||
int delaySeconds = 1;
|
||||
@ -383,33 +378,10 @@ public class PebbleIoThread extends GBDeviceIoThread {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!mIsConnected && !mQuit) {
|
||||
try {
|
||||
gbDevice.setState(GBDevice.State.WAITING_FOR_RECONNECT);
|
||||
gbDevice.sendDeviceUpdateIntent(getContext());
|
||||
UUID reconnectUUID = mPebbleProtocol.isFw3x ? PEBBLE_UUID_RECONNECT3X : PEBBLE_UUID_RECONNECT;
|
||||
mBtServerSocket = mBtAdapter.listenUsingRfcommWithServiceRecord("PebbleReconnectListener", reconnectUUID);
|
||||
mBtSocket = mBtServerSocket.accept();
|
||||
LOG.info("incoming connection on reconnect uuid (" + reconnectUUID + "), will connect actively");
|
||||
mBtSocket.close();
|
||||
mIsConnected = connect(gbDevice.getAddress());
|
||||
} catch (IOException ex) {
|
||||
ex.printStackTrace();
|
||||
LOG.info("error while reconnecting");
|
||||
} finally {
|
||||
try {
|
||||
if (mBtServerSocket != null) {
|
||||
mBtServerSocket.close();
|
||||
mBtServerSocket = null;
|
||||
}
|
||||
} catch (IOException ignore) {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!mIsConnected) {
|
||||
mBtSocket = null;
|
||||
LOG.info("Bluetooth socket closed, will quit IO Thread");
|
||||
mQuit = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -421,10 +393,16 @@ public class PebbleIoThread extends GBDeviceIoThread {
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
enablePebbleKitReceiver(false);
|
||||
mBtSocket = null;
|
||||
}
|
||||
|
||||
enablePebbleKitReceiver(false);
|
||||
|
||||
if (mQuit) {
|
||||
gbDevice.setState(GBDevice.State.NOT_CONNECTED);
|
||||
} else {
|
||||
gbDevice.setState(GBDevice.State.WAITING_FOR_RECONNECT);
|
||||
}
|
||||
gbDevice.sendDeviceUpdateIntent(getContext());
|
||||
}
|
||||
|
||||
@ -700,13 +678,6 @@ public class PebbleIoThread extends GBDeviceIoThread {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
if (mBtServerSocket != null) {
|
||||
try {
|
||||
mBtServerSocket.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
if (mTCPSocket != null) {
|
||||
try {
|
||||
mTCPSocket.close();
|
||||
|
@ -1883,8 +1883,10 @@ public class PebbleProtocol extends GBDeviceProtocol {
|
||||
if (!mDatalogSessions.containsKey(id)) {
|
||||
if (uuid.equals(UUID_ZERO) && log_tag == 81) {
|
||||
mDatalogSessions.put(id, new DatalogSessionHealthSteps(id, uuid, log_tag, item_type, item_size));
|
||||
} else if (uuid.equals(UUID_ZERO) && (log_tag == 83 || log_tag == 84)) {
|
||||
} else if (uuid.equals(UUID_ZERO) && log_tag == 83) {
|
||||
mDatalogSessions.put(id, new DatalogSessionHealthSleep(id, uuid, log_tag, item_type, item_size));
|
||||
} else if (uuid.equals(UUID_ZERO) && log_tag == 84) {
|
||||
mDatalogSessions.put(id, new DatalogSessionHealthOverlayData(id, uuid, log_tag, item_type, item_size));
|
||||
} else {
|
||||
mDatalogSessions.put(id, new DatalogSession(id, uuid, log_tag, item_type, item_size));
|
||||
}
|
||||
|
@ -78,6 +78,7 @@ public class PebbleSupport extends AbstractSerialDeviceSupport {
|
||||
private boolean reconnect() {
|
||||
if (!isConnected() && useAutoConnect()) {
|
||||
if (getDevice().getState() == GBDevice.State.WAITING_FOR_RECONNECT) {
|
||||
gbDeviceIOThread.quit();
|
||||
gbDeviceIOThread.interrupt();
|
||||
gbDeviceIOThread = null;
|
||||
if (!connect()) {
|
||||
|
@ -6,6 +6,9 @@
|
||||
<item
|
||||
android:id="@+id/appmanager_app_delete"
|
||||
android:title="@string/appmananger_app_delete"/>
|
||||
<item
|
||||
android:id="@+id/appmanager_app_delete_cache"
|
||||
android:title="@string/appmananger_app_delete_cache"/>
|
||||
<item
|
||||
android:id="@+id/appmanager_health_activate"
|
||||
android:title="@string/appmanager_health_activate"/>
|
||||
|
@ -14,6 +14,7 @@
|
||||
<!--Strings related to AppManager-->
|
||||
<string name="title_activity_appmanager">App Manager</string>
|
||||
<string name="appmananger_app_delete">Löschen</string>
|
||||
<string name="appmananger_app_delete_cache">Löschen und aus dem Zwischenspeicher entfernen</string>
|
||||
<!--Strings related to AppBlacklist-->
|
||||
<string name="title_activity_appblacklist">Sperre für Benachrichtigungen</string>
|
||||
<!--Strings related to FwAppInstaller-->
|
||||
@ -44,6 +45,8 @@
|
||||
<string name="pref_summary_notifications_pebblemsg">Unterstützung für Anwendungen, die Benachrichtigungen per Intent an die Pebble schicken. Kann für Conversations verwendet werden.</string>
|
||||
<string name="pref_title_notifications_generic">Andere Benachrichtigungen</string>
|
||||
<string name="pref_title_whenscreenon">… auch wenn der Bildschirm an ist</string>
|
||||
<string name="pref_title_notification_filter">Bitte nicht stören</string>
|
||||
<string name="pref_summary_notification_filter">Stoppe unerwünschte Nachrichten, wenn im \"Nicht Stören\"-Modus</string>
|
||||
<string name="always">immer</string>
|
||||
<string name="when_screen_off">wenn der Bildschirm aus ist</string>
|
||||
<string name="never">niemals</string>
|
||||
@ -202,8 +205,9 @@
|
||||
<string name="pref_title_keep_data_on_device">Aktivitätsdaten auf dem Gerät lassen</string>
|
||||
<string name="miband_fwinstaller_incompatible_version">Inkompatible Firmware</string>
|
||||
<string name="fwinstaller_firmware_not_compatible_to_device">Diese Firmware ist nicht mit dem Gerät kompatibel</string>
|
||||
<string name="miband_prefs_reserve_alarm_calendar">Wecker für zukünftige Ereignisse vormerken</string>
|
||||
<string name="miband_prefs_hr_sleep_detection">Verwende den Herzfrequenzsensor um die Schlaferkennung zu verbessern</string>
|
||||
<string name="waiting_for_reconnect">warte auf eingehende Verbindung</string>
|
||||
<string name="waiting_for_reconnect">warte auf Verbindung</string>
|
||||
<string name="appmananger_app_reinstall">Erneut installieren</string>
|
||||
<string name="activity_prefs_about_you">Über Dich</string>
|
||||
<string name="activity_prefs_year_birth">Geburtsjahr</string>
|
||||
@ -214,6 +218,7 @@
|
||||
<string name="appmanager_health_deactivate">deaktivieren</string>
|
||||
<string name="authenticating">Authentifiziere</string>
|
||||
<string name="authentication_required">Authentifizierung erforderlich</string>
|
||||
<string name="app_configure">Konfigurieren</string>
|
||||
<string name="appwidget_text">Zzz</string>
|
||||
<string name="add_widget">Widget hinzufügen</string>
|
||||
<string name="activity_prefs_sleep_duration">Gewünschte Schlafdauer in Stunden</string>
|
||||
|
@ -69,8 +69,6 @@
|
||||
<string name="this_is_a_test_notification_from_gadgetbridge">Notificación de prueba desde Gadgetbridge</string>
|
||||
<string name="bluetooth_is_not_supported_">Bluetooth no está soportado.</string>
|
||||
<string name="bluetooth_is_disabled_">Bluetooth está desactivado.</string>
|
||||
<string name="tap_connected_device_for_app_mananger">pulsa el dispositivo conectado para el Gestor de App</string>
|
||||
<string name="tap_a_device_to_connect">pulsa un dispositivo para conectar</string>
|
||||
<string name="cannot_connect_bt_address_invalid_">No se puede conectar. ¿Dirección BT incorrecta?</string>
|
||||
<string name="gadgetbridge_running">Gadgetbridge funcionando</string>
|
||||
<string name="installing_binary_d_d">instalando binario %1$d/%2$d</string>
|
||||
@ -101,13 +99,11 @@
|
||||
<string name="miband_pairing_using_dummy_userdata">No se han proporcionado datos de usuario válidos, se usarán datos de usuario por defecto.</string>
|
||||
<string name="miband_pairing_tap_hint">Cuando tu MiBand vibre y parpadee, púlsala repetidas veces.</string>
|
||||
<string name="appinstaller_install">Instalar</string>
|
||||
<string name="discovery_connected_devices_hint">Haz visible tu dispositivo. No es probable que se detecten los dispositivos que ya están conectados.</string>
|
||||
<string name="discovery_note">Nota:</string>
|
||||
<string name="candidate_item_device_image">Imagen del dispositivo</string>
|
||||
<string name="miband_prefs_alias">Nombre/Apodo</string>
|
||||
<string name="pref_header_vibration_count">Número de vibraciones</string>
|
||||
<string name="title_activity_sleepmonitor">Monitor de sueño</string>
|
||||
<string name="pref_write_logfiles">Guardar logs</string>
|
||||
<string name="initializing">iniciando</string>
|
||||
<string name="busy_task_fetch_activity_data">Recuperando datos de actividad</string>
|
||||
<string name="sleep_activity_date_range">Desde %1$s a %2$s</string>
|
||||
@ -178,9 +174,9 @@
|
||||
<string name="chart_steps">Pasos</string>
|
||||
<string name="liveactivity_live_activity">Actividad</string>
|
||||
<string name="weeksteps_today_steps_description">Pasos hoy, objetivo: %1$s</string>
|
||||
<string name="pref_title_dont_ack_transfer">No confirmar transferencia</string>
|
||||
<string name="pref_summary_dont_ack_transfers">Si los datos no son marcados como descargados, no serán borrados de tu MiBand. Útil si Gadgetbridge se usa conjuntamente con otras apps.</string>
|
||||
<string name="pref_summary_keep_data_on_device">Mantendrá los datos de actividad en la MiBand incluso después de la sincronización. Útil si GB se usa junto con otras apps.</string>
|
||||
<string name="pref_title_dont_ack_transfer">No confirmar transferencia</string>
|
||||
<string name="live_activity_steps_history">Historial de pasos</string>
|
||||
<string name="live_activity_current_steps_per_minute">Pasos/min actuales</string>
|
||||
<string name="live_activity_total_steps">Pasos totales</string>
|
||||
|
@ -178,9 +178,9 @@
|
||||
<string name="chart_steps">Pas</string>
|
||||
<string name="liveactivity_live_activity">Activité en direct</string>
|
||||
<string name="weeksteps_today_steps_description">Nombre de pas aujourd\'hui, objectif: %1$s</string>
|
||||
<string name="pref_title_dont_ack_transfer">Ne pas confirmer le transfert de données d\'activités</string>
|
||||
<string name="pref_summary_dont_ack_transfers">Les données d\'activités ne seront pas effacées du bracelet si elles ne sont pas confirmées. Utile si GB est utilisé avec d\'autres applications.</string>
|
||||
<string name="pref_summary_keep_data_on_device">Les données d\'activités seront conservées sur le Mi Band après la synchronisation. Utile si GB est utilisé avec d\'autres applications.</string>
|
||||
<string name="pref_title_dont_ack_transfer">Ne pas confirmer le transfert de données d\'activités</string>
|
||||
<string name="live_activity_steps_history">Historique de pas</string>
|
||||
<string name="live_activity_current_steps_per_minute">Pas/minute actuel</string>
|
||||
<string name="live_activity_total_steps">Nombre total de pas</string>
|
||||
|
@ -70,8 +70,6 @@
|
||||
<string name="this_is_a_test_notification_from_gadgetbridge">Notifica di prova creata da Gadgetbridge</string>
|
||||
<string name="bluetooth_is_not_supported_">Bluetooth non supportato.</string>
|
||||
<string name="bluetooth_is_disabled_">Bluetooth disabilitato.</string>
|
||||
<string name="tap_connected_device_for_app_mananger">tocca il dispositivo connesso per gestire le App</string>
|
||||
<string name="tap_a_device_to_connect">tocca il dispositivo da connettere</string>
|
||||
<string name="cannot_connect_bt_address_invalid_">Impossibile connettersi. Indirizzo BT non valido?</string>
|
||||
<string name="gadgetbridge_running">Gadgetbridge in esecuzione</string>
|
||||
<string name="installing_binary_d_d">installazione del binario %1$d/%2$d</string>
|
||||
@ -102,13 +100,11 @@
|
||||
<string name="miband_pairing_using_dummy_userdata">Dati dell\'utente non inseriti, vengono usati dati d\'esempio.</string>
|
||||
<string name="miband_pairing_tap_hint">Quando la Mi Band vibra e lampeggia, dalle qualche leggero colpetto.</string>
|
||||
<string name="appinstaller_install">Installa</string>
|
||||
<string name="discovery_connected_devices_hint">Imposta il tuo dispositivo perchè sia rilevabile. I dispositivi attualmente connessi non saranno probabilmente rilevati.</string>
|
||||
<string name="discovery_note">Nota:</string>
|
||||
<string name="candidate_item_device_image">Immagine dispositivo</string>
|
||||
<string name="miband_prefs_alias">Nome / Soprannome</string>
|
||||
<string name="pref_header_vibration_count">Numero vibrazioni</string>
|
||||
<string name="title_activity_sleepmonitor">Monitoraggio del sonno</string>
|
||||
<string name="pref_write_logfiles">Salva il log su file</string>
|
||||
<string name="initializing">inizializzazione in corso</string>
|
||||
<string name="busy_task_fetch_activity_data">Recupero dati attività</string>
|
||||
<string name="sleep_activity_date_range">Da %1$s a %2$s</string>
|
||||
@ -179,9 +175,9 @@
|
||||
<string name="chart_steps">Passi</string>
|
||||
<string name="liveactivity_live_activity">Attività in tempo reale</string>
|
||||
<string name="weeksteps_today_steps_description">Passi di oggi, traguardo: %1$s</string>
|
||||
<string name="pref_title_dont_ack_transfer">Non confermare il trasferimento dati</string>
|
||||
<string name="pref_summary_dont_ack_transfers">Se il trasferimento non viene confermato, i dati rimangono memorizzati sulla Mi Band. Utile se GB è usato insieme ad altre app.</string>
|
||||
<string name="pref_summary_keep_data_on_device">Conserva i dati delle attività sulla Mi Band anche dopo averli sincronizzati. Utile se GB è usato insieme ad altre app.</string>
|
||||
<string name="pref_title_dont_ack_transfer">Non confermare il trasferimento dati</string>
|
||||
<string name="live_activity_steps_history">Storico dei passi</string>
|
||||
<string name="live_activity_current_steps_per_minute">Passi/minuto</string>
|
||||
<string name="live_activity_total_steps">Passi totali</string>
|
||||
|
@ -14,6 +14,7 @@
|
||||
<!--Strings related to AppManager-->
|
||||
<string name="title_activity_appmanager">アプリ管理画面</string>
|
||||
<string name="appmananger_app_delete">削除</string>
|
||||
<string name="appmananger_app_delete_cache">キャッシュから削除</string>
|
||||
<!--Strings related to AppBlacklist-->
|
||||
<string name="title_activity_appblacklist">ステータス通知ブラックリスト</string>
|
||||
<!--Strings related to FwAppInstaller-->
|
||||
@ -44,6 +45,8 @@
|
||||
<string name="pref_summary_notifications_pebblemsg">インテント経由でPebbleに通知を送信するアプリケーションをサポートします。Conversationsに使用することができます。</string>
|
||||
<string name="pref_title_notifications_generic">一般ステータス通知対応</string>
|
||||
<string name="pref_title_whenscreenon">… スクリーンがオンのときにも</string>
|
||||
<string name="pref_title_notification_filter">サイレント</string>
|
||||
<string name="pref_summary_notification_filter">サイレントモードに基づいて、送信される不要な通知を停止します。</string>
|
||||
<string name="always">いつも</string>
|
||||
<string name="when_screen_off">スクリーンがオフのとき</string>
|
||||
<string name="never">なし</string>
|
||||
|
@ -181,9 +181,9 @@
|
||||
<string name="chart_steps">걸음 수</string>
|
||||
<string name="liveactivity_live_activity">실시간 활동</string>
|
||||
<string name="weeksteps_today_steps_description">오늘 걸음 수, 목표: %1$s</string>
|
||||
<string name="pref_title_dont_ack_transfer">활동 데이터 전송을 확인하지 않음</string>
|
||||
<string name="pref_summary_dont_ack_transfers">만약 활동 데이터가 밴드에 확인되지 않았다면, 지워지지 않을 것입니다. 가젯브릿지가 다른 앱들과 같이 사용될 때 유용합니다.</string>
|
||||
<string name="pref_summary_keep_data_on_device">동기화 이후에도 Mi Band의 활동 데이터가 유지될 것입니다. 가젯브릿지가 다른 앱들과 같이 사용될 때 유용합니다.</string>
|
||||
<string name="pref_title_dont_ack_transfer">활동 데이터 전송을 확인하지 않음</string>
|
||||
<string name="live_activity_steps_history">걸음 수 기록</string>
|
||||
<string name="live_activity_current_steps_per_minute">현재의 분당 걸음 수</string>
|
||||
<string name="live_activity_total_steps">전체 걸음 수</string>
|
||||
@ -224,4 +224,5 @@
|
||||
<string name="updatefirmwareoperation_firmware_not_sent">펌웨어가 전송되지 않음</string>
|
||||
<string name="charts_legend_heartrate">심박수</string>
|
||||
<string name="live_activity_heart_rate">심박수</string>
|
||||
<string name="pref_title_general_autocreonnect">자동으로 재연결</string>
|
||||
</resources>
|
||||
|
@ -67,8 +67,6 @@
|
||||
<string name="this_is_a_test_notification_from_gadgetbridge">To jest testowe powiadomienie z Gadgetbridge</string>
|
||||
<string name="bluetooth_is_not_supported_">Bluetooth nie jest obsługiwane</string>
|
||||
<string name="bluetooth_is_disabled_">Bluetooth jest wyłączone</string>
|
||||
<string name="tap_connected_device_for_app_mananger">Kliknij podłączone urządzenia dla zarządzania aplikacjami</string>
|
||||
<string name="tap_a_device_to_connect">kliknij urządzenie by połączyć</string>
|
||||
<string name="cannot_connect_bt_address_invalid_">Nie można połączyć. Adres BT nieprawidłowy?</string>
|
||||
<string name="gadgetbridge_running">Gadgetbridge działa</string>
|
||||
<string name="installing_binary_d_d">Instalowanie binarki %1$d/%2$d</string>
|
||||
@ -99,13 +97,11 @@
|
||||
<string name="miband_pairing_using_dummy_userdata">Brak prawidłowych danych użytkownika, używam danych zastępczych na ten moment.</string>
|
||||
<string name="miband_pairing_tap_hint">Gdy twój Mi Band wibruje i błyska, stuknij go kilka razy pod rząd.</string>
|
||||
<string name="appinstaller_install">instaluj</string>
|
||||
<string name="discovery_connected_devices_hint">Uwidocznij swoje urządzenie. Aktualnie połączone urządzenia prawdopodobnie nie będą znalezione.</string>
|
||||
<string name="discovery_note">Uwaga</string>
|
||||
<string name="candidate_item_device_image">Obraz urządzenia</string>
|
||||
<string name="miband_prefs_alias">Nazwisko/Pseudonim</string>
|
||||
<string name="pref_header_vibration_count">Liczba wibracji</string>
|
||||
<string name="title_activity_sleepmonitor">Monitor snu</string>
|
||||
<string name="pref_write_logfiles">Zapisuj logi</string>
|
||||
<string name="initializing">Uruchamianie</string>
|
||||
<string name="busy_task_fetch_activity_data">Pobieranie danych aktywności</string>
|
||||
<string name="sleep_activity_date_range">Od %1$s do %2$s</string>
|
||||
@ -176,9 +172,9 @@
|
||||
<string name="chart_steps">Kroki</string>
|
||||
<string name="liveactivity_live_activity">Ostatnia aktywność</string>
|
||||
<string name="weeksteps_today_steps_description">Kroków dziś, cel: %1$s</string>
|
||||
<string name="pref_title_dont_ack_transfer">Nie wysyłaj danych aktywności</string>
|
||||
<string name="pref_summary_dont_ack_transfers">Gdy dane aktywności nie są przesłane na opaskę, wtedy nie będą usuwane. Przydatne gdy Gadgetbridge jest używany wraz z innymi aplikacjami</string>
|
||||
<string name="pref_summary_keep_data_on_device">Dane aktywności będą zachowane na Mi Band nawet po synchronizacji. Przydatne gdy Gadgetbridge jest używany z innymi aplikacjami.</string>
|
||||
<string name="pref_title_dont_ack_transfer">Nie wysyłaj danych aktywności</string>
|
||||
<string name="live_activity_steps_history">Historia kroków</string>
|
||||
<string name="live_activity_current_steps_per_minute">Aktualnie kroków/min</string>
|
||||
<string name="live_activity_total_steps">Kroków łącznie</string>
|
||||
|
@ -68,8 +68,6 @@
|
||||
<string name="this_is_a_test_notification_from_gadgetbridge">Это тестовое уведомление от Gadgetbridge</string>
|
||||
<string name="bluetooth_is_not_supported_">Bluetooth не поддерживается.</string>
|
||||
<string name="bluetooth_is_disabled_">Bluetooth отключён.</string>
|
||||
<string name="tap_connected_device_for_app_mananger">нажмите на подключённое устройство для App Manager</string>
|
||||
<string name="tap_a_device_to_connect">нажмите на устройство для соединения</string>
|
||||
<string name="cannot_connect_bt_address_invalid_">Не удалось соединиться. Неверен адрес BT?</string>
|
||||
<string name="gadgetbridge_running">Gadgetbridge запущен</string>
|
||||
<string name="installing_binary_d_d">установки бинарного файла %1$d/%2$d</string>
|
||||
@ -100,13 +98,11 @@
|
||||
<string name="miband_pairing_using_dummy_userdata">Не предоставлено действительных данных пользователя. Используются данные по-умолчанию.</string>
|
||||
<string name="miband_pairing_tap_hint">Когда ваш Mi Band вибрирует и мигает, постучите по нему несколько раз.</string>
|
||||
<string name="appinstaller_install">Установить</string>
|
||||
<string name="discovery_connected_devices_hint">Подключённые в настоящее время устройства, скорее всего, не будут обнаружены.</string>
|
||||
<string name="discovery_note">Заметка:</string>
|
||||
<string name="candidate_item_device_image">Изображение устройства</string>
|
||||
<string name="miband_prefs_alias">Имя/псевдоним</string>
|
||||
<string name="pref_header_vibration_count">Количество вибраций</string>
|
||||
<string name="title_activity_sleepmonitor">Анализ сна</string>
|
||||
<string name="pref_write_logfiles">Записывать файлы журнала</string>
|
||||
<string name="initializing">Инициализация</string>
|
||||
<string name="busy_task_fetch_activity_data">Получение данных активности</string>
|
||||
<string name="sleep_activity_date_range">От %1$s до %2$s</string>
|
||||
@ -177,9 +173,9 @@
|
||||
<string name="chart_steps">Шаги</string>
|
||||
<string name="liveactivity_live_activity">Жизненная активность</string>
|
||||
<string name="weeksteps_today_steps_description">Шагов сегодня, цель: %1$s</string>
|
||||
<string name="pref_title_dont_ack_transfer">Не передавать данные об активности</string>
|
||||
<string name="pref_summary_dont_ack_transfers">Если данные об активности не будут переданы на устройство, оно не будет очищено. Полезно, если GB используется с другими приложениями.</string>
|
||||
<string name="pref_summary_keep_data_on_device">Хранить данные о деятельности на Mi Band, даже после синхронизации. Полезно, если Mi Band используется совместно с другими приложениями.</string>
|
||||
<string name="pref_title_dont_ack_transfer">Не передавать данные об активности</string>
|
||||
<string name="live_activity_steps_history">История шагов</string>
|
||||
<string name="live_activity_current_steps_per_minute">Текущие шаги в минуту</string>
|
||||
<string name="live_activity_total_steps">Всего шагов</string>
|
||||
|
@ -31,6 +31,9 @@
|
||||
<string name="pref_header_datetime">Дата і час</string>
|
||||
<string name="pref_title_datetime_syctimeonconnect">Синхронізувати час під час з\'єднання</string>
|
||||
<string name="pref_summary_datetime_syctimeonconnect">Синхронізувати час під час з\'єднання з пристроєм, а також під час зміни часу чи часової зони в системі</string>
|
||||
<string name="pref_title_theme">Тема</string>
|
||||
<string name="pref_theme_light">Світла</string>
|
||||
<string name="pref_theme_dark">Темна</string>
|
||||
<string name="pref_header_notifications">Сповіщення</string>
|
||||
<string name="pref_title_notifications_repetitions">Повтори</string>
|
||||
<string name="pref_title_notifications_call">Виклики</string>
|
||||
@ -67,8 +70,6 @@
|
||||
<string name="this_is_a_test_notification_from_gadgetbridge">Це тестове сповіщення від Gadgetbridge</string>
|
||||
<string name="bluetooth_is_not_supported_">Bluetooth не підтримується.</string>
|
||||
<string name="bluetooth_is_disabled_">Bluetooth вимкнуто.</string>
|
||||
<string name="tap_connected_device_for_app_mananger">натисніть на під\'єднаний пристрій для App Manager</string>
|
||||
<string name="tap_a_device_to_connect">натисніть на пристрій для з\'єднання</string>
|
||||
<string name="cannot_connect_bt_address_invalid_">Не вдалося з\'єднатися. Можливо помилкова адреса BT?</string>
|
||||
<string name="gadgetbridge_running">Gadgetbridge запущено</string>
|
||||
<string name="installing_binary_d_d">встановлення бінарного файлу %1$d/%2$d</string>
|
||||
@ -99,13 +100,11 @@
|
||||
<string name="miband_pairing_using_dummy_userdata">Не отримано дійсних даних користувача. Використовуються типові дані.</string>
|
||||
<string name="miband_pairing_tap_hint">Коли ваш Mi—Band вібрує та блимає, постукайте по ньому кілька раз.</string>
|
||||
<string name="appinstaller_install">Встановити</string>
|
||||
<string name="discovery_connected_devices_hint">Під\'єднані на даний момент пристрої, скоріш за все не будуть виявлені.</string>
|
||||
<string name="discovery_note">Замітка:</string>
|
||||
<string name="candidate_item_device_image">Зображення пристрою</string>
|
||||
<string name="miband_prefs_alias">Ім\'я/нік</string>
|
||||
<string name="pref_header_vibration_count">Кількість вібрацій</string>
|
||||
<string name="title_activity_sleepmonitor">Аналіз сну</string>
|
||||
<string name="pref_write_logfiles">Записувати файли звіту</string>
|
||||
<string name="initializing">Ініціалізація…</string>
|
||||
<string name="busy_task_fetch_activity_data">Отримання даних активності</string>
|
||||
<string name="sleep_activity_date_range">Від %1$s до %2$s</string>
|
||||
@ -176,9 +175,9 @@
|
||||
<string name="chart_steps">Кроки</string>
|
||||
<string name="liveactivity_live_activity">Життєва активність</string>
|
||||
<string name="weeksteps_today_steps_description">Кроків сьогодні, мета: %1$s</string>
|
||||
<string name="pref_title_dont_ack_transfer">Не передавати дані про активність</string>
|
||||
<string name="pref_summary_dont_ack_transfers">Якщо дані не будуть передані на пристрій, пристрій не буде очищений. Корисно, якщо Gadgetbridge використовується разом з іншими додатками.</string>
|
||||
<string name="pref_summary_keep_data_on_device">Дозволяє лишити дані на Mi-браслеті після синхронізації. Зазвичай використовується, якщо GB працює ще з іншими додатками.</string>
|
||||
<string name="pref_title_dont_ack_transfer">Не передавати дані про активність</string>
|
||||
<string name="live_activity_steps_history">Історія кроків</string>
|
||||
<string name="live_activity_current_steps_per_minute">Поточні кроки/хв</string>
|
||||
<string name="live_activity_total_steps">Загалом кроків</string>
|
||||
|
@ -52,8 +52,6 @@
|
||||
<string name="this_is_a_test_notification_from_gadgetbridge">Đây là một kiểm tra thông báo từ Gadgetbridge</string>
|
||||
<string name="bluetooth_is_not_supported_">Không hỗ trợ Bluetooth.</string>
|
||||
<string name="bluetooth_is_disabled_">Đã tắt Bluetooth.</string>
|
||||
<string name="tap_connected_device_for_app_mananger">chạm vào thiết bị đã kết nối để chạy Trình quản lý ứng dụng</string>
|
||||
<string name="tap_a_device_to_connect">chạm vào một thiết bị để kết nối</string>
|
||||
<string name="cannot_connect_bt_address_invalid_">Không thể kết nối. Địa chỉ BT không hợp lệ?</string>
|
||||
<string name="gadgetbridge_running">Gadgetbridge đang chạy</string>
|
||||
<string name="installing_binary_d_d">đang cài phần mềm chạy %1$d/%2$d</string>
|
||||
@ -83,7 +81,6 @@
|
||||
<string name="candidate_item_device_image">Ảnh thiết bị</string>
|
||||
<string name="miband_prefs_alias">Tên/Bí danh</string>
|
||||
<string name="title_activity_sleepmonitor">Trình giám sát giấc ngủ</string>
|
||||
<string name="pref_write_logfiles">Ghi tập tin nhật ký</string>
|
||||
<string name="initializing">đang khởi chạy</string>
|
||||
<string name="sleep_activity_date_range">Từ %1$s đến %2$s</string>
|
||||
<string name="miband_prefs_wearside">Đeo bên trái hay phải?</string>
|
||||
|
@ -17,6 +17,7 @@
|
||||
<!-- Strings related to AppManager -->
|
||||
<string name="title_activity_appmanager">App Manager</string>
|
||||
<string name="appmananger_app_delete">Delete</string>
|
||||
<string name="appmananger_app_delete_cache">Delete and remove from cache</string>
|
||||
|
||||
<!-- Strings related to AppBlacklist -->
|
||||
<string name="title_activity_appblacklist">Notification Blacklist</string>
|
||||
@ -52,6 +53,8 @@
|
||||
<string name="pref_summary_notifications_pebblemsg">Support for applications which send Notifications to the Pebble via Intent. Can be used for Conversations.</string>
|
||||
<string name="pref_title_notifications_generic">Generic notification support</string>
|
||||
<string name="pref_title_whenscreenon">… also when screen is on</string>
|
||||
<string name="pref_title_notification_filter">Do Not Disturb</string>
|
||||
<string name="pref_summary_notification_filter">Stop unwanted Notifications from being sent based on the Do Not Disturb mode.</string>
|
||||
|
||||
<string name="always">always</string>
|
||||
<string name="when_screen_off">when screen is off</string>
|
||||
@ -249,5 +252,4 @@
|
||||
<string name="charts_legend_heartrate">Heart Rate</string>
|
||||
<string name="live_activity_heart_rate">Heart Rate</string>
|
||||
<string name="pref_title_general_autocreonnect">Reconnect automatically</string>
|
||||
|
||||
</resources>
|
||||
|
@ -1,5 +1,13 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<changelog>
|
||||
<release version="0.9.8" versioncode="52">
|
||||
<change>Pebble: fix more reconnnect issues</change>
|
||||
<change>Pebble: fix deep sleep not being detected with Firmware 3.12 when using Pebble Health</change>
|
||||
<change>Pebble: option in AppManager to delete files from cache</change>
|
||||
<change>Pebble: enable pbw cache and watchface configuration for Firmware 2.x</change>
|
||||
<change>Pebble: allow enabling of Pebble Health without "untested features" being enabled</change>
|
||||
<change>Honour "Do Not Disturb" for phone calls and SMS</change>
|
||||
</release>
|
||||
<release version="0.9.7" versioncode="51">
|
||||
<change>Pebble: hopefully fix some reconnect issues</change>
|
||||
<change>Mi Band: fix live activity monitoring running forever if back button pressed</change>
|
||||
|
@ -77,6 +77,13 @@
|
||||
android:defaultValue="false"
|
||||
android:key="notifications_generic_whenscreenon"
|
||||
android:title="@string/pref_title_whenscreenon" />
|
||||
|
||||
<CheckBoxPreference
|
||||
android:defaultValue="false"
|
||||
android:key="notification_filter"
|
||||
android:summary="@string/pref_summary_notification_filter"
|
||||
android:title="@string/pref_title_notification_filter" />
|
||||
|
||||
<Preference
|
||||
android:key="pref_key_blacklist"
|
||||
android:title="@string/pref_blacklist" />
|
||||
|
Loading…
Reference in New Issue
Block a user