1
0
mirror of https://codeberg.org/Freeyourgadget/Gadgetbridge synced 2024-12-25 10:05:49 +01:00

Merge branch 'master' into background-javascript

This commit is contained in:
Daniele Gobbetti 2017-09-25 11:21:11 +02:00
commit af6271a428
38 changed files with 1768 additions and 294 deletions

34
FEATURES.md Normal file
View File

@ -0,0 +1,34 @@
## Feature Matrix
| | Pebble OG | Pebble Time/2 | Mi Band | Mi Band 2 | Amazfit Bip |
|-----------------------------------| ----------|---------------|---------|-----------|-------------|
|Calls Notification | YES | YES | YES | YES | YES |
|Reject Calls | YES | YES | NO | NO | YES |
|Accept Calls | NO(2) | NO(2) | NO | NO | NO(3) |
|Generic Notification | YES | YES | YES | YES | YES |
|Dismiss Notifications on Phone | YES | YES | NO | NO | NO |
|Predefined Replies | YES | YES | NO | NO | NO |
|Voice Replies | N/A | NO(3) | N/A | N/A | N/A |
|Calendar Sync | YES | YES | NO | NO | NO |
|Configure alarms from Gadgetbridge | NO | NO | YES | YES | YES |
|Smart alarms | NO(1) | YES | YES | NO | NO |
|Weather | NO(1) | YES | NO | NO | YES |
|Activity Tracking | NO(1) | YES | YES | YES | YES |
|Sleep Tracking | NO(1) | YES | YES | YES | YES |
|HR Tracking | N/A | YES | YES | YES | YES |
|Realtime Activity Tracking | NO | NO | YES | YES | YES |
|Music Control | YES | YES | NO | NO | NO |
|Watchapp/face Installation | YES | YES | NO | NO | NO |
|Firmware Installaton | YES | YES | YES | YES | YES |
|Taking Screenshots | YES | YES | NO | NO | NO |
|Support Android Companion Apps | YES | YES | NO | NO | NO |
(1) Possible via 3rd Party Watchapp
(2) Theoretically possible (works on iOS, would need lot of work)
(3) Possible but not implemented yet
### Notes about Pebble Firmware >=3.0
* Gadgetbridge will keep track of installed watchfaces, but if the Pebble is used with another phone or another app, the information displayed in the app manager can get out of sync since it is impossible to query Firmware >= 3.x for installed apps/watchfaces.

View File

