From e66d0a2d10883a8d58013bdc586759f8d70bdd00 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E0=A6=89=E0=A7=8E=E0=A6=B8=E0=A6=AC=20=E0=A6=B0=E0=A6=BE?= =?UTF-8?q?=E0=A7=9F=28Utsob=20Roy=29?= Date: Tue, 2 Oct 2018 03:04:51 +0600 Subject: [PATCH 001/200] Enhancement and Fixes for Bengali Transliteration. (#1263) * Added various fixes and enhancment for Bengali transliteration. * various fixes and enhancment for Bengali transliteration * fixed a coding typo [master] * Boolean lowercase and added .project in .gitignore * Boolean lowercase and added .project in .gitignore * typo fix [master] * fixed negative index error [master] * fixed negative index error [master] * unprinted character fix [master] * enhanced transliteration [master] * lowercased boolean and replaced Integer with int [master] * removed .setting, .classpath and .project and added them to .gitignore too. * bug fix and multilingual testcase [master] --- .gitignore | 3 + .settings/org.eclipse.buildship.core.prefs | 2 + app/src/main/.classpath | 11 --- app/src/main/.project | 33 ------- .../main/.settings/org.eclipse.jdt.core.prefs | 12 --- .../util/BengaliLanguageUtils.java | 88 +++++++++++++++++-- .../gadgetbridge/test/LanguageUtilsTest.java | 9 +- 7 files changed, 93 insertions(+), 65 deletions(-) create mode 100644 .settings/org.eclipse.buildship.core.prefs delete mode 100644 app/src/main/.classpath delete mode 100644 app/src/main/.project delete mode 100644 app/src/main/.settings/org.eclipse.jdt.core.prefs diff --git a/.gitignore b/.gitignore index 9bcb005c7c..abeb34c901 100644 --- a/.gitignore +++ b/.gitignore @@ -31,3 +31,6 @@ proguard/ MPChartLib fw.dirs +**/.project +**/.settings +**/.classpath diff --git a/.settings/org.eclipse.buildship.core.prefs b/.settings/org.eclipse.buildship.core.prefs new file mode 100644 index 0000000000..e8895216fd --- /dev/null +++ b/.settings/org.eclipse.buildship.core.prefs @@ -0,0 +1,2 @@ +connection.project.dir= +eclipse.preferences.version=1 diff --git a/app/src/main/.classpath b/app/src/main/.classpath deleted file mode 100644 index 60ab2ffa57..0000000000 --- a/app/src/main/.classpath +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/app/src/main/.project b/app/src/main/.project deleted file mode 100644 index f8b13a0fd2..0000000000 --- a/app/src/main/.project +++ /dev/null @@ -1,33 +0,0 @@ - - - Gadgetbridge - - - - - - com.android.ide.eclipse.adt.ResourceManagerBuilder - - - - - com.android.ide.eclipse.adt.PreCompilerBuilder - - - - - org.eclipse.jdt.core.javabuilder - - - - - com.android.ide.eclipse.adt.ApkBuilder - - - - - - com.android.ide.eclipse.adt.AndroidNature - org.eclipse.jdt.core.javanature - - diff --git a/app/src/main/.settings/org.eclipse.jdt.core.prefs b/app/src/main/.settings/org.eclipse.jdt.core.prefs deleted file mode 100644 index d17b6724d1..0000000000 --- a/app/src/main/.settings/org.eclipse.jdt.core.prefs +++ /dev/null @@ -1,12 +0,0 @@ -eclipse.preferences.version=1 -org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled -org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7 -org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve -org.eclipse.jdt.core.compiler.compliance=1.7 -org.eclipse.jdt.core.compiler.debug.lineNumber=generate -org.eclipse.jdt.core.compiler.debug.localVariable=generate -org.eclipse.jdt.core.compiler.debug.sourceFile=generate -org.eclipse.jdt.core.compiler.problem.assertIdentifier=error -org.eclipse.jdt.core.compiler.problem.enumIdentifier=error -org.eclipse.jdt.core.compiler.source=1.7 diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/util/BengaliLanguageUtils.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/util/BengaliLanguageUtils.java index 8c91eb7b97..a59acfbe13 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/util/BengaliLanguageUtils.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/util/BengaliLanguageUtils.java @@ -22,7 +22,7 @@ import java.util.regex.*; // What's the reason to extending LanguageUtils? // Just doing it because already done in the previous code. public class BengaliLanguageUtils extends LanguageUtils { - // Composite Letters. + // Composite Letters. private final static HashMap composites = new HashMap() { { put("ক্ষ", "kkh"); @@ -39,7 +39,25 @@ public class BengaliLanguageUtils extends LanguageUtils { put("্ব", "w"); } }; + // Vowels Only + private final static HashMap vowels = new HashMap() { + { + put("আ", "aa"); + put("অ", "a"); + put("ই", "i"); + put("ঈ", "ii"); + put("উ", "u"); + put("ঊ", "uu"); + put("ঋ", "ri"); + put("এ", "e"); + put("ঐ", "oi"); + put("ও", "o"); + put("ঔ", "ou"); + } + }; + + // Vowels and Hasants private final static HashMap vowelsAndHasants = new HashMap() { { put("আ", "aa"); @@ -149,7 +167,8 @@ public class BengaliLanguageUtils extends LanguageUtils { }; // The regex to extract Bengali characters in nested groups. - private final static String pattern = "(র্){0,1}(([অ-হড়-য়])(্([অ-মশ-হড়-য়]))*)((‍){0,1}(্([য-ল]))){0,1}([া-ৌ]){0,1}|([্ঁঃংৎ০-৯।])| "; + private final static String pattern = "(র্){0,1}(([অ-হড়-য়])(্([অ-মশ-হড়-য়]))*)((‍){0,1}(্([য-ল]))){0,1}([া-ৌ]){0,1}|([্ঁঃংৎ০-৯।])|(\\s)"; + private final static Pattern bengaliRegex = Pattern.compile(pattern); private static String getVal(String key) { @@ -173,7 +192,15 @@ public class BengaliLanguageUtils extends LanguageUtils { Matcher m = bengaliRegex.matcher(txt); StringBuffer sb = new StringBuffer(); + String lastChar = ""; + boolean lastHadComposition = false; + boolean lastHadKaar = false; + boolean nextNeedsO = false; + int lastHadO = 0; while (m.find()) { + boolean thisNeedsO = false; + boolean changePronounciation = false; + boolean thisHadKaar = false; String appendableString = ""; String reff = m.group(1); if (reff != null) { @@ -200,6 +227,10 @@ public class BengaliLanguageUtils extends LanguageUtils { g = g + 1; } } + if (m.group(2) != null && m.group(2).equals("ক্ষ")) { + changePronounciation = true; + thisNeedsO = true; + } int g = 6; while (g < 10) { String key = getVal(m.group(g)); @@ -209,16 +240,24 @@ public class BengaliLanguageUtils extends LanguageUtils { } g = g + 1; } + String phala = m.group(8); + if (phala != null && phala.equals("্য")) { + changePronounciation = true; + thisNeedsO = true; + } + String jukto = m.group(4); + if (jukto != null) { + thisNeedsO = true; + } String kaar = m.group(10); if (kaar != null) { String kaarStr = letters.get(kaar); if (kaarStr != null) { appendableString = appendableString + kaarStr; } - } else if (appendableString.length() > 0 && !vowelsAndHasants.containsKey(m.group(0))) { - // Adding 'a' like ITRANS if no vowel is present. - // TODO: Have to add it dynamically using Bengali grammer rules. - appendableString = appendableString + "a"; + if (kaarStr.equals("i") || kaarStr.equals("ii") || kaarStr.equals("u") || kaarStr.equals("uu")) { + changePronounciation = true; + } } String singleton = m.group(11); if (singleton != null) { @@ -227,6 +266,9 @@ public class BengaliLanguageUtils extends LanguageUtils { appendableString = appendableString + singleStr; } } + if (changePronounciation && lastChar.equals("a")) { + sb.setCharAt(sb.length() - 1, 'o'); + } String others = m.group(0); if (others != null) { @@ -234,7 +276,41 @@ public class BengaliLanguageUtils extends LanguageUtils { appendableString = appendableString + others; } } + String whitespace = m.group(12); + if (nextNeedsO && kaar == null && whitespace == null && !vowels.containsKey(m.group(0))) { + appendableString = appendableString + "o"; + lastHadO++; + thisNeedsO = false; + } + + if (((kaar != null && lastHadO > 1) || whitespace != null) && !lastHadKaar && sb.length() > 0 + && sb.charAt(sb.length() - 1) == 'o' && !lastHadComposition) { + sb.deleteCharAt(sb.length() - 1); + lastHadO = 0; + } + nextNeedsO = false; + if (thisNeedsO && kaar == null && whitespace == null && !vowels.containsKey(m.group(0))) { + appendableString = appendableString + "o"; + lastHadO++; + } + if (appendableString.length() > 0 && !vowelsAndHasants.containsKey(m.group(0)) && kaar == null) { + nextNeedsO = true; + } + if (reff != null || m.group(4) != null || m.group(6) != null) { + lastHadComposition = true; + } else { + lastHadComposition = false; + } + if (kaar != null) { + lastHadKaar = true; + } else { + lastHadKaar = false; + } m.appendReplacement(sb, appendableString); + lastChar = appendableString; + } + if (!lastHadKaar && sb.length() > 0 && sb.charAt(sb.length() - 1) == 'o' && !lastHadComposition) { + sb.deleteCharAt(sb.length() - 1); } m.appendTail(sb); return sb.toString(); diff --git a/app/src/test/java/nodomain/freeyourgadget/gadgetbridge/test/LanguageUtilsTest.java b/app/src/test/java/nodomain/freeyourgadget/gadgetbridge/test/LanguageUtilsTest.java index c5a7801897..d648116ba9 100644 --- a/app/src/test/java/nodomain/freeyourgadget/gadgetbridge/test/LanguageUtilsTest.java +++ b/app/src/test/java/nodomain/freeyourgadget/gadgetbridge/test/LanguageUtilsTest.java @@ -57,11 +57,14 @@ public class LanguageUtilsTest extends TestBase { assertEquals("Farsi transiteration failed", farsiExpected, farsiActual); } + @Test public void testStringTransliterateBengali() throws Exception { // input with cyrillic and diacritic letters - String[] inputs = { "অনিরুদ্ধ", "বিজ্ঞানযাত্রা চলছে চলবে।", "আমি সব দেখেশুনে ক্ষেপে গিয়ে করি বাঙলায় চিৎকার!" }; - String[] outputs = { "aniruddha", "biggaanaJaatraa chalachhe chalabe.", - "aami saba dekheshune kkhepe giye kari baangalaaya chitkaara!" }; + String[] inputs = { "অনিরুদ্ধ", "বিজ্ঞানযাত্রা চলছে চলবে।", "আমি সব দেখেশুনে ক্ষেপে গিয়ে করি বাঙলায় চিৎকার!", + "আমার জাভা কোড is so bad! কী আর বলবো!" }; + String[] outputs = { "oniruddho", "biggaanJaatraa cholchhe cholbe.", + "aami sob dekheshune kkhepe giye kori baanglaay chitkaar!", + "aamaar jaabhaa koD is so bad! kii aar bolbo!"}; String result; From a399b4be451ee9586e4287018090b55a3436c93c Mon Sep 17 00:00:00 2001 From: postsorino Date: Sun, 23 Sep 2018 13:29:15 +0000 Subject: [PATCH 002/200] Translated using Weblate (Greek) Currently translated at 100.0% (578 of 578 strings) Translation: Freeyourgadget/Gadgetbridge Translate-URL: https://hosted.weblate.org/projects/freeyourgadget/gadgetbridge/el/ --- app/src/main/res/values-el/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/res/values-el/strings.xml b/app/src/main/res/values-el/strings.xml index e279ba5334..9b4d623da8 100644 --- a/app/src/main/res/values-el/strings.xml +++ b/app/src/main/res/values-el/strings.xml @@ -686,7 +686,7 @@ "Από δεξιά προς αριστερά " "Ενεργοποιήστε αυτή την επιλογή αν η συσκευή σας δεν έχει υποστήριξη για γλώσσες που γράφονται από δεξιά " Μέγιστο μήκος γραμμής στις γλώσσες που γράφονται από δεξιά - Όταν η γραφή από δεξιά είναι ενεργοποιημένη , το κείμενο χωρίζεται σε γραμμές. Αλλάξτε αυτή τη τιμή αν οι γραμμές είναι πολύ μακριές ή κοντές. + Μακραίνει ή κονταίνει τις γραμμές στις γλώσσες που γράφονται από δεξιά %1$s χαμηλή μπαταρία %1$s χαμηλή μπαταρία: %2$s From 2c0615e0dcbe132aacb84074d7ac974537fb1337 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gilles=20=C3=89milien=20MOREL?= Date: Mon, 24 Sep 2018 17:34:58 +0000 Subject: [PATCH 003/200] Translated using Weblate (French) Currently translated at 95.3% (551 of 578 strings) Translation: Freeyourgadget/Gadgetbridge Translate-URL: https://hosted.weblate.org/projects/freeyourgadget/gadgetbridge/fr/ --- app/src/main/res/values-fr/strings.xml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index b141f49fbf..f8f8f1d350 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -10,16 +10,16 @@ Suivi du sommeil (ALPHA) Retrouver votre appareil perdu Prendre une capture d\'écran - Déconnexion + Déconnecter Supprimer l’appareil Supprimer %1$s - Ceci va supprimer l’appareil et toutes les données associées ! + Ceci va supprimer l’appareil et toutes les données associées ! Ouvrir le tiroir de navigation Fermer le tiroir de navigation Presser longuement l\'icône pour déconnecter Déconnexion Connexion - Capture d\'écran de l\'appareil + Capturer l\'écran de l\'appareil Déboguer Gestionnaire d\'application @@ -51,7 +51,7 @@ Ce micrologiciel n\'a pas été testé et peut ne pas être compatible avec Gadgetbridge. \n \nIl n\'est PAS conseillé de le flasher sur votre Mi Band ! - Si vous désirez continuer et que tout fonctionne correctement par la suite, veuillez en informer les développeurs de Gadgetbridge pour demander l\'ajout du micrologiciel %s à leur liste + Si vous désirez continuer et que tout fonctionne correctement par la suite, veuillez en informer les développeurs de Gadgetbridge pour demander l\'ajout du micrologiciel %s à leur liste. Paramètres Paramètres généraux From 81ed44a7078a7c96ddbc3e0ae5a5b1fbf3a7c9ec Mon Sep 17 00:00:00 2001 From: Full Name Date: Tue, 25 Sep 2018 15:54:25 +0000 Subject: [PATCH 004/200] Translated using Weblate (Czech) Currently translated at 100.0% (578 of 578 strings) Translation: Freeyourgadget/Gadgetbridge Translate-URL: https://hosted.weblate.org/projects/freeyourgadget/gadgetbridge/cs/ --- app/src/main/res/values-cs/strings.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/main/res/values-cs/strings.xml b/app/src/main/res/values-cs/strings.xml index 4e7a1d5aca..5c7c27a1fe 100644 --- a/app/src/main/res/values-cs/strings.xml +++ b/app/src/main/res/values-cs/strings.xml @@ -550,9 +550,9 @@ \nNETESTOVÁNO, MŮŽE POŠKODIT VAŠE ZAŘÍZENÍ, POKRAČUJTE NA VLASTNÍ NEBEZPEČÍ! Minimální doba mezi upozorněními Zprava doleva - Povolte, podporuje-li vaše zařízení jazyky zprava doleva + Povolte, nepodporuje-li vaše zařízení jazyky zprava doleva Maximální délka řádku pro zprava doleva - Je-li zapnuta podpora pro zleva doprava, text je rozdělen do řádků. Změňte tuto hodnotu jsou-li řádky příliš dlouhé/krátké. + Prodlužuje/zkracuje text řádků jazyků zleva doprava ID115 nastavení Orientace displeje From 027a7a44761018f188ccb35ad200efc845c59c4a Mon Sep 17 00:00:00 2001 From: youzhiran <2668760098@qq.com> Date: Sat, 29 Sep 2018 11:34:51 +0000 Subject: [PATCH 005/200] Translated using Weblate (Chinese (Simplified)) Currently translated at 74.7% (432 of 578 strings) Translation: Freeyourgadget/Gadgetbridge Translate-URL: https://hosted.weblate.org/projects/freeyourgadget/gadgetbridge/zh_Hans/ --- app/src/main/res/values-zh-rCN/strings.xml | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index dd15091002..6d1d023259 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -36,8 +36,8 @@ 停用 打开心率检测 关闭心率检测 - 启用系统天气预报应用 - 禁用系统天气预报应用 + 启用系统天气应用 + 禁用系统天气应用 安装天气通知应用 配置 移至顶部 @@ -539,4 +539,13 @@ HPlus 选择导出位置 Gadgetbridge 通知 - +更换LED灯颜色 + 调整FM频率 + 校准设备 + + + 屏蔽所有通知 + 开启所有通知 + + + From 0b2009dbc34ed5140b8cd07fdb9f2755c28da168 Mon Sep 17 00:00:00 2001 From: Dreamwalker Date: Sun, 30 Sep 2018 03:06:45 +0000 Subject: [PATCH 006/200] Translated using Weblate (Korean) Currently translated at 88.9% (514 of 578 strings) Translation: Freeyourgadget/Gadgetbridge Translate-URL: https://hosted.weblate.org/projects/freeyourgadget/gadgetbridge/ko/ --- app/src/main/res/values-ko/strings.xml | 108 +++++++++++++++++++++++-- 1 file changed, 102 insertions(+), 6 deletions(-) diff --git a/app/src/main/res/values-ko/strings.xml b/app/src/main/res/values-ko/strings.xml index c8569a3b1b..41505922f5 100644 --- a/app/src/main/res/values-ko/strings.xml +++ b/app/src/main/res/values-ko/strings.xml @@ -158,16 +158,16 @@ 설치 상태를 파악하는 동안 기다려주세요... 기기의 배터리 잔량이 적습니다! %1$s 배터리 남음: %2$s%% - 마지막 충전: %s \n + 마지막 충전: %s 충전 횟수: %s 당신의 수면 - 주간 걸음 수 + "주간 걸음 수 " 당신의 활동과 수면 - 펌웨어 업데이트 중... + 펌웨어 업데이트 중… 파일을 설치할 수 없습니다. 기기가 준비되어 있지 않습니다. %1$s: %2$s %3$s 호환 버전 - 테스트를 거치지 않은 버전 + 테스트를 거치지 않은 버전! 기기에 연결: %1$s Pebble 펌웨어 %1$s 올바른 하드웨어 리비전 @@ -371,7 +371,7 @@ 총 분수 분당 걸음 수 - 주간 수면 시간 + "주간 수면 시간 " 오늘의 수면, 목표 수면 시간: %1$s 칼로리 거리 @@ -556,4 +556,100 @@ 설정 Alipay - + LED 색상 변경 + FM 주파수 변경 + 디바이스 조정하기 + + + 모든 알람 블랙리스트 + 모든 알람을 위한 화이트리스트 + + + %s 펌웨어를 Mi Band 3에 설치하려고 합니다. +\n +\n.res 파일을 먼저 설치하고 .fw 파일을 설치하십시오. .fw 파일이 설치된 이후에 기기가 재시작될 것입니다. +\n +\n기존의 .res 파일과 설치하려는 .res 파일이 동일하다면, .res 파일을 다시 설치할 필요는 없습니다. +\n +\n테스트되지 않은 기능입니다. 기기가 고장날 가능성이 있습니다. 본인의 책임 하에 진행하십시오! + 알람간 최소 시간 + 오른쪽에서 왼쪽으로 + 만약 당신의 디바이스에서 좌우 언어가 보이지 않는다면 이것을 활성화하세요 + 좌우 최대 라인 길이 + 텍스트 좌우 길이 조정은 분리된다 + + 날씨 + "GATT client 만 " + "이것은 Pebble2 만의 것이고 실험적입니다. 만약 연결 문제가 있다면 시도해보세요 " + ID115 설정 + 화면 방향 + + 자동 추출 + 자동 추출 활성화 + 추출 장소 + 추출 간격 + "매 %d 시간 마다 추출 " + + 활동 데이터 자동으로 가져오기 + 가져 오기는 화면 잠금 해제시 발생합니다. 잠금 메커니즘이 설정된 경우에만 작동합니다! + 가져오는 최소 시간 + 매 %d 분마다 데이터 가져오기 + + Mi Band 2 설정 + Mi Band 3 설정 + Amazfit Cor 설정s + 수평 + 수직 + 시계가 진동하면 장치를 흔들거나 버튼을 누르십시오. + + %1$s 배터리 부족 + %1$s 배터리 부족: %2$s + 데이터베이스 추출 실패! 당신의 설정을 확인해주세요. + 수면 부족: %1$s + 늦잠: %1$s + 제한 없음 + 5초 + 10초 + 20초 + 30초 + 1분 + 5분 + 10분 + 30분 + + 걸음수 부족: %1$d + 걸음수 초과 : %1$d + 현재 / 최대 심박수: %1$d / %2$d + 당신의 수면시간은 %1$s 부터 %2$s 까지 + 잠을 자지 않았습니다 + 밴드 스크린 언락 + 슬어올려 밴드 스크린 화면 잠금 해제 + 야간 모드 + 밤이 되면 자동으로 밴드 밝기 감소 + + 노르웨이 + 스페인어 + 러시아어 + 독일어 + 이탈리아어 + 프랑스어(불어) + 폴란드어 + 한국어 + 일본어 + + 차트 설정 + 최대 심박수 + 최소 심박수 + + 확인 + + 켜기 + 일몰 + MyKronoz ZeTime + "Watch 9 " + "Roidmi " + "Roidmi 3 " + + 알람 + 언어 및 지역 설정 + From f59f972f2bfd6ec7f0ad54ded7d3592dcf274536 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Allan=20Nordh=C3=B8y?= Date: Sun, 30 Sep 2018 11:11:09 +0000 Subject: [PATCH 007/200] Translated using Weblate (English) Currently translated at 100.0% (578 of 578 strings) Translation: Freeyourgadget/Gadgetbridge Translate-URL: https://hosted.weblate.org/projects/freeyourgadget/gadgetbridge/en/ --- app/src/main/res/values/strings.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 91dec54a02..2b15468ad8 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -527,7 +527,7 @@ Overwrite Cancel Delete - Ok + OK Vibration @@ -655,7 +655,7 @@ Enable this to support contextual Arabic Right To Left Support Share log - Please keep in mind Gadgetbridge log files may contain lots of personal information, including but not limited to health data, unique identifiers (such as a device MAC address), music preferences, etc. Consider editing the file and removing this information before sending the file to a public issue report. + Please keep in mind Gadgetbridge logs files that may contain lots of personal info, including but not limited to health data, unique identifiers (such as a device\'s MAC address), music preferences, etc. Consider editing the file and removing this info before sending the file to a public issue report. Warning! No data From f513dad014b44a61a47bf103d3ec90a407ce6e4e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Allan=20Nordh=C3=B8y?= Date: Sun, 30 Sep 2018 11:10:23 +0000 Subject: [PATCH 008/200] =?UTF-8?q?Translated=20using=20Weblate=20(Norwegi?= =?UTF-8?q?an=20Bokm=C3=A5l)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently translated at 100.0% (578 of 578 strings) Translation: Freeyourgadget/Gadgetbridge Translate-URL: https://hosted.weblate.org/projects/freeyourgadget/gadgetbridge/nb_NO/ --- app/src/main/res/values-nb-rNO/strings.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/src/main/res/values-nb-rNO/strings.xml b/app/src/main/res/values-nb-rNO/strings.xml index 600be9e8ab..d14f24a296 100644 --- a/app/src/main/res/values-nb-rNO/strings.xml +++ b/app/src/main/res/values-nb-rNO/strings.xml @@ -663,7 +663,7 @@ OK Del logg - Ha i minnet at Gadgetbridge-loggfiler kan inneholde mye personlig informasjon, inkludert, og ikke begrenset til helsedata, unike indetifikatorer (som enhetens MAC-adresse), musikkpreferanser, osv. Overvei å redigere filen for fjerning av denne infoen før du sender filen til som offentlig feilrapport. + Ha i minnet at Gadgetbridge-loggfiler kan inneholde mye personlig info, inkludert, og ikke begrenset til helsedata, unike identifikatorer (som enhetens MAC-adresse), musikkpreferanser, osv. Overvei å redigere filen for fjerning av denne info-en før du sender filen til som offentlig feilrapport. Advarsel! Endre LED-farge Endre FM-frekvens @@ -676,9 +676,9 @@ Ugyldig frekvens Skriv inn en frekvens mellom 87.5 og 108.0 Høyre-til-venstre - Skru på dette hvis din enhet ikke kan vise høyre til venstre-språk. + Skru på dette hvis din enhet ikke kan vise høyre til venstre-språk Maksimal linjelengde for høyre-til-venstre - Strekker eller korter ned linjene høyre-til-venstre tekst inndeles i. + Strekker eller korter ned linjene høyre-til-venstre tekst inndeles i %1$s batteri snart tomt %1$s batteri snart tomt: %2$s From 099389a7f9bb0954632ae894109d9a88669ac5f6 Mon Sep 17 00:00:00 2001 From: hr-sales Date: Wed, 3 Oct 2018 16:29:39 +0000 Subject: [PATCH 009/200] Translated using Weblate (Portuguese (Brazil)) Currently translated at 45.1% (261 of 578 strings) Translation: Freeyourgadget/Gadgetbridge Translate-URL: https://hosted.weblate.org/projects/freeyourgadget/gadgetbridge/pt_BR/ --- app/src/main/res/values-pt-rBR/strings.xml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/app/src/main/res/values-pt-rBR/strings.xml b/app/src/main/res/values-pt-rBR/strings.xml index a6b89a5b42..406df3794b 100644 --- a/app/src/main/res/values-pt-rBR/strings.xml +++ b/app/src/main/res/values-pt-rBR/strings.xml @@ -7,7 +7,7 @@ Sair Sincronizar Monitor de sono (ALPHA) - Buscando dispositivo desconectado + Buscar dispositivo desconectado Print da tela Desconectar Apagar dispositivo @@ -420,4 +420,6 @@ Ativar botão Ativar vibração Notificações - Gadgetbridge - +Alterar cor do LED + Alterar frequência FM + From 93b12c2f6ebcc4f2b125315602b9d2e026f5c3a2 Mon Sep 17 00:00:00 2001 From: postsorino Date: Mon, 8 Oct 2018 19:25:48 +0000 Subject: [PATCH 010/200] Translated using Weblate (Greek) Currently translated at 100.0% (578 of 578 strings) Translation: Freeyourgadget/Gadgetbridge Translate-URL: https://hosted.weblate.org/projects/freeyourgadget/gadgetbridge/el/ --- app/src/main/res/values-el/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/res/values-el/strings.xml b/app/src/main/res/values-el/strings.xml index 9b4d623da8..6c1aaf8399 100644 --- a/app/src/main/res/values-el/strings.xml +++ b/app/src/main/res/values-el/strings.xml @@ -668,7 +668,7 @@ Λειτουργία \"νύχτας\" Μείωση φωτεινότητας της οθόνης του Mi band 3 κατά τη διάρκεια της νύχτας - Οκ + ΟΚ Στη δύση του ηλίου "Roidmi " From 06d3d458741611a30eb22e936b114f2aa357d562 Mon Sep 17 00:00:00 2001 From: Hirnchirurg Date: Mon, 8 Oct 2018 20:41:16 +0000 Subject: [PATCH 011/200] Translated using Weblate (German) Currently translated at 92.5% (535 of 578 strings) Translation: Freeyourgadget/Gadgetbridge Translate-URL: https://hosted.weblate.org/projects/freeyourgadget/gadgetbridge/de/ --- app/src/main/res/values-de/strings.xml | 65 ++++++++++++++++++++------ 1 file changed, 51 insertions(+), 14 deletions(-) diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index 620b4618f6..6639802a71 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -45,15 +45,15 @@ Blockierte Kalenderbenachrichtigungen FW/App Installer - Es soll die Firmware %s anstelle der aktuell installierten Version auf das Mi Band gespielt werden. + Es soll die Firmware %s anstelle der aktuell installierten Version auf das Mi Band installiert werden. Es sollen die Firmwares %1$s und %2$s anstelle der aktuell installierten Versionen auf das Mi Band gespielt werden. Diese Firmware ist getestet worden und ist mit Gadgetbridge kompatibel. Diese Firmware ist nicht getestet und könnte inkompatibel mit Gadgetbridge sein.\n\nEs wird nicht empfohlen, sie auf dem Mi Band zu installieren! - Wenn du dennoch fortfahren möchtest und das Gerät anschliessend korrekt funktioniert, melde bitte den Gadgetbridge Entwicklern, dass diese Firmwareversion %s funktioniert + Wenn du dennoch fortfahren möchtest und das Gerät anschliessend korrekt funktioniert, melde bitte den Gadgetbridge-Entwicklern, dass diese Firmwareversion %s funktioniert Einstellungen Allgemeine Einstellungen - Verbinde, wenn Bluetooth eingeschaltet wird + Verbinde mit Gadgetbridge, wenn Bluetooth eingeschaltet wird Automatisch starten Verbindung automatisch wiederherstellen Bevorzugter Audioplayer @@ -130,7 +130,7 @@ Benachrichtigungsprotokoll erzwingen Diese Option erzwingt das neuste Benachrichtigungsprotokoll abhängig von der Firmwareversion. NUR EINSCHALTEN, WENN DU WEISST, WAS DU TUST! Ungetestete Features freischalten - Schaltet ungetetestete Features frei. NUR EINSCHALTEN, WENN DU WEISST WAS DU TUST! + Schaltet ungetestete Features frei. NUR EINSCHALTEN, WENN DU WEISST WAS DU TUST! BLE immer bevorzugen Nutze den experimentellen LE support für alle Pebbles anstelle von klassischem BT. Setzt voraus, dass die \"Pebble LE\" gekoppelt wird, nachdem die nicht-LE Pebble einmal verbunden war. Pebble 2/LE GATT MTU Limit @@ -285,15 +285,15 @@ Live Aktivität Schritte heute, Ziel: %1$s Transfer von Aktivitätsdaten nicht bestätigen (kein ACK) - Wenn der Transfer der Aktivitätsdaten nicht bestätigt wird, werden die Daten nicht auf dem Mi Band gelöscht. Das ist sinnvoll, wenn neben Gadgetbridge noch andere Apps auf das Mi Band zugreifen. - Aktivitätsdaten verbleiben auf dem Mi Band, auch nach der Synchronisierung. Hilfreich, wenn das Mi Band mit weiteren Apps verwendet wird. + Wenn der Transfer der Aktivitätsdaten nicht bestätigt wird, werden die Daten nicht auf dem MiBand gelöscht. Das ist sinnvoll, wenn neben Gadgetbridge noch andere Apps auf das MiBand zugreifen. + Aktivitätsdaten verbleiben auf dem MiBand, auch nach der Synchronisierung. Hilfreich, wenn das MiBand mit weiteren Apps verwendet wird. Benutze Modus mit niedriger Latenz für Firmware-Updates Dies kann bei Geräten helfen, bei denen Firmwareupdates fehlschlagen Schritteverlauf Akt. Schritte pro Minute Schritte insgesamt Verlauf Schritte pro Minute - Starte Deine Aktivität + Starte deine Aktivität Aktivität Leichter Schlaf Tiefschlaf @@ -306,7 +306,7 @@ Wecker für zukünftige Ereignisse vormerken Verwende den Herzfrequenzsensor, um die Schlaferkennung zu verbessern Zeitausgleich in Stunden (um den Schlaf von Schichtarbeitern zu erkennen) - Mi2: Datumsformat + Datumsformat Zeit Zeit & Datum Benachrichtigungen bei Schrittziel @@ -345,7 +345,7 @@ Puls Puls Rohdaten in der Datenbank speichern - Wenn eingeschaltet, werden Daten so wie sie eingehen für eine spätere analyse gespeichert. Achtung: Die Datenbank wird dadurch größer! + Wenn eingeschaltet, werden Daten so wie sie eingehen für eine spätere Analyse gespeichert. Achtung: Die Datenbank wird dadurch grösser! Datenbankverwaltung Datenbankverwaltung Die Datenbankoperationen verwenden den folgenden Pfad auf dem Gerät. \nDieser Pfad ist von anderen Android-Apps und ihrem Computer aus zugreifbar. \nSie finden die exportierte Datenbank hier (bzw. legen die zu importierende dort ab): @@ -353,7 +353,7 @@ Kann nicht auf den Exportpfad zugreifen. Bitte die Entwickler kontaktieren. Exportiert nach: %1$s Fehler beim Exportieren der DB: %1$s - Fehler beim Exlortieren der Einstellungen: %1$s + Fehler beim Exportieren der Einstellungen: %1$s Daten importieren? Wirklich die aktuelle Datenbank überschreiben? Alle aktuellen Aktivitätsdaten (sofern vorhanden) gehen verloren. Import erfolgreich. @@ -374,7 +374,7 @@ Vibration Pebble-Kopplung - Ein Kopplungsdialog sollte auf dem Android-Gerät aufpoppen. Falls das nicht passiert, schau in die Benachrichtigungen und akzeptiere die Kopplungsanfrage. Akzeptiere danach die Kopplungsanfrage auf Deiner Pebble + Ein Kopplungsdialog sollte auf dem Android-Gerät erscheinen. Falls das nicht passiert, schau in die Benachrichtigungen und akzeptiere die Kopplungsanfrage. Akzeptiere danach die Kopplungsanfrage auf deiner Pebble Stelle sicher, dass dieses Skin in der Wetter-App aktiviert ist, damit du Wetterdaten auf deine Pebble erhältst. \n\nKeine Konfiguration nötig. \n\nDu kannst die System-Wetter-App deiner Pebble im App-Management aktivieren. \n\nUnterstützte Watchfaces werden die Wetterdaten automatisch anzeigen. Bluetooth-Kopplung aktivieren Deaktiviere dies, falls du Probleme beim Verbinden hast @@ -387,7 +387,7 @@ Gefunden! Mi2: Uhrzeitformat Installiere Version %1$s vor dem Installieren der Firmware! - Text Benachrichtigung + Text-Benachrichtigung = 1.0.1.28 und installiertes Mili_pro.ft* benötigt.]]> Aus Aus @@ -414,7 +414,7 @@ Aktion bei Tastendruck Bestimmte Aktion bei Tastendruck auf dem Mi Band 2 Anzahl der Tastendrücke, die einen Broadcast auslöst - Zu Sendende Broadcast-Nachricht + Zu sendende Broadcast-Nachricht Aktiviere Tastenaktion Aktiviere Aktion bei einer bestimmten Anzahl an Tastendrücken Aktiviere Vibration @@ -453,7 +453,7 @@ stündlich automatisch - Web View Aktivität + Web-View Aktivität Wetter Firmware @@ -571,4 +571,41 @@ Koreanisch Japanisch + LED Farbe wechseln + FM Frequenz wechseln + Minimale Zeit zwischen den Benachrichtigungen + Von rechts nach links + Dies anschalten, wenn dein Gerät keine Sprachen von rechts nach links anzeigen kann + Nur GATT-Client + Bildschirmausrichtung + + Minimale Zeit zwischen den Abrufen + Alle %d Minuten abrufen + + %1$s Batterie gering + Kein Limit + 5 Sekunden + 10 Sekunden + 20 Sekunden + 30 Sekunden + 1 Minute + 5 Minuten + 10 Minuten + 30 Minuten + + Fehlende Schritte: %1$d + Überschritte: %1$d + Aktueller / Maximaler Puls: %1$d / %2$d + MiBand-Bildschirm entsperren + Wische nach oben, um den Bildschirm vom MiBand zu entriegeln. + Nachtmodus + Niedrigere MiBand-Bildschirmhelligkeit nachts automatisch einstellen + + Diagrammeinstellungen + Maximaler Puls + Minimaler Puls + + Akzeptieren + + Bei Sonnenuntergang From cbf3d7c2b3d8c407c062d18e180ce2ce42cf2e54 Mon Sep 17 00:00:00 2001 From: Full Name Date: Tue, 16 Oct 2018 08:34:53 +0000 Subject: [PATCH 012/200] Translated using Weblate (Czech) Currently translated at 100.0% (578 of 578 strings) Translation: Freeyourgadget/Gadgetbridge Translate-URL: https://hosted.weblate.org/projects/freeyourgadget/gadgetbridge/cs/ --- app/src/main/res/values-cs/strings.xml | 38 ++++++++++++++------------ 1 file changed, 20 insertions(+), 18 deletions(-) diff --git a/app/src/main/res/values-cs/strings.xml b/app/src/main/res/values-cs/strings.xml index 5c7c27a1fe..1528e95c80 100644 --- a/app/src/main/res/values-cs/strings.xml +++ b/app/src/main/res/values-cs/strings.xml @@ -107,8 +107,8 @@ Povolit přístup třetích stran k aplikaci Android Povolit experimentální podporu pro aplikace Androidu přes PebbleKit Východ a západ slunce - Zasílat časy východu a západu slunce podle umístění do Pebble časové osi - Odstraňovat skryté notifikace automaticky + Zasílat časy východu a západu slunce podle umístění do časové osy Pebble + Automaticky odstraňovat skryté notifikace Notifikace budou z Pebble odstraněny automaticky, pokud byly skryty na zařízení s Androidem Soukromý režim Běžné notifikace @@ -149,7 +149,7 @@ (neznámé) Test Test notifikací - Toto je notifikace z Gadgetbridge + Toto je testovací notifikace z Gadgetbridge. Diakritika: ěščřžýáíéúů BT není podporován. BT je vypnutý. Dotkněte se zařízení pro App Manager @@ -188,8 +188,8 @@ Muž Žena Jiný - Vlevo - Vpravo + Levá + Pravá Data uživatele nejsou platná, nyní používám vzorová. Když Mi Band zavibruje a blikne, dotkněte se jej několikrát po sobě. Instalovat @@ -223,7 +223,7 @@ Navigace Sociální sítě Najit ztracené zařízení - Zrušit pro zastavení vibrací. + Zastavit vibrací. Vaše aktivita Nastavit buzení Nastavit buzení @@ -326,13 +326,15 @@ Pokud je zatrženo, tak jsou data uložena v původní podobě pro pozdější vyhodnocení. Databáze bude v tom případě větší! Správa databáze Správa databáze - Operace s databází použití následující cestu v zařízení. \nTato cesta je dostupní pro ostatní aplikace Androidu a váš počítač. \nExportovanou databázi (nebo místo pro importovanou databázi) naleznete tady: + Operace s databází použijí následující cestu v zařízení. +\nTato cesta je dostupná pro ostatní aplikace Androidu a váš počítač. +\nExportovanou databázi (nebo místo pro importovanou databázi) naleznete zde: Smazat původní databázi Nelze přistoupit na zadanou cestu. Kontaktujte vývojáře. Exportováno do: %1$s Chyba při exportu DB: %1$s Importovat data? - Opravdu chcete přepsat aktuální databázi? Všechna uložená data o aktivitě se ztratí. + Opravdu chcete přepsat aktuální databázi\? Všechna uložená data aktivit budou ztracena. Importováno. Chyba při importu DB: %1$s Smazat data o aktivitách? @@ -368,7 +370,7 @@ Skrýť číslo, ale zobrazit jméno Zakázané kalendáře - Časová os Pebble + Časová osa Pebble Synchronizace kalendáře Odesílat události kalendáře na časovou osu @@ -389,7 +391,7 @@ Nerušit Náramek nebude přijímat upozornění, pokud je aktivní režim Nerušit Upozornění na nečinnost - Náramek zavibruje, když budete zadaný čas bez pohybu + Náramek zavibruje po určité době neaktivity Limit času bez pohybu (v minutách) Vypnutí upozornění na nečinnost během zadaného časového intervalu Od @@ -467,7 +469,7 @@ Export databáze selhal! Zkontrolujte nastavení. Automaticky Zjednodušená Čínština - Tradiční Čísština + Tradiční Čínština Angličtina Španělština @@ -537,8 +539,8 @@ Kalibrovat zařízení - Seznam všech zakázaných upozornění - Seznam všech povolených upozornění + Zakázat všechny aplikace + Povolit všechny aplikace Chystáte se nainstalovat firmvér %s do vašeho Mi Band 3. @@ -562,9 +564,9 @@ Minimální doba mezi synchronizacemi Synchronizovat každých %d minut - Mi Band 2 nastavení - Mi Band 3 nastavení - Amazfit Cor nastavenís + Nastavení Mi Band 2 + Nastavení Mi Band 3 + Nastavení Amazfit Cors Na šířku Na výšku Po zavibrování stiskněte tlačítko, nebo se zařízením zatřeste. @@ -588,7 +590,7 @@ Aktuální / Maximální tepová frekvence: %1$d / %2$d Spánek od %1$s do %2$s Bez spánku - Odemčení obrazovky zařízení + Odemknutí obrazovky zařízení Přejeďte prstem pro odemčení obrazovky zařízení Noční režim Nižší automatická intenzita displeje v noci @@ -632,7 +634,7 @@ Kalibrace Watch 9 Kontextuální Arabština Zapnout podporu pro kontextuální arabštinu - Podpora zprava doleva + Podpora jazyků zprava doleva Sdílet záznam Prosím nezapomeňte, že ladící záznamy Gadgetbridge mohou obsahovat osobní informace, zahrnující například zdravotní data, identifikátory (MAC adresu), hudební preference a podobně. Tyto informace můžete vymazat před odesláním souboru do veřejného reportu. Upozornění! From 24afaa8b44f92446453a5f015fba9f12feb69d74 Mon Sep 17 00:00:00 2001 From: WaldiS Date: Sat, 20 Oct 2018 12:50:12 +0000 Subject: [PATCH 013/200] Translated using Weblate (Polish) Currently translated at 51.3% (297 of 578 strings) Translation: Freeyourgadget/Gadgetbridge Translate-URL: https://hosted.weblate.org/projects/freeyourgadget/gadgetbridge/pl/ --- app/src/main/res/values-pl/strings.xml | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/app/src/main/res/values-pl/strings.xml b/app/src/main/res/values-pl/strings.xml index d610f46d8f..c2c52a793b 100644 --- a/app/src/main/res/values-pl/strings.xml +++ b/app/src/main/res/values-pl/strings.xml @@ -7,7 +7,7 @@ Zakończ Synchronizuj Monitor snu (ALPHA) - Odnajdź zagubione urządzenie + Znajdź zgubione urządzenie Zrób zrzut ekranu Rozłącz Usuń urządzenie @@ -272,15 +272,15 @@ Tworzenie zrzutu ekranu urządzenia - Aktywuj systemową aplikację pogodową - Dezaktywuj systemową aplikację pogodową - Zainstaluj powiadomienia pogodowe + Aktywuj Systemową Aplikację Pogody + Dezaktywuj Systemową Aplikację Pogody + Zainstaluj aplikację Powiadomienia o pogodzie Czarna lista kalendarzy Uruchom automatycznie Ukryj powiadomienia z Gadgetbridge - Ikona na pasku stanu i powiadomienia na zablokowanym ekranie wyświetlają się - Ikona na pasku stanu i powiadomienia na zablokowanym ekranie są ukryte + "Ikona na pasku stanu i powiadomienia pokazują się na zablokowanym ekranie " + Ikona na pasku stanu i powiadomienia jest ukryta na zablokowanym ekranie Niechciane powiadomienia są wyłączone w tym trybie Transliteracja @@ -408,4 +408,6 @@ Przesuń tekst powiadomienia poza ekran Spróbuj uzyskać obecną lokalizację podczas biegu, używaj zapisanej lokalizacji jako rezerwowej + Zmień kolor diody LED + Zmień częstotliwość FM From cc3271ad146cbf3313e6c6f87c976f88fc42120b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bo=C5=BCydar?= Date: Sat, 20 Oct 2018 12:58:54 +0000 Subject: [PATCH 014/200] Translated using Weblate (Polish) Currently translated at 51.3% (297 of 578 strings) Translation: Freeyourgadget/Gadgetbridge Translate-URL: https://hosted.weblate.org/projects/freeyourgadget/gadgetbridge/pl/ --- app/src/main/res/values-pl/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/res/values-pl/strings.xml b/app/src/main/res/values-pl/strings.xml index c2c52a793b..5ef1591a3c 100644 --- a/app/src/main/res/values-pl/strings.xml +++ b/app/src/main/res/values-pl/strings.xml @@ -58,7 +58,7 @@ Rozmowy telefoniczne SMS Wiadomości Pebble - Obsługa ogólnych powiadomień + Obsługa powiadomień generycznych ...także gdy ekran jest włączony Nie przeszkadzać Zawsze From 6e731885fd3e0fe3d46434677f664653d75df392 Mon Sep 17 00:00:00 2001 From: WaldiS Date: Sat, 20 Oct 2018 12:59:00 +0000 Subject: [PATCH 015/200] Translated using Weblate (Polish) Currently translated at 53.4% (309 of 578 strings) Translation: Freeyourgadget/Gadgetbridge Translate-URL: https://hosted.weblate.org/projects/freeyourgadget/gadgetbridge/pl/ --- app/src/main/res/values-pl/strings.xml | 27 ++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/app/src/main/res/values-pl/strings.xml b/app/src/main/res/values-pl/strings.xml index 5ef1591a3c..de1874c64f 100644 --- a/app/src/main/res/values-pl/strings.xml +++ b/app/src/main/res/values-pl/strings.xml @@ -58,7 +58,7 @@ Rozmowy telefoniczne SMS Wiadomości Pebble - Obsługa powiadomień generycznych + Ogólna obsługa powiadomień ...także gdy ekran jest włączony Nie przeszkadzać Zawsze @@ -71,14 +71,14 @@ Ustawienia programisty Adres Mi Band Ustawienia Pebble - Monitory aktywności + Monitorowanie aktywności Preferowany monitor aktywności Synchronizuj Pebble Health Synchronizuj Misfit Synchronizuj Morpheuz Zezwól zewnętrznym aplikacjom Android na dostęp - Włącz eksperymentalną obsługę aplikacji Android przez PebbleKit - Wschód i zachód + Włącz eksperymentalną obsługę aplikacji Android za pomocą PebbleKit + Wschód i zachód słońca Wyślij czas wschodu i zachodu bazując na lokazliacji do ośi czasu Pebble Lokalizacja Uzyskaj lokalizację @@ -269,7 +269,7 @@ Przytrzymaj aby rozłączyć Rozłączanie Łączenie - Tworzenie zrzutu ekranu urządzenia + Wykonaj zrzut ekranu urządzenia Aktywuj Systemową Aplikację Pogody @@ -284,7 +284,7 @@ Niechciane powiadomienia są wyłączone w tym trybie Transliteracja - Włącz tą opcję jeśli twoje urządzenie nie wspiera czcionki w twoim języku + Włącz tę opcję, jeśli twoje urządzenie nie obsługuje czcionki twojego języka Prywatność Wyświetl nazwę i numer @@ -343,9 +343,9 @@ Opóźnienie po wciśnięciu przycisku akcji Opaska zawibruje gdy zostanie osiągnięty dzienny cel korków Nie przeszkadzać - Obsługa aplikacji, które wysyłają powiadomienia na Pebble przy użyciu PebbleKit. + Obsługa aplikacji wysyłających powiadomienia do Pebble za pośrednictwem PebbleKit. Pogoda - Odrzucanie połączeń + Odrzuć połączenie Całodobowy pomiar tętna Automatyczny eksport Eksportować co %d godzin @@ -369,7 +369,7 @@ Kalibracja urządzenia - Czarna lista dla wszystkich powiadomień + Czarna lista dla powiadomień Biała lista dla wszystkich powiadomień @@ -398,10 +398,10 @@ Włącz gesty lewo/prawo w wykresie aktywności Minimalny czas pomiędzy powiadomieniami - Włącz tryb prywatny - Lokalizacja pogody + Tryb prywatności połączeń telefonicznych + Lokalizacja pogody (CM/LOS) - Wyłączenie tej opcji zatrzyma również Pebble 2/LE w wibracjach połączeń wychodzących + Wyłączenie tej opcji spowoduje również, że Pebble 2/LE przestanie wibrować przy połączeniach wychodzących Powiadomienia są automatycznie usuwane z Pebble po usunięciu ich z urządzenia Android @@ -410,4 +410,7 @@ Zmień kolor diody LED Zmień częstotliwość FM + Od prawej do lewej + Włącz tę opcję, jeśli Twoje urządzenie nie może wyświetlać języków z pisownią od prawej do lewej + Max. Długość linii od prawej do lewej From dde8a5044fce9776ce69a6e22d455d0e004ceb38 Mon Sep 17 00:00:00 2001 From: Andreas Shimokawa Date: Sun, 28 Oct 2018 15:32:57 +0100 Subject: [PATCH 016/200] Mi Band 3: Whitelist FW 1.8.0.0 --- .../service/devices/huami/miband3/MiBand3FirmwareInfo.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/miband3/MiBand3FirmwareInfo.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/miband3/MiBand3FirmwareInfo.java index 995cebb2d6..881979125c 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/miband3/MiBand3FirmwareInfo.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/miband3/MiBand3FirmwareInfo.java @@ -51,12 +51,14 @@ public class MiBand3FirmwareInfo extends HuamiFirmwareInfo { crcToVersion.put(38254, "1.5.0.7"); crcToVersion.put(46985, "1.5.0.11"); crcToVersion.put(31330, "1.6.0.16"); + crcToVersion.put(10930, "1.8.0.0"); // resources crcToVersion.put(54724, "1.2.0.8"); crcToVersion.put(52589, "1.3.0.4"); crcToVersion.put(34642, "1.3.0.8"); crcToVersion.put(25278, "1.4.0.12-1.6.0.16"); + crcToVersion.put(23249, "1.8.0.0"); // font crcToVersion.put(19775, "1"); From 29dc806fb16d708ae5c154bd2013f7f651350a2e Mon Sep 17 00:00:00 2001 From: Daniele Gobbetti Date: Sun, 28 Oct 2018 17:58:24 +0100 Subject: [PATCH 017/200] Ignore notifications that are older than 1 second In case of grouped notifications, we get multiple notifications also if the android device shows only one. This means that with this change the most recently updated chat will get through, but others will not. This should help with #1062 and #657 --- .../gadgetbridge/externalevents/NotificationListener.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/externalevents/NotificationListener.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/externalevents/NotificationListener.java index 18f6242bba..0c03d5c156 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/externalevents/NotificationListener.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/externalevents/NotificationListener.java @@ -209,6 +209,10 @@ public class NotificationListener extends NotificationListenerService { String source = sbn.getPackageName().toLowerCase(); Notification notification = sbn.getNotification(); + if (notification.when < (sbn.getPostTime() - 1000)) { + LOG.info("NOT processing notification, too old. notification.when: " + notification.when + " post time: " + sbn.getPostTime() + " now: " + System.currentTimeMillis()); + return; + } NotificationSpec notificationSpec = new NotificationSpec(); notificationSpec.id = (int) sbn.getPostTime(); //FIXME: a truly unique id would be better From 6b136210a1d20a9182a6c8c8f7c51edc43cd487a Mon Sep 17 00:00:00 2001 From: Andreas Shimokawa Date: Sun, 28 Oct 2018 21:31:09 +0100 Subject: [PATCH 018/200] bump android gradle plugin and build tools version --- app/build.gradle | 2 +- build.gradle | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 71251a8754..ef18ee942f 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -17,7 +17,7 @@ android { targetCompatibility JavaVersion.VERSION_1_7 } compileSdkVersion 27 - buildToolsVersion "28.0.2" + buildToolsVersion '28.0.3' defaultConfig { applicationId "nodomain.freeyourgadget.gadgetbridge" diff --git a/build.gradle b/build.gradle index e1aec6bd72..6b7dab00ba 100644 --- a/build.gradle +++ b/build.gradle @@ -6,7 +6,7 @@ buildscript { google() } dependencies { - classpath 'com.android.tools.build:gradle:3.2.0' + classpath 'com.android.tools.build:gradle:3.2.1' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files From b9999edf2a2634e0b4fb62c6526c60caa62718f9 Mon Sep 17 00:00:00 2001 From: Daniele Gobbetti Date: Mon, 29 Oct 2018 18:39:38 +0100 Subject: [PATCH 019/200] Ignore notifications that are older than the last forwarded one for the same source. This reuses the data structure populated to prevent overflow, but avoids to forward notifications that are older than the reference. --- .../externalevents/NotificationListener.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/externalevents/NotificationListener.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/externalevents/NotificationListener.java index 0c03d5c156..89353f8970 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/externalevents/NotificationListener.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/externalevents/NotificationListener.java @@ -209,9 +209,12 @@ public class NotificationListener extends NotificationListenerService { String source = sbn.getPackageName().toLowerCase(); Notification notification = sbn.getNotification(); - if (notification.when < (sbn.getPostTime() - 1000)) { - LOG.info("NOT processing notification, too old. notification.when: " + notification.when + " post time: " + sbn.getPostTime() + " now: " + System.currentTimeMillis()); - return; + if (notificationTimes.containsKey(source)) { + long last_time = notificationTimes.get(source); + if (notification.when <= last_time) { + LOG.info("NOT processing notification, too old. notification.when: " + notification.when + " last notification for this source: " + last_time); + return; + } } NotificationSpec notificationSpec = new NotificationSpec(); notificationSpec.id = (int) sbn.getPostTime(); //FIXME: a truly unique id would be better From eede85a9c98f850de7f21333a14812c530d87153 Mon Sep 17 00:00:00 2001 From: Daniele Gobbetti Date: Wed, 31 Oct 2018 21:47:12 +0100 Subject: [PATCH 020/200] Various improvements and bugfixes to notification handling Prevent duplicate notifications with a dedicated data structure (not reusing the anti-burst one) #1062, #657 Pebble: Forward the actions attached to notifications (not only reply) inspired by the work of dnastase #705 --- .../activities/DebugActivity.java | 1 - .../GBDeviceEventNotificationControl.java | 1 + .../externalevents/AlarmClockReceiver.java | 8 +- .../externalevents/NotificationListener.java | 59 +++++++----- .../externalevents/PebbleReceiver.java | 1 - .../externalevents/SMSReceiver.java | 1 - .../gadgetbridge/impl/GBDeviceService.java | 3 +- .../gadgetbridge/model/DeviceService.java | 1 + .../gadgetbridge/model/NotificationSpec.java | 34 ++++++- .../service/AbstractDeviceSupport.java | 3 +- .../service/DeviceCommunicationService.java | 12 ++- .../devices/pebble/PebbleProtocol.java | 95 +++++++++++++------ 12 files changed, 145 insertions(+), 74 deletions(-) diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/DebugActivity.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/DebugActivity.java index 95cd9e3c86..d9cc223598 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/DebugActivity.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/DebugActivity.java @@ -122,7 +122,6 @@ public class DebugActivity extends AbstractGBActivity { notificationSpec.subject = testString; notificationSpec.type = NotificationType.values()[sendTypeSpinner.getSelectedItemPosition()]; notificationSpec.pebbleColor = notificationSpec.type.color; - notificationSpec.id = -1; GBApplication.deviceService().onNotification(notificationSpec); } }); diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/deviceevents/GBDeviceEventNotificationControl.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/deviceevents/GBDeviceEventNotificationControl.java index 1e7037b174..25fd8bf319 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/deviceevents/GBDeviceEventNotificationControl.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/deviceevents/GBDeviceEventNotificationControl.java @@ -20,6 +20,7 @@ public class GBDeviceEventNotificationControl extends GBDeviceEvent { public int handle; public String phoneNumber; public String reply; + public String title; public Event event = Event.UNKNOWN; public enum Event { diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/externalevents/AlarmClockReceiver.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/externalevents/AlarmClockReceiver.java index aafdf94f5c..b92566fa3e 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/externalevents/AlarmClockReceiver.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/externalevents/AlarmClockReceiver.java @@ -64,10 +64,10 @@ public class AlarmClockReceiver extends BroadcastReceiver { private synchronized void sendAlarm(boolean on) { dismissLastAlarm(); if (on) { - lastId = generateId(); NotificationSpec spec = new NotificationSpec(); + //TODO: can we attach a dismiss action to the notification and not use the notification ID explicitly? + lastId = spec.getId(); spec.type = NotificationType.GENERIC_ALARM_CLOCK; - spec.id = lastId; spec.sourceName = "ALARMCLOCKRECEIVER"; // can we get the alarm title somehow? GBApplication.deviceService().onNotification(spec); @@ -81,8 +81,4 @@ public class AlarmClockReceiver extends BroadcastReceiver { } } - private int generateId() { - // lacks negative values, but should be sufficient - return (int) (Math.random() * Integer.MAX_VALUE); - } } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/externalevents/NotificationListener.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/externalevents/NotificationListener.java index 89353f8970..77df28c99b 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/externalevents/NotificationListener.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/externalevents/NotificationListener.java @@ -50,6 +50,7 @@ import android.support.v7.graphics.Palette; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Objects; @@ -87,7 +88,8 @@ public class NotificationListener extends NotificationListenerService { private LimitedQueue mActionLookup = new LimitedQueue(16); - private HashMap notificationTimes = new HashMap<>(); + private HashMap notificationBurstPrevention = new HashMap<>(); + private HashMap notificationOldRepeatPrevention = new HashMap<>(); private final BroadcastReceiver mReceiver = new BroadcastReceiver() { @@ -145,19 +147,20 @@ public class NotificationListener extends NotificationListenerService { break; case ACTION_REPLY: int id = intent.getIntExtra("handle", -1); + NotificationCompat.Action wearableAction = (NotificationCompat.Action) mActionLookup.lookup(id); String reply = intent.getStringExtra("reply"); - NotificationCompat.Action replyAction = (NotificationCompat.Action) mActionLookup.lookup(id); - if (replyAction != null && replyAction.getRemoteInputs() != null) { - RemoteInput[] remoteInputs = replyAction.getRemoteInputs(); - PendingIntent actionIntent = replyAction.getActionIntent(); + if (wearableAction != null) { + PendingIntent actionIntent = wearableAction.getActionIntent(); Intent localIntent = new Intent(); localIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - Bundle extras = new Bundle(); - extras.putCharSequence(remoteInputs[0].getResultKey(), reply); - RemoteInput.addResultsToIntent(remoteInputs, localIntent, extras); - + if(wearableAction.getRemoteInputs()!=null) { + RemoteInput[] remoteInputs = wearableAction.getRemoteInputs(); + Bundle extras = new Bundle(); + extras.putCharSequence(remoteInputs[0].getResultKey(), reply); + RemoteInput.addResultsToIntent(remoteInputs, localIntent, extras); + } try { - LOG.info("will send reply intent to remote application"); + LOG.info("will send exec intent to remote application"); actionIntent.send(context, 0, localIntent); mActionLookup.remove(id); } catch (PendingIntent.CanceledException e) { @@ -209,15 +212,13 @@ public class NotificationListener extends NotificationListenerService { String source = sbn.getPackageName().toLowerCase(); Notification notification = sbn.getNotification(); - if (notificationTimes.containsKey(source)) { - long last_time = notificationTimes.get(source); - if (notification.when <= last_time) { - LOG.info("NOT processing notification, too old. notification.when: " + notification.when + " last notification for this source: " + last_time); + if (notificationOldRepeatPrevention.containsKey(source)) { + if (notification.when <= notificationOldRepeatPrevention.get(source)) { + LOG.info("NOT processing notification, already sent newer notifications from this source."); return; } } NotificationSpec notificationSpec = new NotificationSpec(); - notificationSpec.id = (int) sbn.getPostTime(); //FIXME: a truly unique id would be better // determinate Source App Name ("Label") PackageManager pm = getPackageManager(); @@ -249,7 +250,7 @@ public class NotificationListener extends NotificationListenerService { // Get color notificationSpec.pebbleColor = getPebbleColorForNotification(notificationSpec); - LOG.info("Processing notification " + notificationSpec.id + " from source " + source + " with flags: " + notification.flags); + LOG.info("Processing notification " + notificationSpec.getId() + " age: " + (System.currentTimeMillis() - notification.when) + " from source " + source + " with flags: " + notification.flags); dissectNotificationTo(notification, notificationSpec, preferBigText); @@ -263,16 +264,23 @@ public class NotificationListener extends NotificationListenerService { NotificationCompat.WearableExtender wearableExtender = new NotificationCompat.WearableExtender(notification); List actions = wearableExtender.getActions(); + notificationSpec.attachedActions = new ArrayList<>(); for (NotificationCompat.Action act : actions) { - if (act != null && act.getRemoteInputs() != null) { - LOG.info("found wearable action: " + act.getTitle() + " " + sbn.getTag()); - mActionLookup.add(notificationSpec.id, act); - notificationSpec.flags |= NotificationSpec.FLAG_WEARABLE_REPLY; - break; + if (act != null) { + NotificationSpec.Action wearableAction = new NotificationSpec.Action(); + wearableAction.title = act.getTitle().toString(); + if(act.getRemoteInputs()!=null) { + wearableAction.isReply = true; + } + notificationSpec.flags |= NotificationSpec.FLAG_WEARABLE_ACTIONS; + notificationSpec.attachedActions.add(wearableAction); + mActionLookup.add((notificationSpec.getId()<<4) + notificationSpec.attachedActions.size(), act); + LOG.info("found wearable action: " + notificationSpec.attachedActions.size() + " - "+ act.getTitle() + " " + sbn.getTag()); } } - if ((notificationSpec.flags & NotificationSpec.FLAG_WEARABLE_REPLY) == 0 && NotificationCompat.isGroupSummary(notification)) { //this could cause #395 to come back + + if ((notificationSpec.flags & NotificationSpec.FLAG_WEARABLE_ACTIONS) == 0 && NotificationCompat.isGroupSummary(notification)) { //this could cause #395 to come back LOG.info("Not forwarding notification, FLAG_GROUP_SUMMARY is set and no wearable action present. Notification flags: " + notification.flags); return; } @@ -280,14 +288,15 @@ public class NotificationListener extends NotificationListenerService { // Ignore too frequent notifications, according to user preference long min_timeout = prefs.getInt("notifications_timeout", 0) * 1000; long cur_time = System.currentTimeMillis(); - if (notificationTimes.containsKey(source)) { - long last_time = notificationTimes.get(source); + if (notificationBurstPrevention.containsKey(source)) { + long last_time = notificationBurstPrevention.get(source); if (cur_time - last_time < min_timeout) { LOG.info("Ignoring frequent notification, last one was " + (cur_time - last_time) + "ms ago"); return; } } - notificationTimes.put(source, cur_time); + notificationBurstPrevention.put(source, cur_time); + notificationOldRepeatPrevention.put(source, notification.when); GBApplication.deviceService().onNotification(notificationSpec); } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/externalevents/PebbleReceiver.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/externalevents/PebbleReceiver.java index a2091a662a..e8e889e643 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/externalevents/PebbleReceiver.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/externalevents/PebbleReceiver.java @@ -62,7 +62,6 @@ public class PebbleReceiver extends BroadcastReceiver { } NotificationSpec notificationSpec = new NotificationSpec(); - notificationSpec.id = -1; String notificationData = intent.getStringExtra("notificationData"); try { diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/externalevents/SMSReceiver.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/externalevents/SMSReceiver.java index be96e43816..0e1d774228 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/externalevents/SMSReceiver.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/externalevents/SMSReceiver.java @@ -50,7 +50,6 @@ public class SMSReceiver extends BroadcastReceiver { } NotificationSpec notificationSpec = new NotificationSpec(); - notificationSpec.id = -1; notificationSpec.type = NotificationType.GENERIC_SMS; Bundle bundle = intent.getExtras(); diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/impl/GBDeviceService.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/impl/GBDeviceService.java index 8542607888..d69c4d64c5 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/impl/GBDeviceService.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/impl/GBDeviceService.java @@ -150,8 +150,9 @@ public class GBDeviceService implements DeviceService { .putExtra(EXTRA_NOTIFICATION_SUBJECT, notificationSpec.subject) .putExtra(EXTRA_NOTIFICATION_TITLE, notificationSpec.title) .putExtra(EXTRA_NOTIFICATION_BODY, notificationSpec.body) - .putExtra(EXTRA_NOTIFICATION_ID, notificationSpec.id) + .putExtra(EXTRA_NOTIFICATION_ID, notificationSpec.getId()) .putExtra(EXTRA_NOTIFICATION_TYPE, notificationSpec.type) + .putExtra(EXTRA_NOTIFICATION_ACTIONS, notificationSpec.attachedActions) .putExtra(EXTRA_NOTIFICATION_SOURCENAME, notificationSpec.sourceName) .putExtra(EXTRA_NOTIFICATION_PEBBLE_COLOR, notificationSpec.pebbleColor) .putExtra(EXTRA_NOTIFICATION_SOURCEAPPID, notificationSpec.sourceAppId); diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/DeviceService.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/DeviceService.java index d15e858db1..974a1cbf23 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/DeviceService.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/DeviceService.java @@ -77,6 +77,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_ACTIONS = "notification_actions"; String EXTRA_NOTIFICATION_PEBBLE_COLOR = "notification_pebble_color"; String EXTRA_FIND_START = "find_start"; String EXTRA_VIBRATION_INTENSITY = "vibration_intensity"; diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/NotificationSpec.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/NotificationSpec.java index 7d0ff891f5..24503d42db 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/NotificationSpec.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/NotificationSpec.java @@ -16,11 +16,16 @@ along with this program. If not, see . */ package nodomain.freeyourgadget.gadgetbridge.model; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.concurrent.atomic.AtomicInteger; + public class NotificationSpec { - public static final int FLAG_WEARABLE_REPLY = 0x00000001; + public static final int FLAG_WEARABLE_ACTIONS = 0x00000001; public int flags; - public int id; + private static final AtomicInteger c = new AtomicInteger((int) (System.currentTimeMillis()/1000)); + private int id; public String sender; public String phoneNumber; public String title; @@ -29,7 +34,10 @@ public class NotificationSpec { public NotificationType type; public String sourceName; public String[] cannedReplies; - + /** + * Wearable actions that were attached to the incoming notifications and will be passed to the gadget (includes the "reply" action) + */ + public ArrayList attachedActions; /** * The application that generated the notification. */ @@ -39,4 +47,24 @@ public class NotificationSpec { * The color that should be assigned to this notification when displayed on a Pebble */ public byte pebbleColor; + + public NotificationSpec() { + this.id = c.incrementAndGet(); + } + + public NotificationSpec(int id) { + if (id != -1) + this.id = id; + else + this.id = c.incrementAndGet(); + } + + public int getId() { + return id; + } + + public static class Action implements Serializable { + public boolean isReply = false; + public String title; + } } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/AbstractDeviceSupport.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/AbstractDeviceSupport.java index 1f995e4ca3..d550539728 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/AbstractDeviceSupport.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/AbstractDeviceSupport.java @@ -52,8 +52,8 @@ import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventAppInfo; import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventBatteryInfo; import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventCallControl; import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventDisplayMessage; -import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventFmFrequency; import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventFindPhone; +import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventFmFrequency; import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventLEDColor; import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventMusicControl; import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventNotificationControl; @@ -337,6 +337,7 @@ public abstract class AbstractDeviceSupport implements DeviceSupport { if (action != null) { Intent notificationListenerIntent = new Intent(action); notificationListenerIntent.putExtra("handle", deviceEvent.handle); + notificationListenerIntent.putExtra("title", deviceEvent.title); if (deviceEvent.reply != null) { Prefs prefs = GBApplication.getPrefs(); String suffix = prefs.getString("canned_reply_suffix", null); diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/DeviceCommunicationService.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/DeviceCommunicationService.java index 065c8045a1..e96c59935b 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/DeviceCommunicationService.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/DeviceCommunicationService.java @@ -147,6 +147,7 @@ import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_MUS import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_MUSIC_TRACK; import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_MUSIC_TRACKCOUNT; import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_MUSIC_TRACKNR; +import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_NOTIFICATION_ACTIONS; 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; @@ -356,7 +357,8 @@ public class DeviceCommunicationService extends Service implements SharedPrefere mGBDevice.sendDeviceUpdateIntent(this); break; case ACTION_NOTIFICATION: { - NotificationSpec notificationSpec = new NotificationSpec(); + int desiredId = intent.getIntExtra(EXTRA_NOTIFICATION_ID, -1); + NotificationSpec notificationSpec = new NotificationSpec(desiredId); notificationSpec.phoneNumber = intent.getStringExtra(EXTRA_NOTIFICATION_PHONENUMBER); notificationSpec.sender = intent.getStringExtra(EXTRA_NOTIFICATION_SENDER); notificationSpec.subject = intent.getStringExtra(EXTRA_NOTIFICATION_SUBJECT); @@ -364,17 +366,17 @@ 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.attachedActions = (ArrayList) intent.getSerializableExtra(EXTRA_NOTIFICATION_ACTIONS); 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); notificationSpec.sourceAppId = intent.getStringExtra(EXTRA_NOTIFICATION_SOURCEAPPID); if (notificationSpec.type == NotificationType.GENERIC_SMS && notificationSpec.phoneNumber != null) { - notificationSpec.id = mRandom.nextInt(); // FIXME: add this in external SMS Receiver? - GBApplication.getIDSenderLookup().add(notificationSpec.id, notificationSpec.phoneNumber); + GBApplication.getIDSenderLookup().add(notificationSpec.getId(), notificationSpec.phoneNumber); } - if (((notificationSpec.flags & NotificationSpec.FLAG_WEARABLE_REPLY) > 0) + //TODO: check if at least one of the attached actions is a reply action instead? + if (((notificationSpec.flags & NotificationSpec.FLAG_WEARABLE_ACTIONS) > 0) || (notificationSpec.type == NotificationType.GENERIC_SMS && notificationSpec.phoneNumber != null)) { // NOTE: maybe not where it belongs if (prefs.getBoolean("pebble_force_untested", false)) { diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/pebble/PebbleProtocol.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/pebble/PebbleProtocol.java index a9ff4a8ade..74aa5b5044 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/pebble/PebbleProtocol.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/pebble/PebbleProtocol.java @@ -60,6 +60,7 @@ import nodomain.freeyourgadget.gadgetbridge.model.CallSpec; import nodomain.freeyourgadget.gadgetbridge.model.CannedMessagesSpec; import nodomain.freeyourgadget.gadgetbridge.model.MusicStateSpec; import nodomain.freeyourgadget.gadgetbridge.model.NotificationSpec; +import nodomain.freeyourgadget.gadgetbridge.model.NotificationSpec.Action; import nodomain.freeyourgadget.gadgetbridge.model.NotificationType; import nodomain.freeyourgadget.gadgetbridge.model.Weather; import nodomain.freeyourgadget.gadgetbridge.model.WeatherSpec; @@ -484,8 +485,9 @@ public class PebbleProtocol extends GBDeviceProtocol { @Override public byte[] encodeNotification(NotificationSpec notificationSpec) { - boolean hasHandle = notificationSpec.id != -1 && notificationSpec.phoneNumber == null; - int id = notificationSpec.id != -1 ? notificationSpec.id : mRandom.nextInt(); + //TODO: simplify this logic? is hasHandle still needed? + boolean hasHandle = notificationSpec.getId() != -1 && notificationSpec.phoneNumber == null; + int id = notificationSpec.getId() != -1 ? notificationSpec.getId() : mRandom.nextInt(); String title; String subtitle = null; @@ -507,11 +509,11 @@ public class PebbleProtocol extends GBDeviceProtocol { // 3.x notification return encodeBlobdbNotification(id, (int) (ts & 0xffffffffL), title, subtitle, notificationSpec.body, notificationSpec.sourceName, hasHandle, notificationSpec.type, notificationSpec.pebbleColor, - notificationSpec.cannedReplies); + notificationSpec.cannedReplies, notificationSpec.attachedActions); } 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); + notificationSpec.sourceName, hasHandle, notificationSpec.cannedReplies, notificationSpec.attachedActions); } else { // 1.x notification on FW 2.X String[] parts = {title, notificationSpec.body, String.valueOf(ts), subtitle}; @@ -594,7 +596,8 @@ public class PebbleProtocol extends GBDeviceProtocol { */ } - private byte[] encodeExtensibleNotification(int id, int timestamp, String title, String subtitle, String body, String sourceName, boolean hasHandle, String[] cannedReplies) { + //TODO: add support for attachedActions + private byte[] encodeExtensibleNotification(int id, int timestamp, String title, String subtitle, String body, String sourceName, boolean hasHandle, String[] cannedReplies, ArrayList attachedActions) { final short ACTION_LENGTH_MIN = 10; String[] parts = {title, subtitle, body}; @@ -930,7 +933,7 @@ public class PebbleProtocol extends GBDeviceProtocol { private byte[] encodeBlobdbNotification(int id, int timestamp, String title, String subtitle, String body, String sourceName, boolean hasHandle, NotificationType notificationType, byte backgroundColor, - String[] cannedReplies) { + String[] cannedReplies, ArrayList attachedActions) { final short NOTIFICATION_PIN_LENGTH = 46; final short ACTION_LENGTH_MIN = 10; @@ -943,36 +946,43 @@ public class PebbleProtocol extends GBDeviceProtocol { int icon_id = notificationType.icon; // Calculate length first - byte actions_count; - short actions_length; + byte actions_count = 0; + short actions_length = 0; String dismiss_string; String open_string = "Open on phone"; String mute_string = "Mute"; - String reply_string = "Reply"; if (sourceName != null) { mute_string += " " + sourceName; } byte dismiss_action_id; if (hasHandle && !"ALARMCLOCKRECEIVER".equals(sourceName)) { - actions_count = 3; + actions_count += 3; dismiss_string = "Dismiss"; dismiss_action_id = 0x02; - actions_length = (short) (ACTION_LENGTH_MIN * actions_count + dismiss_string.getBytes().length + open_string.getBytes().length + mute_string.getBytes().length); + //TODO: ACTION_LENGTH_MIN disagrees with my observation of the needed bytes. I used 6 instead of 10 + actions_length += (short) (6 * 3 + dismiss_string.getBytes().length + open_string.getBytes().length + mute_string.getBytes().length); } else { - actions_count = 1; + actions_count += 1; dismiss_string = "Dismiss all"; dismiss_action_id = 0x03; - actions_length = (short) (ACTION_LENGTH_MIN * actions_count + dismiss_string.getBytes().length); + actions_length += (short) (ACTION_LENGTH_MIN + dismiss_string.getBytes().length); + } + if (attachedActions != null && attachedActions.size() > 0) { + for (Action act : attachedActions) { + actions_count++; + actions_length += (short) (6 + act.title.getBytes().length); + } } int replies_length = -1; if (cannedReplies != null && cannedReplies.length > 0) { - actions_count++; + //do not increment actions_count! reply is an action and was already added above for (String reply : cannedReplies) { replies_length += reply.getBytes().length + 1; } - actions_length += ACTION_LENGTH_MIN + reply_string.getBytes().length + replies_length + 3; // 3 = attribute id (byte) + length(short) + //similarly, only the replies lenght has to be added, the lenght for the bare action was already added above + actions_length += replies_length + 3; // 3 = attribute id (byte) + length(short) } byte attributes_count = 2; // icon @@ -1053,21 +1063,31 @@ public class PebbleProtocol extends GBDeviceProtocol { buf.put(mute_string.getBytes()); } - if (cannedReplies != null && replies_length > 0) { - buf.put((byte) 0x05); - buf.put((byte) 0x03); // reply action - buf.put((byte) 0x02); // number attributes - buf.put((byte) 0x01); // title - buf.putShort((short) reply_string.getBytes().length); - buf.put(reply_string.getBytes()); - buf.put((byte) 0x08); // canned replies - buf.putShort((short) replies_length); - for (int i = 0; i < cannedReplies.length - 1; i++) { - buf.put(cannedReplies[i].getBytes()); - buf.put((byte) 0x00); + if (attachedActions != null && attachedActions.size() > 0) { + for (int ai = 0 ; ai= 0x00 && action <= 0x05) { + if (action >= 0x00 && action <= 0xf) { GBDeviceEventNotificationControl devEvtNotificationControl = new GBDeviceEventNotificationControl(); devEvtNotificationControl.handle = id; String caption = "undefined"; @@ -2125,6 +2145,7 @@ public class PebbleProtocol extends GBDeviceProtocol { caption = "Muted"; icon_id = PebbleIconID.RESULT_MUTE; break; + //TODO: 0x05 is not a special case anymore, and reply action might have an index that is higher. see default below case 0x05: case 0x00: boolean failed = true; @@ -2145,6 +2166,7 @@ public class PebbleProtocol extends GBDeviceProtocol { } devEvtNotificationControl.event = GBDeviceEventNotificationControl.Event.REPLY; devEvtNotificationControl.reply = new String(reply); + devEvtNotificationControl.handle = (devEvtNotificationControl.handle << 4) + 1; caption = "SENT"; icon_id = PebbleIconID.RESULT_SENT; failed = false; @@ -2156,6 +2178,19 @@ public class PebbleProtocol extends GBDeviceProtocol { devEvtNotificationControl = null; // error } break; + default: + if (action > 0x05) { + int simpleActionId = action - 0x05; + caption = "EXECUTED"; + devEvtNotificationControl.event = GBDeviceEventNotificationControl.Event.REPLY; + devEvtNotificationControl.handle = (devEvtNotificationControl.handle << 4) + simpleActionId; + LOG.info("detected simple action, subId:" + simpleActionId + " title:" + devEvtNotificationControl.title); + } else { + caption = "FAILED"; + icon_id = PebbleIconID.RESULT_FAILED; + devEvtNotificationControl = null; // error + } + break; } GBDeviceEventSendBytes sendBytesAck = null; if (mFwMajor >= 3 || needsAck2x) { From 086fc75629100402b9d9787b829bd5283cb785be Mon Sep 17 00:00:00 2001 From: Andreas Shimokawa Date: Wed, 31 Oct 2018 22:03:40 +0100 Subject: [PATCH 021/200] try to satisfy travis --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 616bc59d90..502f7e95a0 100644 --- a/.travis.yml +++ b/.travis.yml @@ -16,7 +16,7 @@ android: - tools # The BuildTools version used by your project - - build-tools-28.0.2 + - build-tools-28.0.3 # The SDK version used to compile your project - android-27 From f3e16c5b1de45befbc2fd6a1e7d5b2eebd2d46e1 Mon Sep 17 00:00:00 2001 From: Andreas Shimokawa Date: Thu, 1 Nov 2018 14:55:14 +0100 Subject: [PATCH 022/200] Pebble: Fix regression causing "Open on Phone" and "Dismiss" to appear on Pebble notification with no corresponding Android notification (i.e. PebbleKit notifications) --- .../gadgetbridge/service/devices/pebble/PebbleProtocol.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/pebble/PebbleProtocol.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/pebble/PebbleProtocol.java index 74aa5b5044..2a31534af9 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/pebble/PebbleProtocol.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/pebble/PebbleProtocol.java @@ -485,8 +485,7 @@ public class PebbleProtocol extends GBDeviceProtocol { @Override public byte[] encodeNotification(NotificationSpec notificationSpec) { - //TODO: simplify this logic? is hasHandle still needed? - boolean hasHandle = notificationSpec.getId() != -1 && notificationSpec.phoneNumber == null; + boolean hasHandle = notificationSpec.sourceAppId != null; int id = notificationSpec.getId() != -1 ? notificationSpec.getId() : mRandom.nextInt(); String title; String subtitle = null; From 22de76620d8145b1330067cdfab89c1298a1ba40 Mon Sep 17 00:00:00 2001 From: Andreas Shimokawa Date: Thu, 1 Nov 2018 15:04:16 +0100 Subject: [PATCH 023/200] Debug: Add button to send a PebbleKit notification --- .../gadgetbridge/activities/DebugActivity.java | 15 +++++++++++++++ app/src/main/res/layout/activity_debug.xml | 7 +++++++ 2 files changed, 22 insertions(+) diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/DebugActivity.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/DebugActivity.java index d9cc223598..475d229c2f 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/DebugActivity.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/DebugActivity.java @@ -224,6 +224,14 @@ public class DebugActivity extends AbstractGBActivity { } }); + Button testPebbleKitNotificationButton = findViewById(R.id.testPebbleKitNotificationButton); + testPebbleKitNotificationButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + testPebbleKitNotification(); + } + }); + Button fetchDebugLogsButton = findViewById(R.id.fetchDebugLogsButton); fetchDebugLogsButton.setOnClickListener(new View.OnClickListener() { @Override @@ -328,6 +336,13 @@ public class DebugActivity extends AbstractGBActivity { } } + private void testPebbleKitNotification() { + Intent pebbleKitIntent = new Intent("com.getpebble.action.SEND_NOTIFICATION"); + pebbleKitIntent.putExtra("messageType", "PEBBLE_ALERT"); + pebbleKitIntent.putExtra("notificationData", "[{\"title\":\"PebbleKitTest\",\"body\":\"sent from Gadgetbridge\"}]"); + getApplicationContext().sendBroadcast(pebbleKitIntent); + } + @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { diff --git a/app/src/main/res/layout/activity_debug.xml b/app/src/main/res/layout/activity_debug.xml index 6bbfe1b949..86088c0c53 100644 --- a/app/src/main/res/layout/activity_debug.xml +++ b/app/src/main/res/layout/activity_debug.xml @@ -124,6 +124,13 @@ grid:layout_columnSpan="2" grid:layout_gravity="fill_horizontal" android:text="create test notification" /> +