@ -33,31 +33,9 @@ vendor's servers.
* Liveview
* Vibratissimo (experimental)
## Features (Pebble)
## Features
* Incoming calls notification and display
* Outgoing call display
* Reject calls (optionally with predefined texts) / hangup calls
* SMS notification
* Support for generic notifications
* Support for up to 16 predefined replies for SMS and Android Wear compatible notifications (experimental, tested with Signal and Conversations)
* Dismiss individual notifications, mute or open corresponding app on phone from the action menu (generic notifications)
* Dismiss all notifications from the action menu (SMS and PebbleKit notifications)
* Music playback info (artist, album, track)
* Music control: play/pause, next track, previous track, volume up, volume down
* List and remove installed apps/watchfaces
* Install watchfaces and watchapps (.pbw)
* Install firmware files (.pbz) [READ THE WIKI](https://github.com/Freeyourgadget/Gadgetbridge/wiki/Pebble-Firmware-updates)
* Install language files (.pbl)
* Take and share screenshots from the Pebble's screen
* PebbleKit support for 3rd Party Android Apps (experimental)
* Fetch activity data from Pebble Health
* Build-in support for Misfit and Morpheuz (experimental)
* Configure watchfaces / apps (limited compatibility, experimental)
## Notes about Firmware >=3.0 (Pebble Time, updated OG)
* Gadgetbridge will keep track of installed watchfaces, but if the Pebble is used with another phone or another app, the information displayed in the app manager can get out of sync since it is impossible to query Firmware >= 3.x for installed apps/watchfaces.
Please see [FEATURES.md](https://github.com/Freeyourgadget/Gadgetbridge/blob/master/FEATURES.md)
## Getting Started (Pebble)
@ -67,42 +45,6 @@ vendor's servers.
For more information read [this wiki article](https://github.com/Freeyourgadget/Gadgetbridge/wiki/Pebble-Getting-Started)
## Features (Mi Band 1x)
* Discovery and pairing
* Mi Band notifications (LEDs + vibration) for
* Display live activity data (alpha)
* Incoming calls
* SMS received
* K-9 mails received
* Conversations messages
* Generic Android notifications
* Synchronize the time to the Mi Band
* Display firmware version and battery state
* Firmware update
* Heart rate measurement on demand and during sleep
* Synchronize activity data
* Display sleep data (alpha)
* Display sports data (step count) (alpha)
* Display live activity data (alpha)
* Set alarms on the Mi Band
## Features (Mi Band 2)
* Discovery and pairing
* Mi Band notifications (Display + vibration) for
* Incoming calls
* SMS received
* K-9 mails received
* Conversations messages
* Generic Android notifications
* Synchronize the time to the Mi Band 2
* Display firmware version
* Firmware update (beta)
* Heart rate measurement on demand and during sleep
* Synchronize activity data (alpha)
* Set alarms on the Mi Band 2
## How to use (Mi Band 1+2)
* When starting Gadgetbridge the first time, it will automatically

View File

@ -70,6 +70,7 @@ dependencies {
compile 'com.android.support:support-v4:25.3.1'
compile 'com.android.support:gridlayout-v7:25.3.1'
compile 'com.android.support:design:25.3.1'
compile 'com.android.support:palette-v7:25.3.1'
compile 'com.github.tony19:logback-android-classic:1.1.1-6'
compile 'org.slf4j:slf4j-api:1.7.7'
compile 'com.github.PhilJay:MPAndroidChart:v3.0.2'

View File

@ -126,6 +126,7 @@ public class DebugActivity extends AbstractGBActivity {
notificationSpec.sender = testString;
notificationSpec.subject = testString;
notificationSpec.type = NotificationType.values()[sendTypeSpinner.getSelectedItemPosition()];
notificationSpec.pebbleColor = notificationSpec.type.color;
notificationSpec.id = -1;
GBApplication.deviceService().onNotification(notificationSpec);
}

View File

@ -1,97 +0,0 @@
/* Copyright (C) 2017 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 <http://www.gnu.org/licenses/>. */
package nodomain.freeyourgadget.gadgetbridge.devices.amazfitbip;
import nodomain.freeyourgadget.gadgetbridge.model.NotificationType;
public class AmazfitBipIcon {
// icons which are unsure which app they are for are suffixed with _NN
public static final int CHAT = 0;
public static final int PENGUIN_1 = 1;
public static final int MI_CHAT_2 = 2;
public static final int FACEBOOK = 3;
public static final int TWITTER = 4;
public static final int MI_APP_5 = 5;
public static final int SNAPCHAT = 6;
public static final int WHATSAPP = 7;
public static final int RED_WHITE_FIRE_8 = 8;
public static final int CHINESE_9 = 9;
public static final int ALARM_CLOCK = 10;
public static final int APP_11 = 11;
public static final int CAMERA_12 = 12;
public static final int CHAT_BLUE_13 = 13;
public static final int COW_14 = 14;
public static final int CHINESE_15 = 15;
public static final int CHINESE_16 = 16;
public static final int STAR_17 = 17;
public static final int APP_18 = 18;
public static final int CHINESE_19 = 19;
public static final int CHINESE_20 = 20;
public static final int CALENDAR = 21;
public static final int FACEBOOK_MESSENGER = 22;
public static final int WHATSAPP_CALL_23 = 23;
public static final int LINE = 24;
public static final int TELEGRAM = 25;
public static final int KAKAOTALK = 26;
public static final int SKYPE = 27;
public static final int VKONTAKTE = 28;
public static final int POKEMONGO = 29;
public static final int HANGOUTS = 30;
public static final int MI_31 = 31;
public static final int CHINESE_32 = 32;
public static final int CHINESE_33 = 33;
public static final int EMAIL = 34;
public static final int WEATHER = 35;
public static final int HR_WARNING_36 = 36;
public static int mapToIconId(NotificationType type) {
switch (type) {
case UNKNOWN:
return APP_11;
case CONVERSATIONS:
return CHAT;
case GENERIC_EMAIL:
return EMAIL;
case GENERIC_NAVIGATION:
return APP_11;
case GENERIC_SMS:
return CHAT;
case GENERIC_CALENDAR:
return CALENDAR;
case FACEBOOK:
return FACEBOOK;
case FACEBOOK_MESSENGER:
return FACEBOOK_MESSENGER;
case RIOT:
return CHAT;
case SIGNAL:
return CHAT_BLUE_13;
case TWITTER:
return TWITTER;
case TELEGRAM:
return TELEGRAM;
case WHATSAPP:
return WHATSAPP;
case GENERIC_ALARM_CLOCK:
return ALARM_CLOCK;
}
return APP_11;
}
}

View File

@ -24,4 +24,6 @@ public class AmazfitBipService {
// goes to UUID_CHARACTERISTIC_3_CONFIGURATION, TODO: validate this for Mi Band 2, it maybe triggers more than only GPS version...
public static final byte[] COMMAND_REQUEST_GPS_VERSION = new byte[]{0x0e};
public static final byte COMMAND_ACTIVITY_DATA_TYPE_DEBUGLOGS = 0x07;
}

View File

@ -45,7 +45,7 @@ public class MiBand2Service {
public static final UUID UUID_CHARACTERISTIC_5_ACTIVITY_DATA = UUID.fromString("00000005-0000-3512-2118-0009af100700");
public static final UUID UUID_CHARACTERISTIC_6_BATTERY_INFO = UUID.fromString("00000006-0000-3512-2118-0009af100700");
public static final UUID UUID_CHARACTERISTIC_7_REALTIME_STEPS = UUID.fromString("00000007-0000-3512-2118-0009af100700");
public static final UUID UUID_UNKNOWN_CHARACTERISTIC8 = UUID.fromString("00000008-0000-3512-2118-0009af100700");
public static final UUID UUID_CHARACTERISTIC_8_USER_SETTINGS = UUID.fromString("00000008-0000-3512-2118-0009af100700");
// service uuid fee1
public static final UUID UUID_CHARACTERISTIC_AUTH = UUID.fromString("00000009-0000-3512-2118-0009af100700");
public static final UUID UUID_CHARACTERISTIC_10_BUTTON = UUID.fromString("00000010-0000-3512-2118-0009af100700");
@ -104,44 +104,13 @@ public class MiBand2Service {
public static final byte AUTH_BYTE = 0x8;
// maybe not really activity data, but steps?
public static final byte COMMAND_FETCH_ACTIVITY_DATA = 0x02;
public static final byte COMMAND_FETCH_DATA = 0x02;
public static final byte COMMAND_XXXX_ACTIVITY_DATA = 0x03; // maybe delete/drop activity data?
public static final byte[] COMMAND_SET_FITNESS_GOAL_START = new byte[] { 0x10, 0x0, 0x0 };
public static final byte[] COMMAND_SET_FITNESS_GOAL_END = new byte[] { 0, 0 };
public static final byte ICON_CHAT = 0x00;
public static final byte ICON_PENGUIN = 0x01;
public static final byte ICON_CHAT_MI = 0x02;
public static final byte ICON_FB = 0x03;
public static final byte ICON_TWITTER = 0x04;
public static final byte ICON_MIBAND = 0x05;
public static final byte ICON_SNAPCHAT = 0x06;
public static final byte ICON_WHATSAPP = 0x07;
public static final byte ICON_MANTA = 0x08;
public static final byte ICON_XX0 = 0x09;
public static final byte ICON_ALARM = 0x10;
public static final byte ICON_SHATTERED_GLASS = 0x11;
public static final byte ICON_INSTAGRAM = 0x12;
public static final byte ICON_CHAT_GHOST = 0x13;
public static final byte ICON_COW = 0x14;
public static final byte ICON_XX2 = 0x15;
public static final byte ICON_XX3 = 0x16;
public static final byte ICON_XX4 = 0x17;
public static final byte ICON_XX5 = 0x18;
public static final byte ICON_XX6 = 0x19;
public static final byte ICON_EGALE = 0x1a;
public static final byte ICON_CALENDAR = 0x1b;
public static final byte ICON_XX7 = 0x1c;
public static final byte ICON_PHONE_CALL = 0x1d;
public static final byte ICON_CHAT_LINE = 0x1e;
public static final byte ICON_TELEGRAM = 0x1f;
public static final byte ICON_CHAT_TALK = 0x20;
public static final byte ICON_SKYPE = 0x21;
public static final byte ICON_VK = 0x22;
public static final byte ICON_CIRCLES = 0x23;
public static final byte ICON_HANGOUTS = 0x24;
public static final byte ICON_MI = 0x25;
public static final byte COMMAND_SET_USERINFO = 0x4f;
public static final byte ICON_HIGH_PRIORITY = 0x7;
@ -209,7 +178,7 @@ public class MiBand2Service {
public static final byte COMMAND_ACTIVITY_DATA_START_DATE = 0x01;
public static final byte COMMAND_ACTIVITY_DATA_TYPE_ACTIVTY = 0x01;
public static final byte COMMAND_ACTIVITY_DATA_TYPE_UNKNOWN_2 = 0x02;
public static final byte COMMAND_ACTIVITY_DATA_XXX_DATE = 0x02; // issued on first connect, followd by COMMAND_XXXX_ACTIVITY_DATA instead of COMMAND_FETCH_ACTIVITY_DATA
public static final byte COMMAND_ACTIVITY_DATA_XXX_DATE = 0x02; // issued on first connect, followd by COMMAND_XXXX_ACTIVITY_DATA instead of COMMAND_FETCH_DATA
public static final byte COMMAND_FIRMWARE_INIT = 0x01; // to UUID_CHARACTERISTIC_FIRMWARE, followed by fw file size in bytes
public static final byte COMMAND_FIRMWARE_START_DATA = 0x03; // to UUID_CHARACTERISTIC_FIRMWARE

View File

@ -0,0 +1,113 @@
/* Copyright (C) 2017 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 <http://www.gnu.org/licenses/>. */
package nodomain.freeyourgadget.gadgetbridge.devices.miband2;
import nodomain.freeyourgadget.gadgetbridge.model.NotificationType;
public class MiBand2Icon {
// icons which are unsure which app they are for are suffixed with _NN
public static final byte WECHAT = 0;
public static final byte PENGUIN_1 = 1;
public static final byte MI_CHAT_2 = 2;
public static final byte FACEBOOK = 3;
public static final byte TWITTER = 4;
public static final byte MI_APP_5 = 5;
public static final byte SNAPCHAT = 6;
public static final byte WHATSAPP = 7;
public static final byte RED_WHITE_FIRE_8 = 8;
public static final byte CHINESE_9 = 9;
public static final byte ALARM_CLOCK = 10;
public static final byte APP_11 = 11;
public static final byte INSTAGRAM = 12;
public static final byte CHAT_BLUE_13 = 13;
public static final byte COW_14 = 14;
public static final byte CHINESE_15 = 15;
public static final byte CHINESE_16 = 16;
public static final byte STAR_17 = 17;
public static final byte APP_18 = 18;
public static final byte CHINESE_19 = 19;
public static final byte CHINESE_20 = 20;
public static final byte CALENDAR = 21;
public static final byte FACEBOOK_MESSENGER = 22;
public static final byte VIBER = 23;
public static final byte LINE = 24;
public static final byte TELEGRAM = 25;
public static final byte KAKAOTALK = 26;
public static final byte SKYPE = 27;
public static final byte VKONTAKTE = 28;
public static final byte POKEMONGO = 29;
public static final byte HANGOUTS = 30;
public static final byte MI_31 = 31;
public static final byte CHINESE_32 = 32;
public static final byte CHINESE_33 = 33;
public static final byte EMAIL = 34;
public static final byte WEATHER = 35;
public static final byte HR_WARNING_36 = 36;
public static byte mapToIconId(NotificationType type) {
switch (type) {
case UNKNOWN:
return APP_11;
case CONVERSATIONS:
return WECHAT;
case GENERIC_EMAIL:
return EMAIL;
case GENERIC_NAVIGATION:
return APP_11;
case GENERIC_SMS:
return WECHAT;
case GENERIC_CALENDAR:
return CALENDAR;
case FACEBOOK:
return FACEBOOK;
case FACEBOOK_MESSENGER:
return FACEBOOK_MESSENGER;
case GOOGLE_HANGOUTS:
return HANGOUTS;
case INSTAGRAM:
return INSTAGRAM;
case KAKAO_TALK:
return KAKAOTALK;
case LINE:
return LINE;
case RIOT:
return WECHAT;
case SIGNAL:
return CHAT_BLUE_13;
case TWITTER:
return TWITTER;
case SKYPE:
return SKYPE;
case SNAPCHAT:
return SNAPCHAT;
case TELEGRAM:
return TELEGRAM;
case VIBER:
return VIBER;
case WECHAT:
return WECHAT;
case WHATSAPP:
return WHATSAPP;
case GENERIC_ALARM_CLOCK:
return ALARM_CLOCK;
}
return APP_11;
}
}

View File

@ -28,6 +28,9 @@ import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.drawable.Drawable;
import android.media.MediaMetadata;
import android.media.session.PlaybackState;
import android.os.Bundle;
@ -42,21 +45,26 @@ import android.support.v4.media.session.MediaControllerCompat;
import android.support.v4.media.session.MediaSessionCompat;
import android.support.v4.media.session.PlaybackStateCompat;
import android.support.v7.app.NotificationCompat;
import android.support.v7.graphics.Palette;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.List;
import java.util.Objects;
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.devices.pebble.PebbleColor;
import nodomain.freeyourgadget.gadgetbridge.model.AppNotificationType;
import nodomain.freeyourgadget.gadgetbridge.model.MusicSpec;
import nodomain.freeyourgadget.gadgetbridge.model.MusicStateSpec;
import nodomain.freeyourgadget.gadgetbridge.model.NotificationSpec;
import nodomain.freeyourgadget.gadgetbridge.model.NotificationType;
import nodomain.freeyourgadget.gadgetbridge.service.DeviceCommunicationService;
import nodomain.freeyourgadget.gadgetbridge.util.BitmapUtil;
import nodomain.freeyourgadget.gadgetbridge.util.LimitedQueue;
import nodomain.freeyourgadget.gadgetbridge.util.PebbleUtils;
import nodomain.freeyourgadget.gadgetbridge.util.Prefs;
public class NotificationListener extends NotificationListenerService {
@ -192,7 +200,7 @@ public class NotificationListener extends NotificationListenerService {
return;
}
String source = sbn.getPackageName();
String source = sbn.getPackageName().toLowerCase();
Notification notification = sbn.getNotification();
NotificationSpec notificationSpec = new NotificationSpec();
notificationSpec.id = (int) sbn.getPostTime(); //FIMXE: a truly unique id would be better
@ -211,6 +219,9 @@ public class NotificationListener extends NotificationListenerService {
boolean preferBigText = false;
// Get the app ID that generated this notification. For now only used by pebble color, but may be more useful later.
notificationSpec.sourceAppId = source;
notificationSpec.type = AppNotificationType.getInstance().get(source);
if (source.startsWith("com.fsck.k9")) {
@ -221,6 +232,9 @@ public class NotificationListener extends NotificationListenerService {
notificationSpec.type = NotificationType.UNKNOWN;
}
// Get color
notificationSpec.pebbleColor = getPebbleColorForNotification(notificationSpec);
LOG.info("Processing notification " + notificationSpec.id + " from source " + source + " with flags: " + notification.flags);
dissectNotificationTo(notification, notificationSpec, preferBigText);
@ -379,13 +393,9 @@ public class NotificationListener extends NotificationListenerService {
return true;
}
if (shouldIgnoreSource(sbn.getPackageName()))
return true;
return shouldIgnoreSource(sbn.getPackageName()) || shouldIgnoreNotification(
sbn.getNotification());
if (shouldIgnoreNotification(sbn.getNotification()))
return true;
return false;
}
private boolean shouldIgnoreSource(String source) {
@ -442,12 +452,46 @@ public class NotificationListener extends NotificationListenerService {
}
}
if ((notification.flags & Notification.FLAG_ONGOING_EVENT) == Notification.FLAG_ONGOING_EVENT) {
// LOG.info("Not forwarding notification, FLAG_ONGOING_EVENT is set. Notification flags: " + notification.flags);
return true;
}
return (notification.flags & Notification.FLAG_ONGOING_EVENT) == Notification.FLAG_ONGOING_EVENT;
return false;
}
/**
* Get the notification color that should be used for this Pebble notification.
*
* Note that this method will *not* edit the NotificationSpec passed in. It will only evaluate the PebbleColor.
*
* See Issue #815 on GitHub to see how notification colors are set.
*
* @param notificationSpec The NotificationSpec to read from.
* @return Returns a PebbleColor that best represents this notification.
*/
private byte getPebbleColorForNotification(NotificationSpec notificationSpec) {
String appId = notificationSpec.sourceAppId;
NotificationType existingType = notificationSpec.type;
// If the notification type is known, return the associated color.
if (existingType != NotificationType.UNKNOWN) {
return existingType.color;
}
// Otherwise, we go and attempt to find the color from the app icon.
Drawable icon;
try {
icon = getApplicationContext().getPackageManager().getApplicationIcon(appId);
Objects.requireNonNull(icon);
} catch (Exception ex) {
// If we can't get the icon, we go with the default defined above.
LOG.warn("Could not get icon for AppID " + appId, ex);
return PebbleColor.IslamicGreen;
}
Bitmap bitmapIcon = BitmapUtil.convertDrawableToBitmap(icon);
int iconPrimaryColor = new Palette.Builder(bitmapIcon)
.generate()
.getVibrantColor(Color.parseColor("#aa0000"));
return PebbleUtils.getPebbleColor(iconPrimaryColor);
}
}

View File

@ -141,7 +141,8 @@ public class GBDeviceService implements DeviceService {
.putExtra(EXTRA_NOTIFICATION_BODY, notificationSpec.body)
.putExtra(EXTRA_NOTIFICATION_ID, notificationSpec.id)
.putExtra(EXTRA_NOTIFICATION_TYPE, notificationSpec.type)
.putExtra(EXTRA_NOTIFICATION_SOURCENAME, notificationSpec.sourceName);
.putExtra(EXTRA_NOTIFICATION_SOURCENAME, notificationSpec.sourceName)
.putExtra(EXTRA_NOTIFICATION_PEBBLE_COLOR, notificationSpec.pebbleColor);
invokeService(intent);
}

View File

@ -53,6 +53,9 @@ public class AppNotificationType extends HashMap<String, NotificationType> {
put("com.google.android.apps.inbox", NotificationType.GOOGLE_INBOX);
put("com.google.android.calendar", NotificationType.GENERIC_CALENDAR);
put("com.google.android.apps.messaging", NotificationType.GOOGLE_MESSENGER);
put("com.google.android.talk", NotificationType.GOOGLE_HANGOUTS);
put("com.google.android.apps.maps", NotificationType.GOOGLE_MAPS);
put("com.google.android.apps.photos", NotificationType.GOOGLE_PHOTOS);
// Conversations
put("eu.siacs.conversations", NotificationType.CONVERSATIONS);
@ -84,6 +87,57 @@ public class AppNotificationType extends HashMap<String, NotificationType> {
// WhatsApp
put("com.whatsapp", NotificationType.WHATSAPP);
// HipChat
put("com.hipchat", NotificationType.HIPCHAT);
// Skype
put("com.skype.raider", NotificationType.SKYPE);
// Mailbox
put("com.mailboxapp", NotificationType.MAILBOX);
// Snapchat
put("com.snapchat.android", NotificationType.SNAPCHAT);
// WeChat
put("com.tencent.mm", NotificationType.WECHAT);
// Viber
put("com.viber.voip", NotificationType.VIBER);
// Instagram
put("com.instagram.android", NotificationType.INSTAGRAM);
// Kik
put("kik.android", NotificationType.KIK);
// Line
put("jp.naver.line.android", NotificationType.LINE);
// BBM
put("com.bbm", NotificationType.BBM);
// Microsoft Outlook
put("com.microsoft.office.outlook", NotificationType.OUTLOOK);
// Yahoo Mail
put("com.yahoo.mobile.client.android.mail", NotificationType.YAHOO_MAIL);
// Kakao Talk
put("com.kakao.talk", NotificationType.KAKAO_TALK);
// Amazon
put("com.amazon.mshop.android.shopping", NotificationType.AMAZON);
// LinkedIn
put("com.linkedin.android", NotificationType.LINKEDIN);
// Slack
put("com.slack", NotificationType.SLACK);
// Transit
put("com.thetransitapp.droid", NotificationType.TRANSIT);
}
}

View File

@ -73,6 +73,7 @@ public interface DeviceService extends EventHandler {
String EXTRA_NOTIFICATION_SUBJECT = "notification_subject";
String EXTRA_NOTIFICATION_TITLE = "notification_title";
String EXTRA_NOTIFICATION_TYPE = "notification_type";
String EXTRA_NOTIFICATION_PEBBLE_COLOR = "notification_pebble_color";
String EXTRA_FIND_START = "find_start";
String EXTRA_VIBRATION_INTENSITY = "vibration_intensity";
String EXTRA_CALL_COMMAND = "call_command";

View File

@ -29,4 +29,14 @@ public class NotificationSpec {
public NotificationType type;
public String sourceName;
public String[] cannedReplies;
/**
* The application that generated the notification.
*/
public String sourceAppId;
/**
* The color that should be assigned to this notification when displayed on a Pebble
*/
public byte pebbleColor;
}

View File

@ -23,24 +23,47 @@ import nodomain.freeyourgadget.gadgetbridge.devices.pebble.PebbleIconID;
public enum NotificationType {
// TODO: this this pebbleism needs to be moved somewhere else
UNKNOWN(PebbleIconID.NOTIFICATION_GENERIC, PebbleColor.Red),
UNKNOWN(PebbleIconID.NOTIFICATION_GENERIC, PebbleColor.DarkCandyAppleRed),
AMAZON(PebbleIconID.NOTIFICATION_AMAZON, PebbleColor.ChromeYellow),
BBM(PebbleIconID.NOTIFICATION_BLACKBERRY_MESSENGER, PebbleColor.DarkGray),
CONVERSATIONS(PebbleIconID.NOTIFICATION_HIPCHAT, PebbleColor.Inchworm),
GENERIC_EMAIL(PebbleIconID.GENERIC_EMAIL, PebbleColor.JaegerGreen),
FACEBOOK(PebbleIconID.NOTIFICATION_FACEBOOK, PebbleColor.CobaltBlue),
FACEBOOK_MESSENGER(PebbleIconID.NOTIFICATION_FACEBOOK_MESSENGER, PebbleColor.BlueMoon),
GENERIC_ALARM_CLOCK(PebbleIconID.ALARM_CLOCK, PebbleColor.Red),
GENERIC_CALENDAR(PebbleIconID.TIMELINE_CALENDAR, PebbleColor.BlueMoon),
GENERIC_EMAIL(PebbleIconID.GENERIC_EMAIL, PebbleColor.Orange),
GENERIC_NAVIGATION(PebbleIconID.LOCATION, PebbleColor.Orange),
GENERIC_PHONE(PebbleIconID.DURING_PHONE_CALL, PebbleColor.JaegerGreen),
GENERIC_SMS(PebbleIconID.GENERIC_SMS, PebbleColor.VividViolet),
GENERIC_CALENDAR(PebbleIconID.TIMELINE_CALENDAR, PebbleColor.Blue),
GMAIL(PebbleIconID.NOTIFICATION_GMAIL, PebbleColor.Red),
GOOGLE_INBOX(PebbleIconID.NOTIFICATION_GOOGLE_INBOX, PebbleColor.Blue),
GOOGLE_MESSENGER(PebbleIconID.NOTIFICATION_GOOGLE_MESSENGER, PebbleColor.Blue),
FACEBOOK(PebbleIconID.NOTIFICATION_FACEBOOK, PebbleColor.Liberty),
FACEBOOK_MESSENGER(PebbleIconID.NOTIFICATION_FACEBOOK_MESSENGER, PebbleColor.VeryLightBlue),
GOOGLE_HANGOUTS(PebbleIconID.NOTIFICATION_GOOGLE_HANGOUTS, PebbleColor.JaegerGreen),
GOOGLE_INBOX(PebbleIconID.NOTIFICATION_GOOGLE_INBOX, PebbleColor.BlueMoon),
GOOGLE_MAPS(PebbleIconID.NOTIFICATION_GOOGLE_MAPS, PebbleColor.BlueMoon),
GOOGLE_MESSENGER(PebbleIconID.NOTIFICATION_GOOGLE_MESSENGER, PebbleColor.VividCerulean),
GOOGLE_PHOTOS(PebbleIconID.NOTIFICATION_GOOGLE_PHOTOS, PebbleColor.BlueMoon),
HIPCHAT(PebbleIconID.NOTIFICATION_HIPCHAT, PebbleColor.CobaltBlue),
INSTAGRAM(PebbleIconID.NOTIFICATION_INSTAGRAM, PebbleColor.CobaltBlue),
KAKAO_TALK(PebbleIconID.NOTIFICATION_KAKAOTALK, PebbleColor.Yellow),
KIK(PebbleIconID.NOTIFICATION_KIK, PebbleColor.IslamicGreen),
LIGHTHOUSE(PebbleIconID.NOTIFICATION_LIGHTHOUSE, PebbleColor.PictonBlue), // ??? - No idea what this is, but it works.
LINE(PebbleIconID.NOTIFICATION_LINE, PebbleColor.IslamicGreen),
LINKEDIN(PebbleIconID.NOTIFICATION_LINKEDIN, PebbleColor.CobaltBlue),
MAILBOX(PebbleIconID.NOTIFICATION_MAILBOX, PebbleColor.VividCerulean),
OUTLOOK(PebbleIconID.NOTIFICATION_OUTLOOK, PebbleColor.BlueMoon),
RIOT(PebbleIconID.NOTIFICATION_HIPCHAT, PebbleColor.LavenderIndigo),
SIGNAL(PebbleIconID.NOTIFICATION_HIPCHAT, PebbleColor.BlueMoon),
SKYPE(PebbleIconID.NOTIFICATION_SKYPE, PebbleColor.VividCerulean),
SLACK(PebbleIconID.NOTIFICATION_SLACK, PebbleColor.Folly),
SNAPCHAT(PebbleIconID.NOTIFICATION_SNAPCHAT, PebbleColor.Icterine),
TELEGRAM(PebbleIconID.NOTIFICATION_TELEGRAM, PebbleColor.VividCerulean),
TRANSIT(PebbleIconID.LOCATION, PebbleColor.JaegerGreen),
TWITTER(PebbleIconID.NOTIFICATION_TWITTER, PebbleColor.BlueMoon),
TELEGRAM(PebbleIconID.NOTIFICATION_TELEGRAM, PebbleColor.PictonBlue),
WHATSAPP(PebbleIconID.NOTIFICATION_WHATSAPP, PebbleColor.MayGreen),
GENERIC_ALARM_CLOCK(PebbleIconID.ALARM_CLOCK, PebbleColor.Red);
VIBER(PebbleIconID.NOTIFICATION_VIBER, PebbleColor.VividViolet),
WECHAT(PebbleIconID.NOTIFICATION_WECHAT, PebbleColor.KellyGreen),
WHATSAPP(PebbleIconID.NOTIFICATION_WHATSAPP, PebbleColor.IslamicGreen),
YAHOO_MAIL(PebbleIconID.NOTIFICATION_YAHOO_MAIL, PebbleColor.Indigo);
// Note: if you add any more constants, update all clients as well
public final int icon;
@ -69,6 +92,9 @@ public enum NotificationType {
return getFixedValue();
case FACEBOOK:
case TWITTER:
case SNAPCHAT:
case INSTAGRAM:
case LINKEDIN:
return "generic_social";
case CONVERSATIONS:
case FACEBOOK_MESSENGER:
@ -77,10 +103,23 @@ public enum NotificationType {
case TELEGRAM:
case WHATSAPP:
case GOOGLE_MESSENGER:
case GOOGLE_HANGOUTS:
case HIPCHAT:
case SKYPE:
case WECHAT:
case KIK:
case KAKAO_TALK:
case SLACK:
return "generic_chat";
case GMAIL:
case GOOGLE_INBOX:
case MAILBOX:
case OUTLOOK:
case YAHOO_MAIL:
return "generic_email";
case LINE:
case VIBER:
return "generic_phone";
case UNKNOWN:
default:
return "generic";

View File

@ -138,6 +138,7 @@ import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_MUS
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_NOTIFICATION_BODY;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_NOTIFICATION_FLAGS;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_NOTIFICATION_ID;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_NOTIFICATION_PEBBLE_COLOR;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_NOTIFICATION_PHONENUMBER;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_NOTIFICATION_SENDER;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_NOTIFICATION_SOURCENAME;
@ -343,6 +344,7 @@ public class DeviceCommunicationService extends Service implements SharedPrefere
notificationSpec.body = intent.getStringExtra(EXTRA_NOTIFICATION_BODY);
notificationSpec.sourceName = intent.getStringExtra(EXTRA_NOTIFICATION_SOURCENAME);
notificationSpec.type = (NotificationType) intent.getSerializableExtra(EXTRA_NOTIFICATION_TYPE);
notificationSpec.pebbleColor = (byte) intent.getSerializableExtra(EXTRA_NOTIFICATION_PEBBLE_COLOR);
notificationSpec.id = intent.getIntExtra(EXTRA_NOTIFICATION_ID, -1);
notificationSpec.flags = intent.getIntExtra(EXTRA_NOTIFICATION_FLAGS, 0);

View File

@ -49,7 +49,7 @@ public class NewAlert {
private final AlertCategory category;
private final int numAlerts;
private final String message;
private int customIcon = -1;
private byte customIcon = -1;
public NewAlert(AlertCategory category, int /*uint8*/ numAlerts, String /*utf8s*/ message) {
this.category = category;
@ -57,7 +57,7 @@ public class NewAlert {
this.message = message;
}
public NewAlert(AlertCategory category, int /*uint8*/ numAlerts, String /*utf8s*/ message, int customIcon) {
public NewAlert(AlertCategory category, int /*uint8*/ numAlerts, String /*utf8s*/ message, byte customIcon) {
this.category = category;
this.numAlerts = numAlerts;
this.message = message;
@ -76,7 +76,7 @@ public class NewAlert {
return message;
}
public int getCustomIcon() {
public byte getCustomIcon() {
return customIcon;
}
}

View File

@ -0,0 +1,31 @@
/* Copyright (C) 2017 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 <http://www.gnu.org/licenses/>. */
package nodomain.freeyourgadget.gadgetbridge.service.devices.amazfitbip;
public class AmazfitBipEvent {
public static final byte FELL_ASLEEP = 0x01;
public static final byte WOKE_UP = 0x02;
public static final byte STEPSGOAL_REACHED = 0x03;
public static final byte BUTTON_PRESSED = 0x04;
public static final byte START_NONWEAR = 0x06;
public static final byte CALL_REJECT = 0x07;
public static final byte CALL_ACCEPT = 0x09;
public static final byte ALARM_TOGGLED = 0x0a;
public static final byte BUTTON_PRESSED_LONG = 0x0b;
public static final byte TICK_30MIN = 0x0e; // unsure
}

View File

@ -41,15 +41,26 @@ public class AmazfitBipFirmwareInfo extends Mi2FirmwareInfo {
0x48, 0x4d, 0x52, 0x45, 0x53
};
private static final byte[] GPS_ALMANAC_HEADER = new byte[]{ // probably wrong
(byte) 0xa0, (byte) 0x80, 0x08, 0x00, (byte) 0x8b, 0x07
};
private static final byte[] GPS_CEP_HEADER = new byte[]{ // probably wrong
0x2a, 0x12, (byte) 0xa0, 0x02
};
static {
// firmware
crcToVersion.put(25257, "0.0.8.74");
crcToVersion.put(57724, "0.0.8.88");
crcToVersion.put(27668, "0.0.8.96");
crcToVersion.put(60173, "0.0.8.97");
crcToVersion.put(3462, "0.0.8.98");
// resources
crcToVersion.put(12586, "RES 0.0.8.74");
crcToVersion.put(34068, "RES 0.0.8.88");
crcToVersion.put(59839, "RES 0.0.8.96-98");
// gps
crcToVersion.put(61520, "GPS 9367,8f79a91,0,0,");
@ -67,6 +78,12 @@ public class AmazfitBipFirmwareInfo extends Mi2FirmwareInfo {
if (ArrayUtils.startsWith(bytes, GPS_HEADER)) {
return FirmwareType.GPS;
}
if (ArrayUtils.startsWith(bytes, GPS_ALMANAC_HEADER)) {
return FirmwareType.GPS_ALMANAC;
}
if (ArrayUtils.startsWith(bytes, GPS_CEP_HEADER)) {
return FirmwareType.GPS_CEP;
}
if (ArrayUtils.equals(bytes, FW_HEADER, FW_HEADER_OFFSET)) {
// TODO: this is certainly not a correct validation, but it works for now
return FirmwareType.FIRMWARE;

View File

@ -30,12 +30,11 @@ import java.nio.ByteOrder;
import java.util.SimpleTimeZone;
import java.util.UUID;
import nodomain.freeyourgadget.gadgetbridge.Logging;
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventCallControl;
import nodomain.freeyourgadget.gadgetbridge.devices.amazfitbip.AmazfitBipIcon;
import nodomain.freeyourgadget.gadgetbridge.devices.amazfitbip.AmazfitBipService;
import nodomain.freeyourgadget.gadgetbridge.devices.amazfitbip.AmazfitBipWeatherConditions;
import nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBand2Service;
import nodomain.freeyourgadget.gadgetbridge.devices.miband2.MiBand2Icon;
import nodomain.freeyourgadget.gadgetbridge.model.CallSpec;
import nodomain.freeyourgadget.gadgetbridge.model.NotificationSpec;
import nodomain.freeyourgadget.gadgetbridge.model.NotificationType;
@ -44,6 +43,7 @@ import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder;
import nodomain.freeyourgadget.gadgetbridge.service.btle.profiles.alertnotification.AlertCategory;
import nodomain.freeyourgadget.gadgetbridge.service.btle.profiles.alertnotification.AlertNotificationProfile;
import nodomain.freeyourgadget.gadgetbridge.service.btle.profiles.alertnotification.NewAlert;
import nodomain.freeyourgadget.gadgetbridge.service.devices.amazfitbip.operations.AmazfitBipFetchLogsOperation;
import nodomain.freeyourgadget.gadgetbridge.service.devices.amazfitbip.operations.AmazfitBipUpdateFirmwareOperation;
import nodomain.freeyourgadget.gadgetbridge.service.devices.miband.NotificationStrategy;
import nodomain.freeyourgadget.gadgetbridge.service.devices.miband2.MiBand2Support;
@ -82,7 +82,7 @@ public class AmazfitBipSupport extends MiBand2Support {
AlertNotificationProfile<?> profile = new AlertNotificationProfile(this);
profile.setMaxLength(230);
int customIconId = AmazfitBipIcon.mapToIconId(notificationSpec.type);
byte customIconId = MiBand2Icon.mapToIconId(notificationSpec.type);
AlertCategory alertCategory = AlertCategory.CustomMiBand2;
@ -118,15 +118,42 @@ public class AmazfitBipSupport extends MiBand2Support {
}
GBDeviceEventCallControl callCmd = new GBDeviceEventCallControl();
if (value[0] == 0x07) {
callCmd.event = GBDeviceEventCallControl.Event.REJECT;
} else if (value[0] == 0x09) {
callCmd.event = GBDeviceEventCallControl.Event.ACCEPT;
} else {
LOG.info("Unhandled button press: " + Logging.formatBytes(value));
return;
switch (value[0]) {
case AmazfitBipEvent.CALL_REJECT:
callCmd.event = GBDeviceEventCallControl.Event.REJECT;
evaluateGBDeviceEvent(callCmd);
break;
case AmazfitBipEvent.CALL_ACCEPT:
callCmd.event = GBDeviceEventCallControl.Event.ACCEPT;
evaluateGBDeviceEvent(callCmd);
break;
case AmazfitBipEvent.BUTTON_PRESSED:
LOG.info("button pressed");
break;
case AmazfitBipEvent.BUTTON_PRESSED_LONG:
LOG.info("button long-pressed ");
break;
case AmazfitBipEvent.START_NONWEAR:
LOG.info("non-wear start detected");
break;
case AmazfitBipEvent.ALARM_TOGGLED:
LOG.info("An alarm was toggled"); // TODO: sync alarms watch -> GB
break;
case AmazfitBipEvent.FELL_ASLEEP:
LOG.info("Fell asleep");
break;
case AmazfitBipEvent.WOKE_UP:
LOG.info("Woke up");
break;
case AmazfitBipEvent.STEPSGOAL_REACHED:
LOG.info("Steps goal reached");
break;
case AmazfitBipEvent.TICK_30MIN:
LOG.info("Tick 30 min (?)");
break;
default:
LOG.warn("unhandled event " + value[0]);
}
evaluateGBDeviceEvent(callCmd);
}
@Override
@ -198,6 +225,15 @@ public class AmazfitBipSupport extends MiBand2Support {
}
}
@Override
public void onTestNewFunction() {
try {
new AmazfitBipFetchLogsOperation(this).perform();
} catch (IOException ex) {
LOG.error("Unable to fetch logs", ex);
}
}
@Override
public boolean onCharacteristicChanged(BluetoothGatt gatt,
BluetoothGattCharacteristic characteristic) {

View File

@ -0,0 +1,131 @@
/* Copyright (C) 2016-2017 Carsten Pfeiffer
This file is part of Gadgetbridge.
Gadgetbridge is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Gadgetbridge is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
package nodomain.freeyourgadget.gadgetbridge.service.devices.amazfitbip.operations;
import android.support.annotation.NonNull;
import android.support.v4.util.TimeUtils;
import android.widget.Toast;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Locale;
import java.util.concurrent.TimeUnit;
import nodomain.freeyourgadget.gadgetbridge.devices.amazfitbip.AmazfitBipService;
import nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBand2Service;
import nodomain.freeyourgadget.gadgetbridge.service.btle.BLETypeConversions;
import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder;
import nodomain.freeyourgadget.gadgetbridge.service.btle.actions.WaitAction;
import nodomain.freeyourgadget.gadgetbridge.service.devices.amazfitbip.AmazfitBipSupport;
import nodomain.freeyourgadget.gadgetbridge.service.devices.miband2.operations.AbstractFetchOperation;
import nodomain.freeyourgadget.gadgetbridge.util.FileUtils;
import nodomain.freeyourgadget.gadgetbridge.util.GB;
public class AmazfitBipFetchLogsOperation extends AbstractFetchOperation {
private static final Logger LOG = LoggerFactory.getLogger(AmazfitBipFetchLogsOperation.class);
private FileOutputStream logOutputStream;
public AmazfitBipFetchLogsOperation(AmazfitBipSupport support) {
super(support);
}
@Override
protected void startFetching(TransactionBuilder builder) {
File dir;
try {
dir = FileUtils.getExternalFilesDir();
} catch (IOException e) {
return;
}
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd-hhmmss", Locale.US);
String filename = "amazfitbip_" + dateFormat.format(new Date()) + ".log";
File outputFile = new File(dir, filename );
try {
logOutputStream = new FileOutputStream(outputFile);
} catch (IOException e) {
LOG.warn("could not create file " + outputFile, e);
return;
}
GregorianCalendar sinceWhen = BLETypeConversions.createCalendar();
sinceWhen.add(Calendar.DAY_OF_MONTH, -10);
builder.write(characteristicFetch, BLETypeConversions.join(new byte[]{
MiBand2Service.COMMAND_ACTIVITY_DATA_START_DATE,
AmazfitBipService.COMMAND_ACTIVITY_DATA_TYPE_DEBUGLOGS},
getSupport().getTimeBytes(sinceWhen, TimeUnit.MINUTES)));
builder.add(new WaitAction(1000)); // TODO: actually wait for the success-reply
builder.notify(characteristicActivityData, true);
builder.write(characteristicFetch, new byte[]{MiBand2Service.COMMAND_FETCH_DATA});
}
@Override
protected String getLastSyncTimeKey() {
return null;
}
@Override
protected void handleActivityFetchFinish() {
LOG.info("Fetching log data has finished");
try {
logOutputStream.close();
logOutputStream = null;
} catch (IOException e) {
LOG.warn("could not close output stream", e);
return;
}
super.handleActivityFetchFinish();
}
@Override
protected void handleActivityNotif(byte[] value) {
if (!isOperationRunning()) {
LOG.error("ignoring notification because operation is not running. Data length: " + value.length);
getSupport().logMessageContent(value);
return;
}
if ((byte) (lastPacketCounter + 1) == value[0]) {
lastPacketCounter++;
bufferActivityData(value);
} else {
GB.toast("Error fetching activity data, invalid package counter: " + value[0], Toast.LENGTH_LONG, GB.ERROR);
handleActivityFetchFinish();
}
}
@Override
protected void bufferActivityData(@NonNull byte[] value) {
try {
logOutputStream.write(Arrays.copyOfRange(value, 1, value.length));
} catch (IOException e) {
LOG.warn("could not write to output stream", e);
handleActivityFetchFinish();
}
}
}

View File

@ -19,8 +19,11 @@ package nodomain.freeyourgadget.gadgetbridge.service.devices.miband2;
public enum FirmwareType {
FIRMWARE((byte) 0),
FONT((byte) 1),
// Amazfit Bip only from here on
RES((byte) 2),
GPS((byte) 3),
GPS_CEP((byte) 4),
GPS_ALMANAC((byte)5),
INVALID(Byte.MIN_VALUE);
private final byte value;

View File

@ -21,6 +21,7 @@ import android.support.annotation.NonNull;
import nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBand2Service;
import nodomain.freeyourgadget.gadgetbridge.devices.miband.VibrationProfile;
import nodomain.freeyourgadget.gadgetbridge.devices.miband2.MiBand2Icon;
import nodomain.freeyourgadget.gadgetbridge.service.btle.BLETypeConversions;
import nodomain.freeyourgadget.gadgetbridge.service.btle.BtLEAction;
import nodomain.freeyourgadget.gadgetbridge.service.btle.GattCharacteristic;
@ -68,9 +69,9 @@ public class Mi2TextNotificationStrategy extends Mi2NotificationStrategy {
case Email:
return new byte[] { BLETypeConversions.fromUint8(AlertCategory.Email.getId()), BLETypeConversions.fromUint8(numAlerts)};
case InstantMessage:
return new byte[] { BLETypeConversions.fromUint8(AlertCategory.CustomMiBand2.getId()), BLETypeConversions.fromUint8(numAlerts), MiBand2Service.ICON_CHAT};
return new byte[] { BLETypeConversions.fromUint8(AlertCategory.CustomMiBand2.getId()), BLETypeConversions.fromUint8(numAlerts), MiBand2Icon.WECHAT};
case News:
return new byte[] { BLETypeConversions.fromUint8(AlertCategory.CustomMiBand2.getId()), BLETypeConversions.fromUint8(numAlerts), MiBand2Service.ICON_PENGUIN};
return new byte[] { BLETypeConversions.fromUint8(AlertCategory.CustomMiBand2.getId()), BLETypeConversions.fromUint8(numAlerts), MiBand2Icon.PENGUIN_1};
}
}
return new byte[] { BLETypeConversions.fromUint8(AlertCategory.SMS.getId()), BLETypeConversions.fromUint8(numAlerts)};

View File

@ -350,7 +350,7 @@ public class MiBand2Support extends AbstractBTLEDeviceSupport {
private MiBand2Support setFitnessGoal(TransactionBuilder transaction) {
LOG.info("Attempting to set Fitness Goal...");
BluetoothGattCharacteristic characteristic = getCharacteristic(MiBand2Service.UUID_UNKNOWN_CHARACTERISTIC8);
BluetoothGattCharacteristic characteristic = getCharacteristic(MiBand2Service.UUID_CHARACTERISTIC_8_USER_SETTINGS);
if (characteristic != null) {
int fitnessGoal = GBApplication.getPrefs().getInt(ActivityUser.PREF_USER_STEPS_GOAL, 10000);
byte[] bytes = ArrayUtils.addAll(
@ -365,6 +365,68 @@ public class MiBand2Support extends AbstractBTLEDeviceSupport {
return this;
}
/**
* Part of device initialization process. Do not call manually.
*
* @param transaction
* @return
*/
private MiBand2Support setUserInfo(TransactionBuilder transaction) {
BluetoothGattCharacteristic characteristic = getCharacteristic(MiBand2Service.UUID_CHARACTERISTIC_8_USER_SETTINGS);
if (characteristic == null) {
return this;
}
LOG.info("Attempting to set user info...");
Prefs prefs = GBApplication.getPrefs();
String alias = prefs.getString(MiBandConst.PREF_USER_ALIAS, null);
ActivityUser activityUser = new ActivityUser();
int height = activityUser.getHeightCm();
int weight = activityUser.getWeightKg();
int birth_year = activityUser.getYearOfBirth();
byte birth_month = 7; // not in user attributes
byte birth_day = 1; // not in user attributes
if (alias == null || weight == 0 || height == 0 || birth_year == 0) {
LOG.warn("Unable to set user info, make sure it is set up");
return this;
}
byte sex = 2; // other
switch (activityUser.getGender()) {
case ActivityUser.GENDER_MALE:
sex = 0;
break;
case ActivityUser.GENDER_FEMALE:
sex = 1;
}
int userid = alias.hashCode(); // hash from alias like mi1
// FIXME: Do encoding like in PebbleProtocol, this is ugly
byte bytes[] = new byte[]{
MiBand2Service.COMMAND_SET_USERINFO,
0,
0,
(byte) (birth_year & 0xff),
(byte) ((birth_year >> 8) & 0xff),
birth_month,
birth_day,
sex,
(byte) (height & 0xff),
(byte) ((height >> 8) & 0xff),
(byte) ((weight * 200) & 0xff),
(byte) (((weight * 200) >> 8) & 0xff),
(byte) (userid & 0xff),
(byte) ((userid >> 8) & 0xff),
(byte) ((userid >> 16) & 0xff),
(byte) ((userid >> 24) & 0xff)
};
transaction.write(characteristic, bytes);
return this;
}
/**
* Part of device initialization process. Do not call manually.
*
@ -373,7 +435,7 @@ public class MiBand2Support extends AbstractBTLEDeviceSupport {
*/
private MiBand2Support setWearLocation(TransactionBuilder builder) {
LOG.info("Attempting to set wear location...");
BluetoothGattCharacteristic characteristic = getCharacteristic(MiBand2Service.UUID_UNKNOWN_CHARACTERISTIC8);
BluetoothGattCharacteristic characteristic = getCharacteristic(MiBand2Service.UUID_CHARACTERISTIC_8_USER_SETTINGS);
if (characteristic != null) {
builder.notify(characteristic, true);
int location = MiBandCoordinator.getWearLocation(getDevice().getAddress());
@ -625,13 +687,18 @@ public class MiBand2Support extends AbstractBTLEDeviceSupport {
public void onReboot() {
try {
TransactionBuilder builder = performInitialized("Reboot");
builder.write(getCharacteristic(MiBand2Service.UUID_CHARACTERISTIC_FIRMWARE), new byte[] { MiBand2Service.COMMAND_FIRMWARE_REBOOT});
sendReboot(builder);
builder.queue(getQueue());
} catch (IOException ex) {
LOG.error("Unable to reboot MI", ex);
}
}
public MiBand2Support sendReboot(TransactionBuilder builder) {
builder.write(getCharacteristic(MiBand2Service.UUID_CHARACTERISTIC_FIRMWARE), new byte[] { MiBand2Service.COMMAND_FIRMWARE_REBOOT});
return this;
}
@Override
public void onHeartRateTest() {
try {
@ -1395,6 +1462,7 @@ public class MiBand2Support extends AbstractBTLEDeviceSupport {
LOG.info("phase3Initialize...");
setDateDisplay(builder);
setTimeFormat(builder);
setUserInfo(builder);
setWearLocation(builder);
setFitnessGoal(builder);
setDisplayItems(builder);

View File

@ -132,10 +132,6 @@ public abstract class AbstractFetchOperation extends AbstractMiBand2Operation {
*/
protected abstract void handleActivityNotif(byte[] value);
/**
* Creates samples from the given 17-length array
* @param value
*/
protected abstract void bufferActivityData(byte[] value);
protected void handleActivityMetadata(byte[] value) {
@ -146,7 +142,7 @@ public abstract class AbstractFetchOperation extends AbstractMiBand2Operation {
// the 4th - 7th bytes probably somehow represent the number of bytes/packets to expect
// last 8 bytes are the start date
Calendar startTimestamp = getSupport().fromTimeBytes(org.apache.commons.lang3.ArrayUtils.subarray(value, 7, value.length));
Calendar startTimestamp = getSupport().fromTimeBytes(Arrays.copyOfRange(value, 7, value.length));
setStartTimestamp(startTimestamp);
GB.toast(getContext().getString(R.string.FetchActivityOperation_about_to_transfer_since,

View File

@ -71,7 +71,7 @@ public class FetchActivityOperation extends AbstractFetchOperation {
builder.write(characteristicFetch, BLETypeConversions.join(new byte[] { MiBand2Service.COMMAND_ACTIVITY_DATA_START_DATE, MiBand2Service.COMMAND_ACTIVITY_DATA_TYPE_ACTIVTY }, getSupport().getTimeBytes(sinceWhen, TimeUnit.MINUTES)));
builder.add(new WaitAction(1000)); // TODO: actually wait for the success-reply
builder.notify(characteristicActivityData, true);
builder.write(characteristicFetch, new byte[] { MiBand2Service.COMMAND_FETCH_ACTIVITY_DATA });
builder.write(characteristicFetch, new byte[] { MiBand2Service.COMMAND_FETCH_DATA});
}
protected void handleActivityFetchFinish() {

View File

@ -0,0 +1,152 @@
/* Copyright (C) 2016-2017 Carsten Pfeiffer
This file is part of Gadgetbridge.
Gadgetbridge is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Gadgetbridge is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
package nodomain.freeyourgadget.gadgetbridge.service.devices.miband2.operations;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCharacteristic;
import android.widget.Toast;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.concurrent.TimeUnit;
import nodomain.freeyourgadget.gadgetbridge.Logging;
import nodomain.freeyourgadget.gadgetbridge.devices.amazfitbip.AmazfitBipService;
import nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBand2Service;
import nodomain.freeyourgadget.gadgetbridge.service.btle.BLETypeConversions;
import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder;
import nodomain.freeyourgadget.gadgetbridge.service.btle.actions.WaitAction;
import nodomain.freeyourgadget.gadgetbridge.service.devices.miband2.MiBand2Support;
import nodomain.freeyourgadget.gadgetbridge.util.GB;
/**
* An operation that fetches activity data. For every fetch, a new operation must
* be created, i.e. an operation may not be reused for multiple fetches.
*/
public class FetchSportsSummaryOperation extends AbstractFetchOperation {
private static final Logger LOG = LoggerFactory.getLogger(FetchSportsSummaryOperation.class);
// private List<MiBandActivitySample> samples = new ArrayList<>(60*24); // 1day per default
private byte lastPacketCounter;
public FetchSportsSummaryOperation(MiBand2Support support) {
super(support);
}
@Override
protected void startFetching(TransactionBuilder builder) {
GregorianCalendar sinceWhen = getLastSuccessfulSyncTime();
// builder.write(characteristicFetch, BLETypeConversions.join(new byte[] {
// MiBand2Service.COMMAND_ACTIVITY_DATA_START_DATE,
// AmazfitBipService.COMMAND_ACTIVITY_DATA_TYPE_SPORTS_SUMMARIES},
// getSupport().getTimeBytes(sinceWhen, TimeUnit.MINUTES)));
// builder.add(new WaitAction(1000)); // TODO: actually wait for the success-reply
// builder.notify(characteristicActivityData, true);
// builder.write(characteristicFetch, new byte[] { MiBand2Service.COMMAND_FETCH_DATA });
}
@Override
protected void handleActivityFetchFinish() {
LOG.info("Fetching activity data has finished round " + fetchCount);
// GregorianCalendar lastSyncTimestamp = saveSamples();
// if (lastSyncTimestamp != null && needsAnotherFetch(lastSyncTimestamp)) {
// try {
// startFetching();
// return;
// } catch (IOException ex) {
// LOG.error("Error starting another round of fetching activity data", ex);
// }
// }
super.handleActivityFetchFinish();
}
@Override
public boolean onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
LOG.warn("characteristic read: " + characteristic.getUuid() + ": " + Logging.formatBytes(characteristic.getValue()));
return super.onCharacteristicRead(gatt, characteristic, status);
}
/**
* Method to handle the incoming activity data.
* There are two kind of messages we currently know:
* - the first one is 11 bytes long and contains metadata (how many bytes to expect, when the data starts, etc.)
* - the second one is 20 bytes long and contains the actual activity data
* <p/>
* The first message type is parsed by this method, for every other length of the value param, bufferActivityData is called.
*
* @param value
*/
@Override
protected void handleActivityNotif(byte[] value) {
LOG.warn("sports data: " + Logging.formatBytes(value));
if (!isOperationRunning()) {
LOG.error("ignoring activity data notification because operation is not running. Data length: " + value.length);
getSupport().logMessageContent(value);
return;
}
if ((value.length % 4) == 1) {
if ((byte) (lastPacketCounter + 1) == value[0] ) {
lastPacketCounter++;
bufferActivityData(value);
} else {
GB.toast("Error fetching activity data, invalid package counter: " + value[0], Toast.LENGTH_LONG, GB.ERROR);
handleActivityFetchFinish();
return;
}
} else {
GB.toast("Error fetching activity data, unexpected package length: " + value.length, Toast.LENGTH_LONG, GB.ERROR);
LOG.warn("Unexpected activity data: " + Logging.formatBytes(value));
}
}
/**
* Creates samples from the given 17-length array
* @param value
*/
@Override
protected void bufferActivityData(byte[] value) {
// TODO: implement
// int len = value.length;
//
// if (len % 4 != 1) {
// throw new AssertionError("Unexpected activity array size: " + len);
// }
//
// for (int i = 1; i < len; i+=4) {
// }
}
@Override
protected String getLastSyncTimeKey() {
return getDevice().getAddress() + "_" + "lastSportsSyncTimeMillis";
}
protected GregorianCalendar getLastSuccessfulSyncTime() {
// FIXME: remove this!
GregorianCalendar calendar = BLETypeConversions.createCalendar();
calendar.add(Calendar.DAY_OF_MONTH, -1);
return calendar;
}
}

View File

@ -97,6 +97,7 @@ public class UpdateFirmwareOperation extends AbstractMiBand2Operation {
UUID characteristicUUID = characteristic.getUuid();
if (fwCControlChar.getUuid().equals(characteristicUUID)) {
handleNotificationNotif(characteristic.getValue());
return true; // don't let anyone else handle it
} else {
super.onCharacteristicChanged(gatt, characteristic);
}
@ -134,7 +135,9 @@ public class UpdateFirmwareOperation extends AbstractMiBand2Operation {
}
case MiBand2Service.COMMAND_FIRMWARE_CHECKSUM: {
if (getFirmwareInfo().getFirmwareType() == FirmwareType.FIRMWARE) {
getSupport().onReboot();
TransactionBuilder builder = performInitialized("reboot");
getSupport().sendReboot(builder);
builder.queue(getQueue());
} else {
GB.updateInstallNotification(getContext().getString(R.string.updatefirmwareoperation_update_complete), false, 100, getContext());
done();
@ -142,6 +145,7 @@ public class UpdateFirmwareOperation extends AbstractMiBand2Operation {
break;
}
case MiBand2Service.COMMAND_FIRMWARE_REBOOT: {
LOG.info("Reboot command successfully sent.");
GB.updateInstallNotification(getContext().getString(R.string.updatefirmwareoperation_update_complete), false, 100, getContext());
// getSupport().onReboot();
done();

View File

@ -498,10 +498,13 @@ public class PebbleProtocol extends GBDeviceProtocol {
if (mFwMajor >= 3) {
// 3.x notification
return encodeBlobdbNotification(id, (int) (ts & 0xffffffffL), title, subtitle, notificationSpec.body, notificationSpec.sourceName, hasHandle, notificationSpec.type, notificationSpec.cannedReplies);
return encodeBlobdbNotification(id, (int) (ts & 0xffffffffL), title, subtitle, notificationSpec.body,
notificationSpec.sourceName, hasHandle, notificationSpec.type, notificationSpec.pebbleColor,
notificationSpec.cannedReplies);
} else if (mForceProtocol || notificationSpec.type != NotificationType.GENERIC_EMAIL) {
// 2.x notification
return encodeExtensibleNotification(id, (int) (ts & 0xffffffffL), title, subtitle, notificationSpec.body, notificationSpec.sourceName, hasHandle, notificationSpec.cannedReplies);
return encodeExtensibleNotification(id, (int) (ts & 0xffffffffL), title, subtitle, notificationSpec.body,
notificationSpec.sourceName, hasHandle, notificationSpec.cannedReplies);
} else {
// 1.x notification on FW 2.X
String[] parts = {title, notificationSpec.body, ts.toString(), subtitle};
@ -922,7 +925,9 @@ public class PebbleProtocol extends GBDeviceProtocol {
return encodeBlobdb(uuid, BLOBDB_INSERT, BLOBDB_PIN, buf.array());
}
private byte[] encodeBlobdbNotification(int id, int timestamp, String title, String subtitle, String body, String sourceName, boolean hasHandle, NotificationType notificationType, String[] cannedReplies) {
private byte[] encodeBlobdbNotification(int id, int timestamp, String title, String subtitle, String body, String sourceName,
boolean hasHandle, NotificationType notificationType, byte backgroundColor,
String[] cannedReplies) {
final short NOTIFICATION_PIN_LENGTH = 46;
final short ACTION_LENGTH_MIN = 10;
@ -933,7 +938,6 @@ public class PebbleProtocol extends GBDeviceProtocol {
}
int icon_id = notificationType.icon;
byte color_id = notificationType.color;
// Calculate length first
byte actions_count;
@ -1023,7 +1027,7 @@ public class PebbleProtocol extends GBDeviceProtocol {
buf.put((byte) 28); // background_color
buf.putShort((short) 1); // length of int
buf.put(color_id);
buf.put(backgroundColor);
// dismiss action
buf.put(dismiss_action_id);

View File

@ -76,22 +76,7 @@ public class GBMusicControlReceiver extends BroadcastReceiver {
}
if (keyCode != -1) {
Prefs prefs = GBApplication.getPrefs();
String audioPlayer = prefs.getString("audio_player", "default");
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
MediaSessionManager mediaSessionManager =
(MediaSessionManager) context.getSystemService(Context.MEDIA_SESSION_SERVICE);
List<MediaController> controllers = mediaSessionManager.getActiveSessions(
new ComponentName(context, NotificationListener.class));
try {
MediaController controller = controllers.get(0);
audioPlayer = controller.getPackageName();
} catch (IndexOutOfBoundsException e) {
System.err.println("IndexOutOfBoundsException: " + e.getMessage());
}
}
String audioPlayer = getAudioPlayer(context);
LOG.debug("keypress: " + musicCmd.toString() + " sent to: " + audioPlayer);
@ -114,4 +99,23 @@ public class GBMusicControlReceiver extends BroadcastReceiver {
context.sendOrderedBroadcast(upIntent, null);
}
}
private String getAudioPlayer(Context context) {
Prefs prefs = GBApplication.getPrefs();
String audioPlayer = prefs.getString("audio_player", "default");
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
MediaSessionManager mediaSessionManager =
(MediaSessionManager) context.getSystemService(Context.MEDIA_SESSION_SERVICE);
List<MediaController> controllers = mediaSessionManager.getActiveSessions(
new ComponentName(context, NotificationListener.class));
try {
MediaController controller = controllers.get(0);
audioPlayer = controller.getPackageName();
} catch (IndexOutOfBoundsException e) {
LOG.error("IndexOutOfBoundsException: " + e.getMessage());
}
}
return audioPlayer;
}
}

View File

@ -0,0 +1,49 @@
/* Copyright (C) 2016-2017 Andreas Shimokawa, Carsten Pfeiffer
This file is part of Gadgetbridge.
Gadgetbridge is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Gadgetbridge is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
package nodomain.freeyourgadget.gadgetbridge.util;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
public class BitmapUtil {
/**
* Get a Bitmap from any given Drawable.
*
* Note that this code will fail if the drawable is 0x0.
*
* @param drawable A Drawable to convert.
* @return A Bitmap representing the drawable.
*/
public static Bitmap convertDrawableToBitmap(Drawable drawable) {
// If whoever made this drawable decided to be nice to us...
if (drawable instanceof BitmapDrawable) {
return ((BitmapDrawable) drawable).getBitmap();
}
Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
drawable.draw(canvas);
return bitmap;
}
}

View File

@ -16,6 +16,8 @@
along with this program. If not, see <http://www.gnu.org/licenses/>. */
package nodomain.freeyourgadget.gadgetbridge.util;
import android.graphics.Color;
public class PebbleUtils {
public static String getPlatformName(String hwRev) {
String platformName;
@ -63,4 +65,29 @@ public class PebbleUtils {
String platformName = getPlatformName(hwRev);
return !"aplite".equals(platformName);
}
/**
* Get the closest Pebble-compatible color from the associated Android Color Integer.
* @param color An Android Color Integer to convert
* @return A byte representing the closest Pebble color.
*/
public static byte getPebbleColor(int color) {
// 85 here is determined by dividing 255 by 3, or reducing an 8-bit color to a 2-bit color. (2^3 = 8)
int colorRed = ((color >> 16) & 0xFF) / 85;
int colorGreen = ((color >> 8) & 0xFF) / 85;
int colorBlue = (color & 0xFF) / 85;
// Bit shifting, woo!
return (byte) ((0b11 << 6) | ((colorRed & 0b11) << 4) | ((colorGreen & 0b11) << 2) | (colorBlue & 0b11));
}
/**
* Get the closest Pebble-compatible color from the associated Hex string.
* @param colorHex A Hex-formatted string (#FFDD00) to convert.
* @return A byte representing the closest Pebble color.
*/
public static byte getPebbleColor(String colorHex) {
return getPebbleColor(Color.parseColor(colorHex));
}
}

View File

@ -0,0 +1,41 @@
<?xml version='1.0' encoding='UTF-8'?>
<resources><string name="action_settings">Asetukset</string>
<string name="controlcenter_fetch_activity_data">Synkronisoi</string>
<string name="controlcenter_find_device">Löydä kadonnut laite</string>
<string name="app_name">Gadgetbridge</string>
<string name="title_activity_controlcenter">Gadgetbridge</string>
<string name="action_quit">Sulje</string>
<string name="action_donate">Lahjoita</string>
<string name="controlcenter_take_screenshot">Ota ruutukaappaus</string>
<string name="controlcenter_disconnect">Katkaise yhteys</string>
<string name="controlcenter_delete_device">Poista laite</string>
<string name="controlcenter_delete_device_name">Poista %1$s</string>
<string name="controlcenter_delete_device_dialogmessage">Tämä toiminto poistaa laitteen ja kaikki siihen liittyvät tiedot!</string>
<string name="controlcenter_navigation_drawer_open">Avaa navigointivetolaatikko</string>
<string name="controlcenter_navigation_drawer_close">Sulje navigointivetolaatikko</string>
<string name="controlcenter_snackbar_need_longpress">Paina korttia pitkään katkaistaksesi yhteyden</string>
<string name="controlcenter_snackbar_disconnecting">Yhteyttä katkaistaan</string>
<string name="controlcenter_snackbar_connecting">Yhdistetään</string>
<string name="controlcenter_snackbar_requested_screenshot">Otataan ruutukaappausta laitteesta</string>
<string name="title_activity_appmanager">Sovellusten hallinta</string>
<string name="appmanager_cached_watchapps_watchfaces">Välimuistissa olevat sovellukset</string>
<string name="appmanager_installed_watchapps">Asennetut sovellukset</string>
<string name="appmanager_installed_watchfaces">Asennetut kellotaulut</string>
<string name="appmananger_app_delete">Poista</string>
<string name="appmananger_app_delete_cache">Poista laitteesta ja välimuistista</string>
<string name="appmananger_app_reinstall">Asenna uudelleen</string>
<string name="appmanager_app_openinstore">Etsi Pebble Appstoresta</string>
<string name="appmanager_health_activate">Aktivoi</string>
<string name="appmanager_health_deactivate">Poista käytöstä</string>
<string name="appmanager_hrm_activate">Aktivoi sykemittari</string>
<string name="appmanager_hrm_deactivate">Poista sykemittari käytöstä</string>
<string name="appmanager_weather_activate">Aktivoi järjestelmän sääsovellus</string>
<string name="appmanager_weather_deactivate">Ota järjestelmän sääsovellus pois käytöstä</string>
<string name="appmanager_weather_install_provider">Asenna sääilmoitussovellus</string>
<string name="app_configure">Määritä</string>
<string name="app_move_to_top">Siirrä ylös</string>
</resources>

View File

@ -186,7 +186,7 @@
<string name="pairing_already_bonded">Déjà lié avec %1$s (%2$s), connexion…</string>
<string name="message_cannot_pair_no_mac">Aucune adresse MAC fournie, ne peut être appairé.</string>
<string name="preferences_category_device_specific_settings">Paramètres spécifiques à l\'appareil </string>
<string name="preferences_miband_settings">Paramètres Mi Band</string>
<string name="preferences_miband_settings">Paramètres Mi Band / Bip</string>
<string name="male">Homme</string>
<string name="female">Femme</string>
<string name="other">Autre</string>
@ -383,7 +383,7 @@ NOTE: la base de données sera bien évidement plus grande !</string>
<string name="weather_notification_label">Assurez vous que ce thème soit activé dans l\'application de notification de la météo pour recevoir les informations sur votre Pebble.\n\nAucune configuration n\'est requise.\n\nVous pouvez activer l\'application météo système de votre Pebble depuis la configuration de l\'application.\n\nLes watchfaces supportées afficheront la météo automatiquement.</string>
<string name="pref_title_setup_bt_pairing">Activer le jumelage Bluetooth</string>
<string name="pref_summary_setup_bt_pairing">Désactivez ceci si vous avez des problèmes de connexion</string>
<string name="unit_metric">Mesure</string>
<string name="unit_metric">Métrique</string>
<string name="unit_imperial">Impériale</string>
<string name="timeformat_24h">24H</string>
<string name="timeformat_am_pm">AM/PM</string>

View File

@ -0,0 +1,490 @@
<?xml version='1.0' encoding='UTF-8'?>
<resources><string name="app_name">Gadgetbridge</string>
<string name="title_activity_controlcenter">Gadgetbridge</string>
<string name="action_settings">Axustes</string>
<string name="action_debug">Depuración</string>
<string name="action_quit">Saír</string>
<string name="action_donate">Doar</string>
<string name="controlcenter_fetch_activity_data">Sincronizar</string>
<string name="controlcenter_start_sleepmonitor">Monitor de sono (Alpha)</string>
<string name="controlcenter_find_device">Atopar dispositivo perdido</string>
<string name="controlcenter_take_screenshot">Capturar pantalla</string>
<string name="controlcenter_disconnect">Desconectar</string>
<string name="controlcenter_delete_device">Borrar dispositivo</string>
<string name="controlcenter_delete_device_name">Borrar %1$s</string>
<string name="controlcenter_delete_device_dialogmessage">Borrarás o dispositivo e todos os datos asociados!</string>
<string name="controlcenter_navigation_drawer_open">Abrir menú de navegación</string>
<string name="controlcenter_navigation_drawer_close">Pechar menú de navegación</string>
<string name="controlcenter_snackbar_need_longpress">Manter pulsado o icono para desconectar</string>
<string name="controlcenter_snackbar_disconnecting">Desconectando</string>
<string name="controlcenter_snackbar_connecting">Conectando</string>
<string name="controlcenter_snackbar_requested_screenshot">Capturando pantalla do dispositivo</string>
<string name="title_activity_debug">Depurar</string>
<string name="title_activity_appmanager">Xestor de App</string>
<string name="appmanager_cached_watchapps_watchfaces">Apps en caché</string>
<string name="appmanager_installed_watchapps">Apps instaladas</string>
<string name="appmanager_installed_watchfaces">Visores instalados</string>
<string name="appmananger_app_delete">Borrar</string>
<string name="appmananger_app_delete_cache">Borrar e retirar da caché</string>
<string name="appmananger_app_reinstall">Reinstalar</string>
<string name="appmanager_app_openinstore">Buscar na Appstore de Pebble</string>
<string name="appmanager_health_activate">Activar</string>
<string name="appmanager_health_deactivate">Desactivar</string>
<string name="appmanager_hrm_activate">Activar Monitor de Ritmo Cardíaco</string>
<string name="appmanager_hrm_deactivate">Desactivar Monitor de Ritmo Cardíaco</string>
<string name="appmanager_weather_activate">Activar app de clima do sistema</string>
<string name="appmanager_weather_deactivate">Desactivar app de clima do sistema</string>
<string name="appmanager_weather_install_provider">Instalar a app de notificacións do clima</string>
<string name="app_configure">Configurar</string>
<string name="app_move_to_top">Mover para arriba</string>
<string name="title_activity_appblacklist">Bloqueo de notificacións</string>
<string name="title_activity_calblacklist">Calendarios bloqueados</string>
<string name="title_activity_fw_app_insaller">Instalador de FW/App</string>
<string name="fw_upgrade_notice">Está a piques de instalar o firmware %s no lugar do actual na súa Mi Band.</string>
<string name="fw_multi_upgrade_notice">Está a piques de instalar os firmwares %1$s e %2$s no lugar dos que están actualmente na súa Mi Band.</string>
<string name="miband_firmware_known">Este firmware foi probado e é compatíbel co Gadgetbridge.</string>
<string name="miband_firmware_unknown_warning">Este firmware non foi probado e pode non ser compatíbel co Gadgetbridge.
\n
\nÉ preferíbel que NON o instale na súa Mi Band!</string>
<string name="miband_firmware_suggest_whitelist">Se aínda así quere proceder e todo continúa a funcionar normalmente, por favor avise aos programadores do Gadgetbridge para permitir o firmware versión: %s</string>
<string name="title_activity_settings">Axustes</string>
<string name="pref_header_general">Axustes xerais</string>
<string name="pref_title_general_autoconnectonbluetooth">Conectar ao dispositivo ao activar o Bluetooth</string>
<string name="pref_title_general_autostartonboot">Iniciar automaticamente</string>
<string name="pref_title_general_autocreonnect">Reconectar automaticamente</string>
<string name="pref_title_audo_player">Reprodutor de audio preferido</string>
<string name="pref_default">Predefinido</string>
<string name="pref_header_datetime">Data e Hora</string>
<string name="pref_title_datetime_syctimeonconnect">Sincronizar hora</string>
<string name="pref_summary_datetime_syctimeonconnect">Sincronizar hora ao conectar ou ao cambiar o fuso horario no android</string>
<string name="pref_title_theme">Tema</string>
<string name="pref_theme_light">Claro</string>
<string name="pref_theme_dark">Escuro</string>
<string name="pref_title_language">Idioma</string>
<string name="pref_title_minimize_priority">Ocultar a notificación de Gadgetbridge</string>
<string name="pref_summary_minimize_priority_off">Amosar icono na barra de estado e notificación na pantalla de bloqueo</string>
<string name="pref_summary_minimize_priority_on">Ocultar icono na barra de estado e notificación na pantalla de bloqueo</string>
<string name="pref_header_notifications">Notificacións</string>
<string name="pref_title_notifications_repetitions">Repeticións</string>
<string name="pref_title_notifications_call">Chamadas telefónicas</string>
<string name="pref_title_notifications_sms">SMS</string>
<string name="pref_title_notifications_pebblemsg">Mensaxes de Pebble</string>
<string name="pref_summary_notifications_pebblemsg">Soporte para aplicacións que envían notificacións a Pebble através de PebbleKit.</string>
<string name="pref_title_notifications_generic">Soporte para notificacións xenéricas</string>
<string name="pref_title_whenscreenon">... tamén coa pantalla acesa</string>
<string name="pref_title_notification_filter">Non Molestar</string>
<string name="pref_summary_notification_filter">Parar notificacións indesexadas baseándose no modo Non Molestar</string>
<string name="pref_title_transliteration">Transliteración</string>
<string name="pref_summary_transliteration">Activar isto se o dispositivo non ten soporte para o seu idioma</string>
<string name="always">Sempre</string>
<string name="when_screen_off">Cando a pantalla está apagada</string>
<string name="never">Nunca</string>
<string name="pref_header_privacy">Privacidade</string>
<string name="pref_title_call_privacy_mode">Modo de privacidade de chamada</string>
<string name="pref_call_privacy_mode_off">Amosar nome e número</string>
<string name="pref_call_privacy_mode_name">Ocultar nome pero amosar número</string>
<string name="pref_call_privacy_mode_number">Ocultar número pero amosar nome</string>
<string name="pref_call_privacy_mode_complete">Ocultar nome e número</string>
<string name="pref_blacklist">Bloquear Apps</string>
<string name="pref_blacklist_calendars">Bloquear Calendarios</string>
<string name="pref_header_cannned_messages">Histórico de mensaxes</string>
<string name="pref_title_canned_replies">Respostas</string>
<string name="pref_title_canned_reply_suffix">Sufixo común</string>
<string name="pref_title_canned_messages_dismisscall">Rexeitar chamada</string>
<string name="pref_title_canned_messages_set">Actualizar no Pebble</string>
<string name="pref_header_development">Opcións de desenvolvedor</string>
<string name="pref_title_development_miaddr">Enderezo do MiBand</string>
<string name="pref_title_pebble_settings">Axustes do Pebble</string>
<string name="pref_header_activitytrackers">Monitores de actividade</string>
<string name="pref_title_pebble_activitytracker">Monitor de actividade preferido</string>
<string name="pref_title_pebble_sync_health">Sincronizar con Pebble Health</string>
<string name="pref_title_pebble_sync_misfit">Sincronizar con Misfit</string>
<string name="pref_title_pebble_sync_morpheuz">Sincronizar con Morpheuz</string>
<string name="pref_title_enable_outgoing_call">Soporte para chamadas saíntes</string>
<string name="pref_title_enable_pebblekit">Permitir acceso a Apps Android de terceiros</string>
<string name="pref_summary_enable_pebblekit">Habilitar soporte experimental para Apps Android que usen PebbleKit</string>
<string name="pref_title_sunrise_sunset">Mencer e solpor</string>
<string name="pref_summary_sunrise_sunset">Enviar mencer e solpor baseado na localización do Pebble</string>
<string name="pref_title_enable_calendar_sync">Sincronizar calendario</string>
<string name="pref_title_autoremove_notifications">Borrar automaticamente as notificacións rexeitadas</string>
<string name="pref_title_pebble_privacy_mode">Modo de privacidade</string>
<string name="pref_pebble_privacy_mode_off">Notificacións normais</string>
<string name="pref_pebble_privacy_mode_complete">Só amosar o icono de notificación</string>
<string name="pref_header_location">Localización</string>
<string name="pref_title_location_aquire">Obter ubicación</string>
<string name="pref_title_location_latitude">Latitude</string>
<string name="pref_title_location_longitude">Lonxitude</string>
<string name="pref_title_location_keep_uptodate">Manter actualizada a ubicación</string>
<string name="toast_enable_networklocationprovider">Por favor, active a ubicación por rede</string>
<string name="toast_aqurired_networklocation">ubicación obtida</string>
<string name="pref_title_pebble_forceprotocol">Forzar o protocolo de notificación</string>
<string name="pref_summary_pebble_forceprotocol">Esta opción forza o uso do protocolo de notificación máis recente dependendo da versión do firmware. HABILITE SE SABE O QUE ESTÁ FACENDO!</string>
<string name="pref_title_pebble_forceuntested">Habilitar características non probadas</string>
<string name="pref_title_pebble_forcele">Preferir sempre BLE</string>
<string name="pref_title_pebble_enable_applogs">Activar rexistro das Apps do dispositivo</string>
<string name="pref_summary_pebble_enable_applogs">Causa que os rexistros das apps do reloxo sexan gardados polo Gadgetbridge (necesita reconectar)</string>
<string name="pref_title_pebble_reconnect_attempts">Intentos de reconexión</string>
<string name="pref_title_unit_system">Unidades</string>
<string name="pref_title_timeformat">Formato de hora</string>
<string name="pref_title_screentime">Tempo de pantalla acesa</string>
<string name="prefs_title_all_day_heart_rate">Medición da frecuencia cardíaca durante todo o día</string>
<string name="not_connected">Non conectado</string>
<string name="connecting">Conectando</string>
<string name="connected">Conectado</string>
<string name="unknown_state">Estado descoñecido</string>
<string name="_unknown_">(descoñecido)</string>
<string name="test">Probar</string>
<string name="test_notification">Probar notificación</string>
<string name="this_is_a_test_notification_from_gadgetbridge">Esta é unha notificación de proba desde Gadgetbridge</string>
<string name="bluetooth_is_not_supported_">O Bluetooth non está soportado.</string>
<string name="bluetooth_is_disabled_">O Bluetooh está desactivado.</string>
<string name="tap_connected_device_for_app_mananger">Toque nun dispositivo conectado para xestionar as Apps</string>
<string name="tap_connected_device_for_activity">Toque nun dispositivo conectado para ver a actividade</string>
<string name="tap_connected_device_for_vibration">Toque nun dispositivo conectado para facelo Vibrar</string>
<string name="tap_a_device_to_connect">Toque nun dispositivo para conectar</string>
<string name="cannot_connect_bt_address_invalid_">Non foi posíbel conectar. Enderezo Bluetooth inválido?</string>
<string name="gadgetbridge_running">Gadgetbridge en execución</string>
<string name="installing_binary_d_d">Instalando binario %1$d/%2$d</string>
<string name="installation_failed_">Fallou a instalación</string>
<string name="installation_successful">Instalación correcta</string>
<string name="initialized">inicializado</string>
<string name="appversion_by_creator">%1$s de %2$s</string>
<string name="title_activity_discovery">Descubrir dispositivos</string>
<string name="discovery_stop_scanning">Parar a busca</string>
<string name="discovery_start_scanning">Comezar a busca</string>
<string name="action_discover">Conectar novo dispositivo</string>
<string name="device_with_rssi">%1$s (%2$s)</string>
<string name="title_activity_android_pairing">Emparellar dispositivo</string>
<string name="android_pairing_hint">Usar o menú de emparellamento Bluetooth de Android para vincular o dispositivo.</string>
<string name="title_activity_mi_band_pairing">Emparella a túa MiBand</string>
<string name="pairing">Emparellando con %s…</string>
<string name="pairing_creating_bond_with">Creando vínculo con %1$s (%2$s)</string>
<string name="pairing_unable_to_pair_with">Incapaz de emparellar con %1$s (%2$s)</string>
<string name="preferences_category_device_specific_settings">Axustes específicos do dispositivo</string>
<string name="pref_summary_enable_outgoing_call">Deshabilitar isto tamén impedirá o Pebble 2/LE vibrar en chamadas saíntes</string>
<string name="pref_header_pebble_timeline">Timeline do Pebble</string>
<string name="pref_summary_enable_calendar_sync">Enviar os eventos do calendario ao timeline</string>
<string name="pref_summary_autoremove_notifications">As notificacións borranse automáticamente do Pebble cando se rexeitan en Android</string>
<string name="pref_pebble_privacy_mode_content">Desplaza a notificación fora da pantalla</string>
<string name="pref_summary_location_keep_uptodate">Intentar obter a ubicación durante a execución, usar a ubicación almacenada como respaldo</string>
<string name="pref_summary_pebble_forceuntested">Activar características non probadas. ¡ACTIVAO SÓ SE SABES O QUE FAS!</string>
<string name="pref_title_pebble_mtu_limit">Pebble 2/LE límite de GATT MTU</string>
<string name="pref_summary_pebble_mtu_limit">Se o teu Pebble 2/Pebble LE non funciona correctamente, proba esta opción para limitar o MTU (rango válido 20512)</string>
<string name="pref_title_pebble_always_ack_pebblekit">Anticipar confirmacións do PebbleKit</string>
<string name="preferences_hplus_settings">Axustes de HPlus/Makibes</string>
<string name="firmware_install_warning">ESTÁS INTENTANDO INSTALAR UN FIRMWARE, CONTINÚA BAIXO A TÚA RESPONSABILIDADE
\n
\n
\nEste firmware é para a revisión de HW: %s</string>
<string name="app_install_info">Estás a piques de instalar a seguinte app:
\n
\n
\n%1$s Versión %2$s de %3$s
\n</string>
<string name="n_a">N/D</string>
<string name="pairing_in_progress">Asociación en progreso: %1$s (%2$s)</string>
<string name="pairing_already_bonded">Xa asociado con %1$s (%2$s), conectando …</string>
<string name="message_cannot_pair_no_mac">Nengún enderezo MAC fornecido, non é posíbel emparellar.</string>
<string name="preferences_miband_settings">Axustes de MiBand / Bip</string>
<string name="male">Home</string>
<string name="female">Muller</string>
<string name="other">Outro</string>
<string name="left">Esquerda</string>
<string name="right">Dereita</string>
<string name="miband_pairing_using_dummy_userdata">Non se proporcionaron datos de usuario válidos, entrementres usaranse dados ficticios.</string>
<string name="miband_pairing_tap_hint">Cando a súa MiBand vibre e parpadee, toque nela algunhas veces seguidas.</string>
<string name="appinstaller_install">Instalar</string>
<string name="discovery_connected_devices_hint">Torne o seu dispositivo visíbel. Os dispositivos actualmente vinculados non son normalmente descubertos. Active a localización (i.e, GPS) no Android 6+. Desactive tamén a Protección da Privacidade para o Gadgetbridge, pois esta poderá bloquear e levar ao reinicio do seu teléfono. Se despois de algúns minutos o dispositivo non foi encontrado, tente outra vez após reiniciar o teléfono.</string>
<string name="discovery_note">Nota:</string>
<string name="candidate_item_device_image">Imaxe do dispositivo</string>
<string name="miband_prefs_alias">Nome/Alcume</string>
<string name="pref_header_vibration_count">Cantidade de vibracións</string>
<string name="title_activity_sleepmonitor">Monitor de sono</string>
<string name="pref_write_logfiles">Escreber arquivos de rexistro</string>
<string name="initializing">Inicializando</string>
<string name="busy_task_fetch_activity_data">Adquirindo datos de actividade</string>
<string name="sleep_activity_date_range">De %1$s até %2$s</string>
<string name="miband_prefs_wearside">De que lado a usa?</string>
<string name="pref_screen_vibration_profile">Perfil de vibración</string>
<string name="vibration_profile_staccato">Moi curto</string>
<string name="vibration_profile_short">Curto</string>
<string name="vibration_profile_medium">Medio</string>
<string name="vibration_profile_long">Longo</string>
<string name="vibration_profile_waterdrop">Moi longo</string>
<string name="vibration_profile_ring">Timbre</string>
<string name="vibration_profile_alarm_clock">Alarma</string>
<string name="miband_prefs_vibration">Vibración</string>
<string name="vibration_try">Probar</string>
<string name="pref_screen_notification_profile_sms">Notificación de SMS</string>
<string name="pref_header_vibration_settings">Axustes de vibración</string>
<string name="pref_screen_notification_profile_generic">Notificación xenérica</string>
<string name="pref_screen_notification_profile_email">Notificación de correo electrónico</string>
<string name="pref_screen_notification_profile_incoming_call">Notificación de chamada entrante</string>
<string name="pref_screen_notification_profile_generic_chat">Conversas</string>
<string name="pref_screen_notification_profile_generic_navigation">Navegación</string>
<string name="pref_screen_notification_profile_generic_social">Rede social</string>
<string name="stats_title">Zonas de velocidade</string>
<string name="stats_x_axis_label">Minutos totais</string>
<string name="stats_y_axis_label">Pasos por minuto</string>
<string name="control_center_find_lost_device">Atopar dispositivo perdido</string>
<string name="control_center_cancel_to_stop_vibration">Cancelar para deter a vibración.</string>
<string name="title_activity_charts">A túa actividade</string>
<string name="title_activity_set_alarm">Configurar alarmas</string>
<string name="controlcenter_start_configure_alarms">Configurar alarmas</string>
<string name="title_activity_alarm_details">Detalles da alarma</string>
<string name="alarm_sun_short">Dom</string>
<string name="alarm_mon_short">Lun</string>
<string name="alarm_tue_short">Mar</string>
<string name="alarm_wed_short">Mér</string>
<string name="alarm_thu_short">Xov</string>
<string name="alarm_fri_short">Ven</string>
<string name="alarm_sat_short">Sáb</string>
<string name="alarm_smart_wakeup">Espertador intelixente</string>
<string name="user_feedback_miband_set_alarms_failed">Houbo un erro configurando as alarmas, por favor téntao de novo!</string>
<string name="user_feedback_miband_set_alarms_ok">Alarmas enviadas ao dispositivo!</string>
<string name="chart_no_data_synchronize">Sen datos. Sincronizar dispositivo?</string>
<string name="user_feedback_miband_activity_data_transfer">A piques de transferir %1$s de datos desde %2$s</string>
<string name="miband_prefs_fitness_goal">Obxectivo de pasos diarios</string>
<string name="dbaccess_error_executing">Erro executando \'%1$s\'</string>
<string name="controlcenter_start_activitymonitor">A túa actividade (ALPHA)</string>
<string name="cannot_connect">Imposíbel conectar: %1$s</string>
<string name="installer_activity_unable_to_find_handler">Non foi posíbel atopar un controlador para instalar o arquivo.</string>
<string name="pbw_install_handler_unable_to_install">Imposíbel instalar o arquivo fornecido: %1$s</string>
<string name="pbw_install_handler_hw_revision_mismatch">Non é posíbel instalar o firmware fornecido: non corresponde coa versión do hardware do seu Pebble.</string>
<string name="installer_activity_wait_while_determining_status">Por favor, agarda mentres se determina o estado da instalación…</string>
<string name="notif_battery_low_title">Dispositivo con batería baixa!</string>
<string name="notif_battery_low_percent">%1$s bateria restante: %2$s%%</string>
<string name="notif_battery_low_bigtext_last_charge_time">Última carga: %s
\n</string>
<string name="notif_battery_low_bigtext_number_of_charges">Número de cargas: %s</string>
<string name="sleepchart_your_sleep">O teu sono</string>
<string name="weeksleepchart_sleep_a_week">Sono na semana</string>
<string name="weeksleepchart_today_sleep_description">Sono hoxe, obxectivo: %1$s</string>
<string name="weekstepschart_steps_a_week">Pasos na semana</string>
<string name="activity_sleepchart_activity_and_sleep">A túa actividade e sono</string>
<string name="updating_firmware">Anovando Firmware…</string>
<string name="fwapp_install_device_not_ready">O arquivo non pode ser instalado, o dispositivo non está preparado.</string>
<string name="miband_installhandler_miband_firmware">Firmware do Mi Band %1$s</string>
<string name="amazfitbip_firmware">Firmware do Amazfit Bip %1$s</string>
<string name="miband_fwinstaller_compatible_version">Versión compatíbel</string>
<string name="miband_fwinstaller_untested_version">Versión sen probar!</string>
<string name="fwappinstaller_connection_state">Conexión ao dispositivo: %1$s</string>
<string name="pbw_installhandler_pebble_firmware">Firmware do Pebble %1$s</string>
<string name="pbwinstallhandler_correct_hw_revision">Revisión de hardware correcta</string>
<string name="pbwinstallhandler_incorrect_hw_revision">Revisión de hardware inválida!</string>
<string name="pbwinstallhandler_app_item">%1$s (%2$s)</string>
<string name="updatefirmwareoperation_updateproblem_do_not_reboot">Ocorreu un erro coa transferencia do firmware. NON REINICIE a súa Mi Band!</string>
<string name="updatefirmwareoperation_metadata_updateproblem">Problemas ao transferir os metadados do firmware</string>
<string name="updatefirmwareoperation_update_complete">Instalación do Firmware completa</string>
<string name="updatefirmwareoperation_update_complete_rebooting">Instalación do Firmware completa, reiniciando o dispositivo…</string>
<string name="updatefirmwareoperation_write_failed">Fallou a escritura do firmware</string>
<string name="chart_steps">Pasos</string>
<string name="calories">Calorías</string>
<string name="distance">Distancia</string>
<string name="clock">Reloxo</string>
<string name="heart_rate">Ritmo cardíaco</string>
<string name="battery">Batería</string>
<string name="liveactivity_live_activity">Actividade en tempo real</string>
<string name="weeksteps_today_steps_description">Pasos hoxe, obxectivo: %1$s</string>
<string name="pref_title_dont_ack_transfer">Non confirmar a transferencia de datos de actividade</string>
<string name="pref_summary_dont_ack_transfers">Se os datos de actividade non foran confirmados ao dispositivo, non serán borrados del. Útil se o GB é utilizado en simultáneo con outras aplicacións.</string>
<string name="pref_summary_keep_data_on_device">Manterá os datos na Mi Band mesmo despois da sincronización. Útil se o GB é utilizado en simultáneo con outras aplicacións.</string>
<string name="pref_title_low_latency_fw_update">Usar modo de baixa latencia para anovacións de Firmware</string>
<string name="pref_summary_low_latency_fw_update">Isto pode axudar en dispositivos nos que fallen as actualizacións de firmware</string>
<string name="live_activity_steps_history">Historial de pasos</string>
<string name="live_activity_current_steps_per_minute">Pasos/min actuais</string>
<string name="live_activity_total_steps">Pasos totais</string>
<string name="live_activity_steps_per_minute_history">Historial de pasos por minuto</string>
<string name="live_activity_start_your_activity">Comeza a túa actividade</string>
<string name="abstract_chart_fragment_kind_activity">Actividade</string>
<string name="abstract_chart_fragment_kind_light_sleep">Sono leve</string>
<string name="abstract_chart_fragment_kind_deep_sleep">Sono profundo</string>
<string name="abstract_chart_fragment_kind_not_worn">Sen usar</string>
<string name="device_not_connected">Non conectado.</string>
<string name="user_feedback_all_alarms_disabled">Todas as alarmas deshabilitadas</string>
<string name="pref_title_keep_data_on_device">Manter datos de actividade no dispositivo</string>
<string name="miband_fwinstaller_incompatible_version">Firmware incompatíbel</string>
<string name="fwinstaller_firmware_not_compatible_to_device">Este firmware non é compatíbel co dispositivo</string>
<string name="miband_prefs_reserve_alarm_calendar">Alarmas reservadas para próximos eventos</string>
<string name="miband_prefs_hr_sleep_detection">Usar sensor de ritmo cardíaco para mellorar a detección de sono</string>
<string name="miband2_prefs_dateformat">Mi2: Formato de data</string>
<string name="dateformat_time">Hora</string>
<string name="dateformat_date_time">Hora e data</string>
<string name="mi2_prefs_button_actions">Accións do botón</string>
<string name="mi2_prefs_button_actions_summary">Especificar accións para pulsación do botón do Mi Band 2</string>
<string name="mi2_prefs_button_press_count">Conta de pulsacións do botón</string>
<string name="mi2_prefs_button_press_count_summary">Número de pulsacións no botón para activar o envío da mensaxe</string>
<string name="mi2_prefs_button_press_broadcast">Mensaxe a enviar</string>
<string name="mi2_prefs_button_action">Activar acción do botón</string>
<string name="mi2_prefs_button_action_summary">Activar acción para un número definido de pulsacións de botón</string>
<string name="mi2_prefs_button_action_vibrate">Activar vibración da banda</string>
<string name="mi2_prefs_button_action_vibrate_summary">Activar vibración da banda en acción desencadenada por botón</string>
<string name="mi2_prefs_button_press_count_max_delay">Retardo máximo entre pulsacións</string>
<string name="mi2_prefs_button_press_count_max_delay_summary">Retardo máximo en milisegundos entre pulsacións de botón</string>
<string name="mi2_prefs_button_press_count_match_delay">Retardo despois da acción do botón</string>
<string name="mi2_prefs_goal_notification">Notificación de obxectivo</string>
<string name="mi2_prefs_goal_notification_summary">A pulseira vai vibrar cando se acade o obxectivo diario de pasos</string>
<string name="mi2_prefs_display_items">Elementos a amosar</string>
<string name="mi2_prefs_display_items_summary">Escolle os elementos a amosar na pantalla da banda</string>
<string name="mi2_prefs_activate_display_on_lift">Activar pantalla ao levantar</string>
<string name="mi2_prefs_rotate_wrist_to_switch_info">Rodar o pulso para mudar a información</string>
<string name="mi2_prefs_do_not_disturb">Non Molestar</string>
<string name="mi2_prefs_do_not_disturb_summary">A banda non recibirá notificacións mentres está activa</string>
<string name="mi2_prefs_inactivity_warnings">Avisos de inactividade</string>
<string name="mi2_prefs_inactivity_warnings_summary">A pulseira vai vibrar se estiveches inactivo durante algún tempo</string>
<string name="mi2_prefs_inactivity_warnings_threshold">Limite de inactividade (en minutos)</string>
<string name="mi2_prefs_inactivity_warnings_dnd_summary">Desactivar os avisos de inactividade durante un intervalo de tempo</string>
<string name="mi2_prefs_do_not_disturb_start">Hora de inicio</string>
<string name="mi2_prefs_do_not_disturb_end">Hora de fin</string>
<string name="FetchActivityOperation_about_to_transfer_since">A piques de transferir dados desde %1$s</string>
<string name="waiting_for_reconnect">Agardando reconexión</string>
<string name="activity_prefs_about_you">Sobre ti</string>
<string name="activity_prefs_year_birth">Ano de nacemento</string>
<string name="activity_prefs_gender">Xénero</string>
<string name="activity_prefs_height_cm">Altura en cm</string>
<string name="activity_prefs_weight_kg">Peso en kg</string>
<string name="authenticating">Autenticando</string>
<string name="authentication_required">Requerida autenticación</string>
<string name="appwidget_text">ZzZ</string>
<string name="add_widget">Engadir widget</string>
<string name="activity_prefs_sleep_duration">Duración de sono preferida en horas</string>
<string name="appwidget_alarms_set">Unha alarma foi definida para %1$02d:%2$02d</string>
<string name="device_hw">Revisión de hardware: %1$s</string>
<string name="device_fw">Versión de firmware: %1$s</string>
<string name="error_creating_directory_for_logfiles">Erro creando un cartafol para os arquivos de rexistro: %1$s</string>
<string name="DEVINFO_HR_VER">"Versión HW: "</string>
<string name="updatefirmwareoperation_update_in_progress">Anovación de Firmware en progreso</string>
<string name="updatefirmwareoperation_firmware_not_sent">Firmware non enviado</string>
<string name="charts_legend_heartrate">Ritmo cardíaco</string>
<string name="live_activity_heart_rate">Ritmo cardíaco</string>
<string name="pref_title_pebble_health_store_raw">Almacenar rexistro en bruto na base de datos</string>
<string name="action_db_management">Xestión da base de datos</string>
<string name="title_activity_db_management">Xestión da base de datos</string>
<string name="activity_db_management_import_export_explanation">A base de datos usa a seguinte ubicación no seu dispositivo.
\nEsta ubicación é accesíbel para outras aplicacións Android e para o seu ordenador.
\nAtopará as súas bases de datos exportadas (ou a que quere importar) aquí:</string>
<string name="activity_db_management_merge_old_title">Borrar a base de datos antiga</string>
<string name="dbmanagementactivvity_cannot_access_export_path">Non se pode acceder á ruta para exportar . Por favor, contacta cos desenvolvedores.</string>
<string name="dbmanagementactivity_exported_to">Exportado a: %1$s</string>
<string name="dbmanagementactivity_error_exporting_db">Erro ao exportar a base de datos: %1$s</string>
<string name="dbmanagementactivity_error_exporting_shared">Erro exportando as preferencias: %1$s</string>
<string name="dbmanagementactivity_import_data_title">Importar datos?</string>
<string name="dbmanagementactivity_overwrite_database_confirmation">Quere sobreescribir a base de datos actual? Perderanse todos os datos actuais de actividade (de habelos).</string>
<string name="dbmanagementactivity_import_successful">Importado con éxito.</string>
<string name="dbmanagementactivity_error_importing_db">Erro ao importar a base de datos: %1$s</string>
<string name="dbmanagementactivity_error_importing_shared">Erro importando preferencia: %1$s</string>
<string name="dbmanagementactivity_delete_activity_data_title">Borrar datos de actividade?</string>
<string name="dbmanagementactivity_really_delete_entire_db">Realmente quere borrar toda a base de datos? Perderanse todos os seus datos de actividade e a información sobre os seus dispositivos.</string>
<string name="dbmanagementactivity_database_successfully_deleted">Datos eliminados con éxito.</string>
<string name="dbmanagementactivity_db_deletion_failed">Fallou o borrado da base de datos.</string>
<string name="dbmanagementactivity_delete_old_activity_db">Borrar a antiga base de datos de actividade?</string>
<string name="dbmanagementactivity_delete_old_activitydb_confirmation">Está seguro de querer borrar a antiga base de datos de actividade? Perderanse os datos de actividade que non foran importados.</string>
<string name="dbmanagementactivity_old_activity_db_successfully_deleted">Datos antigos de actividade borrados con éxito.</string>
<string name="dbmanagementactivity_old_activity_db_deletion_failed">Fallou o borrado da base de datos de actividades antigas.</string>
<string name="dbmanagementactivity_overwrite">Sobreescribir</string>
<string name="Cancel">Cancelar</string>
<string name="Delete">Borrar</string>
<string name="title_activity_vibration">Vibración</string>
<string name="title_activity_pebble_pairing">Emparellando co Pebble</string>
<string name="pref_title_setup_bt_pairing">Activar o emparellamento Bluetooth</string>
<string name="pref_summary_setup_bt_pairing">Desactiva isto se tes problemas de conexión</string>
<string name="unit_metric">Métrico</string>
<string name="unit_imperial">Imperial</string>
<string name="timeformat_24h">24H</string>
<string name="timeformat_am_pm">AM/PM</string>
<string name="pref_screen_notification_profile_alarm_clock">Espertador</string>
<string name="StringUtils_sender">(%1$s)</string>
<string name="find_device_you_found_it">Atopado!</string>
<string name="miband2_prefs_timeformat">Mi2: formato de hora</string>
<string name="mi2_fw_installhandler_fw53_hint">Debe instalar a versión %1$s antes de instalar este firmware!</string>
<string name="mi2_enable_text_notifications">Notificacións de texto</string>
<string name="mi2_enable_text_notifications_summary">Require firmware &gt;= 1.0.1.28 e Mili_pro.ft* instalado.</string>
<string name="off">Apagado</string>
<string name="mi2_dnd_off">Apagado</string>
<string name="mi2_dnd_automatic">Automático (detección de sono)</string>
<string name="mi2_dnd_scheduled">Axendado (intervalo de tempo)</string>
<string name="discovery_attempting_to_pair">Intentando emparellar con %1$s</string>
<string name="discovery_bonding_failed_immediately">O enlace con %1$s fallou de inmediato.</string>
<string name="discovery_trying_to_connect_to">Intentando conectar con: %1$s</string>
<string name="discovery_enable_bluetooth">Active o Bluetooth para achar dispositivos.</string>
<string name="discovery_successfully_bonded">Correctamente enlazado con %1$s.</string>
<string name="discovery_pair_title">Emparellar con %1$s?</string>
<string name="discovery_yes_pair">Emparellar</string>
<string name="discovery_dont_pair">Non emparellar</string>
<string name="_pebble_watch_open_on_phone">Abrir no teléfono</string>
<string name="_pebble_watch_mute">Silenciar</string>
<string name="_pebble_watch_reply">Responder</string>
<string name="fw_upgrade_notice_amazfitbip">Estás a piques de instalar o firmware %s nas veces do que está actualmente no teu Amazfit Bip.
\n
\nPor favor, asegúrate de instalar o firmware .gps, despois o arquivo .res, e finalmente o binario .fw. O teu reloxo reiniciará despois de instalar o arquivo .fw.
\n
\nNota: non tes que instalar .res e .gps se estes arquivos son os mesmos que os previamente instalados.
\n
\nEXPERIMENTAL, PROCEDE BAIXO A TÚA PROPIA RESPONSABILIDADE</string>
<string name="pref_summary_pebble_forcele">Use soporte experimental do Pebble LE nas veces do Bluetooth clásico, require emparellar un \"Pebble LE\" despois de que nengún LE teña sido conectado</string>
<string name="pref_summary_pebble_always_ack_pebblekit">Isto fará que as mensaxes enviadas para apps de terceiros sexan recoñecidas sempre e inmediatamente</string>
<string name="miband_prefs_device_time_offset_hours">Compensación da hora do dispositivo en horas (para detectar o sono de traballadores a turnos)</string>
<string name="mi2_prefs_button_press_broadcast_summary">Enviar mensaxe despois dun número definido de pulsacións</string>
<string name="mi2_prefs_button_press_count_match_delay_summary">Retardo despois dunha acción do botón (o número está en button_id intent extra) ou ben 0 para efecto inmediato</string>
<string name="pref_summary_pebble_health_store_raw">Se marcado, os datos son almacenados no seu formato orixinal ficando disponíbeis para posterior interpretación. Nota: A base de datos será máis grande!</string>
<string name="pebble_pairing_hint">É esperado que vexa unha notificación de emparellamento no seu dispositivo Android. Se iso non acontece, acceda ás notificacións e acepte a solicitude de emparellamento. Despois acepte igualmente a solicitude de emparellamento no seu Pebble</string>
<string name="weather_notification_label">Asegúrate de que este tema esté activado na aplicación de notificación do clima para obter a información no teu Pebble.
\n
\nNon se require configuración.
\n
\nPodes activar a aplicación meteorolóxica do sistema desde a configuración da app.
\n
\nAs \"watchfaces\" soportadas amosarán a información do clima automáticamente.</string>
<string name="discovery_pair_question">Selecciona Emparellar para emparellar os teus dispositivos. Se isto falla, proba de novo sen emparellar.</string>
</resources>

View File

@ -5,6 +5,7 @@
<string name="action_settings">Impostazioni</string>
<string name="action_debug">Debug</string>
<string name="action_quit">Esci</string>
<string name="action_donate">Donazioni</string>
<string name="controlcenter_fetch_activity_data">Sincronizza</string>
<string name="controlcenter_start_sleepmonitor">Monitoraggio del sonno (ALPHA)</string>
<string name="controlcenter_find_device">Trova dispositivo smarrito</string>
@ -40,6 +41,8 @@
<string name="app_move_to_top">Sposta in cima</string>
<!--Strings related to AppBlacklist-->
<string name="title_activity_appblacklist">Blocco notifiche</string>
<!--Strings related to CalBlacklist-->
<string name="title_activity_calblacklist">Calendari ignorati</string>
<!--Strings related to FwAppInstaller-->
<string name="title_activity_fw_app_insaller">Installazione FW/App</string>
<string name="fw_upgrade_notice">Il firmware %s verrà installato al posto di quello attualmente sulla Mi Band.</string>
@ -74,7 +77,7 @@
<string name="pref_title_notifications_pebblemsg">Messaggi Pebble</string>
<string name="pref_summary_notifications_pebblemsg">Supporto per applicazioni che inviano le notifiche a Pebble usando PebbleKit.</string>
<string name="pref_title_notifications_generic">Notifiche generiche</string>
<string name="pref_title_whenscreenon">…anche se lo schermo è acceso</string>
<string name="pref_title_whenscreenon"> anche se lo schermo è acceso</string>
<string name="pref_title_notification_filter">Non disturbare</string>
<string name="pref_summary_notification_filter">Non inviare notifiche nei periodi configurati come \"non disturbare\".</string>
<string name="pref_title_transliteration">Traslitterazione</string>
@ -108,6 +111,7 @@
<string name="pref_summary_enable_pebblekit">Attiva l\'accesso sperimentale ad applicazioni Android che usano PebbleKit</string>
<string name="pref_title_sunrise_sunset">Alba e tramonto</string>
<string name="pref_summary_sunrise_sunset">Mostra gli orari calcolati per l\'alba e il tramonto sulla timeline</string>
<string name="pref_title_enable_calendar_sync">Sincronizza calendario</string>
<string name="pref_title_autoremove_notifications">Rimuovi automaticamente le notifiche</string>
<string name="pref_summary_autoremove_notifications">Le notifiche vengono rimosse automaticamente dal Pebble dopo averle nascoste sul dispositivo Android</string>
<string name="pref_title_pebble_privacy_mode">Impostazioni privacy</string>
@ -135,6 +139,7 @@
<string name="pref_title_pebble_always_ack_pebblekit">Invia l\'ACK dei messaggi PebbleKit prematuramente</string>
<string name="pref_summary_pebble_always_ack_pebblekit">I messaggi inviati alle applicazioni di terze parti verranno immediatamente confermate</string>
<string name="pref_title_pebble_reconnect_attempts">Tentativi di riconessione</string>
<!--HPlus Preferences-->
<string name="pref_title_unit_system">Unità</string>
<string name="pref_title_timeformat">Formato dell\'orario</string>
<string name="pref_title_screentime">Durata dell\'accensione dello schermo</string>
@ -143,8 +148,6 @@
<string name="not_connected">Non connesso</string>
<string name="connecting">In collegamento</string>
<string name="connected">Connesso</string>
<string name="unknown_state">Stato sconosciuto</string>
<string name="connectionstate_hw_fw">HW: %1$s FW: %2$s</string>
<string name="connectionstate_fw">Versione firmware: %1$s</string>
<string name="_unknown_">(sconosciuto)</string>
<string name="test">Test</string>
@ -219,6 +222,9 @@
<string name="pref_screen_notification_profile_generic_chat">Cha</string>
<string name="pref_screen_notification_profile_generic_navigation">Navigazione</string>
<string name="pref_screen_notification_profile_generic_social">Social Network</string>
<string name="stats_title">Zone di velocità</string>
<string name="stats_x_axis_label">Minuti totali</string>
<string name="stats_y_axis_label">Passi al minuto</string>
<string name="control_center_find_lost_device">Trova dispositivo smarrito</string>
<string name="control_center_cancel_to_stop_vibration">Annulla per fermare la vibrazione</string>
<string name="title_activity_charts">Le tue attività</string>
@ -257,6 +263,7 @@
<string name="updating_firmware">Aggiornamento del Firmware...</string>
<string name="fwapp_install_device_not_ready">Il file non può essere installato, il dispositivo non è pronto.</string>
<string name="miband_installhandler_miband_firmware">Firmware Mi Band: %1$s</string>
<string name="amazfitbip_firmware">Firmware Amazfit Bip %1$s</string>
<string name="miband_fwinstaller_compatible_version">Versione compatibile</string>
<string name="miband_fwinstaller_untested_version">Versione non testata!</string>
<string name="fwappinstaller_connection_state">Connessione al device: %1$s</string>
@ -270,6 +277,11 @@
<string name="updatefirmwareoperation_update_complete_rebooting">Installazione del firmware completata, riavvio del dispositivo...</string>
<string name="updatefirmwareoperation_write_failed">Scrittura del firmware non riuscita</string>
<string name="chart_steps">Passi</string>
<string name="calories">Calorie</string>
<string name="distance">Distanza</string>
<string name="clock">Orologio</string>
<string name="heart_rate">Pulsazioni</string>
<string name="battery">Batteria</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>
@ -296,7 +308,21 @@
<string name="miband_prefs_device_time_offset_hours">Sfasamento dell\'orario per il device (per consentire il rilevamento del sonno per chi lavora a turni)</string>
<string name="miband2_prefs_dateformat">Mi2: formato della data</string>
<string name="dateformat_time">Ora</string>
<string name="dateformat_date_time">Ora e data</string>
<string name="mi2_prefs_goal_notification">Notifica raggiungimento obbiettivi</string>
<string name="mi2_prefs_goal_notification_summary">La band vibrerà una volta raggiunto l\'obbiettivo passi giornalieri</string>
<string name="mi2_prefs_display_items">Elementi mostrati</string>
<string name="mi2_prefs_display_items_summary">Scelta elementi da mostrare sullo schermo della band</string>
<string name="mi2_prefs_activate_display_on_lift">Attiva il display quando sollevato</string>
<string name="mi2_prefs_rotate_wrist_to_switch_info">Rotazione polso per cambiare vista</string>
<string name="mi2_prefs_do_not_disturb">Non disturbare</string>
<string name="mi2_prefs_do_not_disturb_summary">La band non riceverà notifiche quando è attiva</string>
<string name="mi2_prefs_inactivity_warnings">Allarmi inattività</string>
<string name="mi2_prefs_inactivity_warnings_summary">La band vibrerà dopo un determinato periodo di inattività</string>
<string name="mi2_prefs_inactivity_warnings_threshold">Limite inattività (in minuti)</string>
<string name="mi2_prefs_inactivity_warnings_dnd_summary">Disabilita allarmi inattività per un dato intervallo di tempo</string>
<string name="mi2_prefs_do_not_disturb_start">Ora inizio</string>
<string name="mi2_prefs_do_not_disturb_end">Ora fine</string>
<string name="FetchActivityOperation_about_to_transfer_since">Vengono trasferiti dati a partire dal %1$s</string>
<string name="waiting_for_reconnect">in attesa di riconnessione</string>
<string name="activity_prefs_about_you">Informazioni sull\'utilizzatore</string>
@ -327,10 +353,12 @@
<string name="dbmanagementactivvity_cannot_access_export_path">Impossibile accedere al path esterno. Per cortesia contatta gli sviluppatori del progetto.</string>
<string name="dbmanagementactivity_exported_to">Esportato su: %1$s</string>
<string name="dbmanagementactivity_error_exporting_db">Errore esportando il DB: %1$s</string>
<string name="dbmanagementactivity_error_exporting_shared">"Errore nell\'esportazione delle preferenze: %1$s"</string>
<string name="dbmanagementactivity_import_data_title">Importare i dati?</string>
<string name="dbmanagementactivity_overwrite_database_confirmation">Vuoi davvero sovrascrivere il database attuale? Tutte le tue attività saranno perse.</string>
<string name="dbmanagementactivity_import_successful">L\'importazione ha avuto successo.</string>
<string name="dbmanagementactivity_error_importing_db">Errore importando il DB: %1$s</string>
<string name="dbmanagementactivity_error_importing_shared">"Errore nell\'importazione della preferenza: %1$s"</string>
<string name="dbmanagementactivity_delete_activity_data_title">Cancella i dati delle attività?</string>
<string name="dbmanagementactivity_really_delete_entire_db">Vuoi davvero cancellare il database? Tutte le informazioni sulle tue attività e sui tuoi dispositivi saranno perse.</string>
<string name="dbmanagementactivity_database_successfully_deleted">Dati cancellati con successo.</string>
@ -359,26 +387,13 @@
<string name="miband2_prefs_timeformat">Mi2: Formato dell\'orario</string>
<string name="mi2_fw_installhandler_fw53_hint">E\' necessario installare la verione %1$s prima di installare questo firmware!</string>
<string name="mi2_enable_text_notifications">Notifiche</string>
<string name="off">Spento</string>
<string name="action_donate">Dona</string>
<string name="title_activity_calblacklist">Calendari con notifiche bloccate</string>
<string name="pref_blacklist_calendars">Blocca calendari</string>
<string name="pref_title_enable_calendar_sync">Sincronizza calendari</string>
<string name="pref_summary_enable_calendar_sync">Mostra eveti dei calendari sulla timeline</string>
<string name="stats_x_axis_label">Minuti totali</string>
<string name="stats_y_axis_label">Passi al minuto</string>
<string name="calories">Calorie</string>
<string name="distance">Distanza</string>
<string name="battery">Batteria</string>
<string name="dateformat_date_time">Ora e data</string>
<string name="mi2_prefs_goal_notification">Notifica al raggiungimento dell\'obiettivo</string>
<string name="mi2_prefs_goal_notification_summary">Il dispositivo vibrerà quando l\'obiettivo giornaliero di passi viene raggiunto</string>
<string name="mi2_prefs_do_not_disturb">Non disturbare</string>
<string name="dbmanagementactivity_error_exporting_shared">Errore durante l\'export delle preferenze: %1$s</string>
<string name="dbmanagementactivity_error_importing_shared">Errore durante l\'importazione delle preferenze: %1$s</string>
<string name="mi2_enable_text_notifications_summary">"Devono essere installati un firmware &gt;= 1.0.1.28 e Mili_pro.ft*."</string>
</resources>
<string name="mi2_enable_text_notifications_summary">Richiede firmware versione minima 1.9.1.28 e Mili_pro.ft* installati.</string>
<string name="off">spento</string>
<string name="mi2_dnd_off">Spento</string>
<string name="mi2_dnd_automatic">Automatico (rilevamento del sonno)</string>
<string name="discovery_attempting_to_pair">Tentativo di connessione a %1$s in corso</string>
<string name="discovery_bonding_failed_immediately">La connessione con %1$s è subito fallita.</string>
<string name="discovery_trying_to_connect_to">Tentativo di connessione con: %1$s</string>
<string name="discovery_enable_bluetooth">Abilitare Bluetooth per l\'individuazione dei dispositivi.</string>
<string name="discovery_dont_pair">Non connettersi</string>
</resources>

View File

@ -25,8 +25,10 @@
<string name="fw_upgrade_notice">지금 기존의 Mi Band 펌웨어 대신 %s 펌웨어를 설치하려고 합니다.</string>
<string name="fw_multi_upgrade_notice">지금 Mi Band의 기존 펌웨어 대신 %1$s와 %2$s 펌웨어를 설치하려고 합니다.</string>
<string name="miband_firmware_known">이 펌웨어는 테스트를 거쳤고 가젯브릿지와 호환됩니다.</string>
<string name="miband_firmware_unknown_warning">이 펌웨어는 테스트를 거치지 않았고 가젯브릿지와 호환되지 않을 수 있습니다.\n\n Mi Band에 설치하지 않는 것이 좋습니다.</string>
<string name="miband_firmware_suggest_whitelist">여전히 계속 진행하기를 원하고 이후에도 정상적으로 작동하기를 원한다면, %s 화이트리스트 펌웨어 버전을 가젯브릿지 개발자들에게 알려주세요.</string>
<string name="miband_firmware_unknown_warning">이 펌웨어는 테스트를 거치지 않았고 가젯브릿지와 호환되지 않을 수 있습니다.
\n
\nMi Band에 설치하지 않는 것이 좋습니다!</string>
<string name="miband_firmware_suggest_whitelist">여전히 계속 진행하기를 원하고 이후에도 정상적으로 작동하기를 원한다면, %s 화이트리스트 펌웨어 버전을 가젯브릿지 개발자들에게 알려주세요</string>
<!--Strings related to Settings-->
<string name="title_activity_settings">설정</string>
<string name="pref_header_general">일반 설정</string>
@ -55,7 +57,7 @@
<string name="pref_header_development">개발자 옵션</string>
<string name="pref_title_development_miaddr">Mi Band 주소</string>
<string name="pref_title_pebble_settings">Pebble 설정</string>
<string name="pref_title_pebble_activitytracker">선호하는 액티비티 트래커</string>
<string name="pref_title_pebble_activitytracker">선호하는 활동 추적자</string>
<string name="pref_title_enable_pebblekit">제 3자 안드로이드 앱 접근을 허용</string>
<string name="pref_summary_enable_pebblekit">PebbleKit을 사용하는 안드로이드 앱을 실험적으로 지원</string>
<string name="pref_title_pebble_forceprotocol">강제 알림 프로토콜</string>
@ -221,4 +223,108 @@
<string name="Delete">삭제</string>
<!--Strings related to Vibration Activity-->
<!--Strings related to Pebble Pairing Activity-->
</resources>
<string name="action_donate">기부</string>
<string name="controlcenter_delete_device">기기 제거</string>
<string name="controlcenter_delete_device_name">%1$s 제거</string>
<string name="controlcenter_delete_device_dialogmessage">기기와 그와 관련된 모든 데이터를 삭제 할 것입니다!</string>
<string name="controlcenter_navigation_drawer_open">네비게이션 드로어 열기</string>
<string name="controlcenter_navigation_drawer_close">네비게이션 드로어 닫기</string>
<string name="controlcenter_snackbar_need_longpress">카드를 길게 눌러 연결 해제</string>
<string name="controlcenter_snackbar_disconnecting">연결 해제 중</string>
<string name="controlcenter_snackbar_connecting">연결 중</string>
<string name="controlcenter_snackbar_requested_screenshot">기기의 스크린샷을 찍는 중</string>
<string name="appmanager_cached_watchapps_watchfaces">캐시에 저장된 앱들</string>
<string name="appmanager_installed_watchapps">설치된 앱들</string>
<string name="appmanager_installed_watchfaces">설치된 워치페이스</string>
<string name="appmananger_app_delete_cache">삭제하고 캐시에서 제거</string>
<string name="appmanager_app_openinstore">페블 앱스토어에서 검색</string>
<string name="appmanager_hrm_activate">심장 박동수 모니터링 활성화</string>
<string name="appmanager_hrm_deactivate">심장 박동수 모니터링 비활성화</string>
<string name="appmanager_weather_activate">시스템 날씨 앱 활성화</string>
<string name="appmanager_weather_deactivate">시스템 날씨 앱 비활성화</string>
<string name="appmanager_weather_install_provider">날씨 알림 앱 설치</string>
<string name="app_move_to_top">가장 위로 이동</string>
<string name="title_activity_calblacklist">비활성화 된 캘린더들</string>
<string name="fw_upgrade_notice_amazfitbip">지금 기존의 Amazfit Bip에 설치되어 있는 펌웨어 대신 %s 펌웨어를 설치하려고 합니다.
\n
\n.gps 펌웨어를 설치하고 나서 .res 파일을, 그리고 최종적으로 .fw 파일을 설치하세요. 시계가 .fw 파일을 설치한 후 재시작 됩니다.
\n
\n비고: 만약 전에 설치되어 있던 .res 파일과 .gps 파일을 그대로 사용한다면 각 파일을 다시 설치 할 필요는 없습니다.
\n
\n실험적인 기능입니다. 기기 파손의 책임은 사용자에게 있으니 주의해서 진행하세요</string>
<string name="pref_title_general_autostartonboot">자동으로 시작</string>
<string name="pref_title_language">언어</string>
<string name="pref_title_minimize_priority">가젯브릿지 알림 숨김</string>
<string name="pref_summary_minimize_priority_off">상태 표시줄과 잠금 화면 알림에 아이콘이 표시됩니다</string>
<string name="pref_summary_minimize_priority_on">상태 표시줄과 잠금 화면 알림에 아이콘이 표시되지 않습니다</string>
<string name="pref_summary_notifications_pebblemsg">PebbleKit를 사용하여 페블에 알림을 보내는 앱을 지원합니다.</string>
<string name="pref_title_notification_filter">방해 금지 모드</string>
<string name="pref_summary_notification_filter">방해 금지 모드가 활성화 되었을 때 원하지 않는 알림을 보내지 않습니다</string>
<string name="pref_title_transliteration">표기법 변환</string>
<string name="pref_summary_transliteration">만약 장치가 당신이 사용하는 언어의 폰트를 지원하지 않는다면 이 옵션을 활성화 하세요</string>
<string name="pref_header_privacy">프라이버시</string>
<string name="pref_title_call_privacy_mode">전화 프라이버시 모드</string>
<string name="pref_call_privacy_mode_off">이름과 번호를 표시</string>
<string name="pref_call_privacy_mode_name">이름을 숨기지만 번호는 표시</string>
<string name="pref_call_privacy_mode_number">이름을 표시하지만 번호는 숨기기</string>
<string name="pref_call_privacy_mode_complete">이름과 번호를 숨기기</string>
<string name="pref_blacklist_calendars">블랙리스트 캘린더</string>
<string name="pref_header_cannned_messages">상용구</string>
<string name="pref_title_canned_replies">답장</string>
<string name="pref_title_canned_messages_dismisscall">전화 거절</string>
<string name="pref_title_canned_messages_set">페블에서 업데이트</string>
<string name="pref_header_activitytrackers">활동 추적자 설정</string>
<string name="pref_title_pebble_sync_health">Pebble Health 동기화</string>
<string name="pref_title_pebble_sync_misfit">Misfit 동기화</string>
<string name="pref_title_pebble_sync_morpheuz">Morpheuz 동기화</string>
<string name="pref_title_enable_outgoing_call">거는 전화를 지원</string>
<string name="pref_summary_enable_outgoing_call">이 옵션을 비활성화 하면 Pebble 2/LE가 전화를 걸 때 진동하지 않습니다</string>
<string name="pref_header_pebble_timeline">페블 타임라인</string>
<string name="pref_title_sunrise_sunset">일출과 일몰</string>
<string name="pref_summary_sunrise_sunset">현재 위치 기반으로 타임라인에 일출과 일몰 시간을 보여줍니다</string>
<string name="pref_title_enable_calendar_sync">캘린더 동기화</string>
<string name="pref_summary_enable_calendar_sync">타임라인에 캘린더 이벤트를 보여줍니다</string>
<string name="pref_title_autoremove_notifications">닫은 알림을 자동으로 삭제</string>
<string name="pref_summary_autoremove_notifications">안드로이드 기기에서 알림을 닫으면 페블에서도 자동으로 삭제합니다</string>
<string name="pref_title_pebble_privacy_mode">프라이버시 모드</string>
<string name="pref_pebble_privacy_mode_off">일반 알림</string>
<string name="pref_pebble_privacy_mode_content">알림 내용을 바로 보여주지 않습니다</string>
<string name="pref_pebble_privacy_mode_complete">알림 아이콘만 보여줍니다</string>
<string name="pref_header_location">위치</string>
<string name="pref_title_location_aquire">위치 찾기</string>
<string name="pref_title_location_latitude">위도</string>
<string name="pref_title_location_longitude">경도</string>
<string name="pref_title_location_keep_uptodate">위치를 자동으로 업데이트</string>
<string name="pref_summary_location_keep_uptodate">사용 중 현재 위치를 받아오려고 시도합니다. 실패하면 저장된 위치를 사용합니다</string>
<string name="toast_enable_networklocationprovider">네트워크 기반 위치 측량 기능을 활성화 해 주세요</string>
<string name="toast_aqurired_networklocation">위치를 찾음</string>
<string name="pref_title_pebble_forcele">블루투스 저전력 연결을 언제나 선호</string>
<string name="pref_summary_pebble_forcele">일반 블루투스 프로토콜이 아닌 실험적인 블루투스 저전력 연결을 사용합니다. 일반적인 연결을 최소한 한번 한 후 Pebble LE를 페어링 하는 것이 필요합니다</string>
<string name="pref_title_pebble_mtu_limit">Pebble 2/LE GATT MTU 제한</string>
<string name="pref_summary_pebble_mtu_limit">만약 Pebble 2/Pebble LE가 기대한 대로 작동하지 않는다면, 이 설정을 사용하여 MTU를 제한하세요 (20-512까지 설정 가능)</string>
<string name="pref_title_pebble_enable_applogs">시계 앱 로그 활성화</string>
<string name="pref_summary_pebble_enable_applogs">시계 앱들의 로그를 Gadgetbridge가 기록합니다 (재연결 필요)</string>
<string name="pref_title_pebble_always_ack_pebblekit">끝나기 전 미리 PebbleKit 연결에 ACK 보내기</string>
<string name="pref_summary_pebble_always_ack_pebblekit">제 3자 앱으로 보내는 메세지에 언제나 바로 ACK을 보냅니다</string>
<string name="pref_title_unit_system">단위</string>
<string name="pref_title_timeformat">시간 형식</string>
</resources>

View File

@ -0,0 +1,129 @@
<?xml version='1.0' encoding='UTF-8'?>
<resources><string name="app_name">Gadgetbridge</string>
<string name="title_activity_controlcenter">Gadgetbridge</string>
<string name="action_settings">Instellingen</string>
<string name="action_debug">Debug</string>
<string name="action_quit">Sluit af</string>
<string name="action_donate">Doneer</string>
<string name="controlcenter_fetch_activity_data">Synchroniseren</string>
<string name="controlcenter_start_sleepmonitor">Slaap monitor (ALPHA)</string>
<string name="controlcenter_find_device">Zoek verloren Toestel</string>
<string name="controlcenter_take_screenshot">Screenshot maken</string>
<string name="controlcenter_disconnect">Loskoppelen</string>
<string name="controlcenter_delete_device">Apparaat Verwijderen</string>
<string name="controlcenter_delete_device_name">Verwijder %1$s</string>
<string name="controlcenter_delete_device_dialogmessage">Dit zal het apparaat en alle bijbehorende gegevens verwijderen!</string>
<string name="controlcenter_snackbar_need_longpress">Druk lang op de kaart om los te koppelen</string>
<string name="controlcenter_snackbar_disconnecting">Loskoppelen</string>
<string name="controlcenter_snackbar_connecting">Aansluiten</string>
<string name="controlcenter_snackbar_requested_screenshot">Een screenshot maken van het apparaat</string>
<string name="title_activity_debug">Debug</string>
<string name="title_activity_appmanager"></string>
<string name="appmanager_cached_watchapps_watchfaces">Apps in de cache</string>
<string name="appmanager_installed_watchapps">Geïnstalleerde apps</string>
<string name="appmanager_installed_watchfaces">Geïnstalleerde wijzerplaten</string>
<string name="appmananger_app_delete">Verwijder</string>
<string name="appmananger_app_delete_cache">Verwijder en verwijder uit cache</string>
<string name="appmananger_app_reinstall">Installeer</string>
<string name="appmanager_app_openinstore">Zoek in Pebble Appstore</string>
<string name="appmanager_health_activate">Activeren</string>
<string name="appmanager_health_deactivate">deactiveren</string>
<string name="appmanager_hrm_activate">Activeer HRM</string>
<string name="appmanager_hrm_deactivate">Deactiveer HRM</string>
<string name="appmanager_weather_activate">Activeer het systeem weer app</string>
<string name="appmanager_weather_install_provider">Installeer de app voor weerbericht</string>
<string name="app_configure">Configureren</string>
<string name="app_move_to_top">Verplaats naar de top</string>
<string name="title_activity_appblacklist">Notificatie zwarte lijst</string>
<string name="fw_upgrade_notice">U staat op het punt om firmware% s te installeren in plaats van die nu op uw Mi Band staat.</string>
<string name="fw_upgrade_notice_amazfitbip">U staat op het punt om firmware% s te installeren in plaats van die nu op uw Amazfit Bip staat.
\n
\nZorg ervoor dat u de .gps firmware installeert, dan het .res-bestand en tenslotte het .fw-bestand. Uw horloge wordt opnieuw gestart na het installeren van het .fw-bestand.
\n
\nOpmerking: u hoeft geen .res en .gps te installeren als deze bestanden exact hetzelfde zijn als die welke eerder zijn geïnstalleerd.
\n
\nEXPERIMENTEEL, PROCEDURE OP JE EIGEN RISICO</string>
<string name="fw_multi_upgrade_notice">U staat op het punt om firmwares %1$s en %2$s te installeren in plaats van die momenteel op uw Mi Band staat.</string>
<string name="miband_firmware_known">Deze firmware is getest en is compatibel met Gadgetbridge.</string>
<string name="miband_firmware_unknown_warning">Deze firmware is niet getest en is mogelijk niet compatibel met Gadgetbridge.
\n
\nU wordt NIET aangemoedigd om het op uw Mi Band te installeren!</string>
<string name="miband_firmware_suggest_whitelist">Als u nog steeds wilt doorgaan en uw apparaat blijft goed functioneren, vertelt u de ontwikkelaars van Gadgetbridge om de firmware-versie op de goedgekeurde lijst te zetten: %s</string>
<string name="title_activity_settings">Instellingen</string>
<string name="pref_header_general">Algemene instellingen</string>
<string name="pref_title_general_autoconnectonbluetooth">Verbind met apparaat wanneer Bluetooth is ingeschakeld</string>
<string name="pref_title_general_autostartonboot">Start automatisch</string>
<string name="pref_title_general_autocreonnect">Verbind automatisch opnieuw</string>
<string name="pref_title_audo_player">Gewenste Audiospeler</string>
<string name="pref_default">Standaard</string>
<string name="pref_header_datetime">Datum en tijd</string>
<string name="pref_title_datetime_syctimeonconnect">Sync tijd</string>
<string name="pref_summary_datetime_syctimeonconnect">Synchroniseer de tijd naar het apparaat wanneer u verbinding maakt en wanneer de tijd of tijdzone op Android verandert</string>
<string name="pref_title_theme">Thema</string>
<string name="pref_theme_light">Licht</string>
<string name="pref_theme_dark">Donker</string>
<string name="pref_title_language">Taal</string>
<string name="pref_title_minimize_priority">Verberg de Gadgetbridge-melding</string>
<string name="pref_summary_minimize_priority_off">Het pictogram in de statusbalk en de melding op het vergrendelingsscherm worden weergegeven</string>
<string name="pref_summary_minimize_priority_on">Het pictogram in de statusbalk en de melding op het vergrendelingsscherm zijn verborgen</string>
<string name="pref_header_notifications">Meldingen</string>
<string name="pref_title_notifications_repetitions">Herhalingen</string>
<string name="pref_title_notifications_call">Telefoongesprekken</string>
<string name="pref_title_notifications_sms">SMS</string>
<string name="pref_title_notifications_pebblemsg">Pebble Berichten</string>
<string name="pref_summary_notifications_pebblemsg">Ondersteuning voor applicaties die meldingen versturen naar de Pebble via PebbleKit sturen.</string>
<string name="pref_title_notifications_generic">Algemene melding ondersteuning</string>
<string name="pref_title_whenscreenon">... ook als het scherm is ingeschakeld</string>
<string name="pref_title_notification_filter">Niet Storen</string>
<string name="pref_summary_notification_filter">Stop ongewenste meldingen te verzenden op basis van de Niet storen modus</string>
<string name="pref_title_transliteration">Transliteratie</string>
<string name="pref_summary_transliteration">Schakel dit in als uw apparaat geen ondersteuning heeft voor het lettertype van uw taal</string>
<string name="always">Altijd</string>
<string name="when_screen_off">Wanneer het scherm uit staat</string>
<string name="never">Nooit</string>
<string name="pref_header_privacy">Privacy</string>
<string name="pref_title_call_privacy_mode">Bel privacy modus</string>
<string name="pref_call_privacy_mode_off">Toon naam en nummer</string>
<string name="pref_call_privacy_mode_name">Verberg naam maar toon nummer</string>
<string name="pref_call_privacy_mode_number">Verberg nummer maar toon naam</string>
<string name="pref_call_privacy_mode_complete">Verberg naam en nummer</string>
<string name="pref_blacklist">Blacklist Apps</string>
<string name="pref_blacklist_calendars">Blacklist Kalenders</string>
<string name="pref_title_canned_replies">Antwoorden</string>
<string name="pref_title_canned_reply_suffix">Vaak voorkomend achtervoegsel</string>
<string name="pref_title_canned_messages_dismisscall">Bel Afwijzing</string>
<string name="pref_title_canned_messages_set">Update op Pebble</string>
<string name="pref_header_development">Ontwikkelaarsopties</string>
<string name="pref_title_development_miaddr">Mi Band adres</string>
<string name="pref_title_pebble_settings">Pebble instellingen</string>
<string name="pref_header_activitytrackers">Activity trackers</string>
<string name="pref_title_pebble_activitytracker">Gewenste activiteit tracker</string>
<string name="pref_title_pebble_sync_health">Synchroniseer Pebble Health</string>
<string name="pref_title_pebble_sync_misfit">Sync Misfit</string>
<string name="pref_title_pebble_sync_morpheuz">Sync Morpheuz</string>
<string name="pref_title_enable_outgoing_call">Ondersteun uitgaande oproepen</string>
<string name="pref_summary_enable_outgoing_call">Als u dit uitschakelt, wordt ook de Pebble 2/LE gestopt om voor uitgaande gesprekken te trillen</string>
</resources>

View File

@ -0,0 +1,54 @@
package nodomain.freeyourgadget.gadgetbridge.test;
import org.junit.Test;
import java.util.HashMap;
import java.util.Map;
import nodomain.freeyourgadget.gadgetbridge.devices.pebble.PebbleColor;
import nodomain.freeyourgadget.gadgetbridge.util.PebbleUtils;
import static org.junit.Assert.assertEquals;
public class PebbleUtilsTest extends TestBase {
@Test
public void testHexToPebbleColorConversion() {
Map<String, Byte> testCases = new HashMap<>();
testCases.put("#000000", PebbleColor.Black);
testCases.put("#ffffff", PebbleColor.White);
testCases.put("#00ff00", PebbleColor.Green);
testCases.put("#452435", PebbleColor.Black);
testCases.put("#334afd", PebbleColor.DukeBlue);
testCases.put("#ccb75c", PebbleColor.Brass);
testCases.put("#1b1c94", PebbleColor.OxfordBlue);
testCases.put("#90f892", PebbleColor.MayGreen);
testCases.put("#ff7301", PebbleColor.Orange);
testCases.put("#00aa00", PebbleColor.IslamicGreen);
for (String colorKey : testCases.keySet()) {
byte evaluatedColor = PebbleUtils.getPebbleColor(colorKey);
assertEquals("Color " + colorKey + " failed to translate properly!",
testCases.get(colorKey).byteValue(), evaluatedColor);
}
}
@Test
public void testIntToPebbleColorConversion() {
Map<Integer, Byte> testCases = new HashMap<>();
testCases.put(0x000000, PebbleColor.Black);
testCases.put(0xffffff, PebbleColor.White);
testCases.put(0x00ff00, PebbleColor.Green);
testCases.put(0x00aa00, PebbleColor.IslamicGreen);
for (int colorKey : testCases.keySet()) {
byte evaluatedColor = PebbleUtils.getPebbleColor(colorKey);
assertEquals("Color " + Integer.toHexString(colorKey) + " failed to translate properly!",
testCases.get(colorKey).byteValue(), evaluatedColor);
}
}
}