From 9cef4c5a012760ef3a62c715dfadfec48a0363fb Mon Sep 17 00:00:00 2001 From: AdrianLxM Date: Mon, 1 May 2017 18:09:53 +0200 Subject: [PATCH 1/7] typo insuin->insulin --- app/src/main/res/values/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 8a868dfef3..f51d0aded2 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -586,7 +586,7 @@ Fast Acting Insulin Novorapid, Novolog, Humalog INS - Fast Acting Insuin Prolonged + Fast Acting Insulin Prolonged key_usersuperbolus Enable superbolus in wizard Enable superbolus functionality in wizard. Do not enable until you learn what it really does. IT MAY CAUSE INSULIN OVERDOSE IF USED BLINDLY! From b80c382512b9ce5552f4545a1550cdf8b79157a8 Mon Sep 17 00:00:00 2001 From: Milos Kozak Date: Tue, 2 May 2017 22:49:17 +0200 Subject: [PATCH 2/7] fix exception in sms comm --- .../SmsCommunicatorPlugin.java | 185 +++++++++--------- 1 file changed, 94 insertions(+), 91 deletions(-) diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/SmsCommunicator/SmsCommunicatorPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/SmsCommunicator/SmsCommunicatorPlugin.java index 6e9d555268..b939c44e48 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/SmsCommunicator/SmsCommunicatorPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/SmsCommunicator/SmsCommunicatorPlugin.java @@ -262,102 +262,105 @@ public class SmsCommunicatorPlugin implements PluginBase { Answers.getInstance().logCustom(new CustomEvent("SMS_Bg")); break; case "LOOP": - switch (splited[1].toUpperCase()) { - case "DISABLE": - case "STOP": - LoopPlugin loopPlugin = (LoopPlugin) MainApp.getSpecificPlugin(LoopPlugin.class); - if (loopPlugin != null && loopPlugin.isEnabled(PluginBase.LOOP)) { - loopPlugin.setFragmentEnabled(PluginBase.LOOP, false); - reply = MainApp.sResources.getString(R.string.smscommunicator_loophasbeendisabled); - sendSMS(new Sms(receivedSms.phoneNumber, reply, new Date())); - } - receivedSms.processed = true; - Answers.getInstance().logCustom(new CustomEvent("SMS_Loop_Stop")); - break; - case "ENABLE": - case "START": - loopPlugin = (LoopPlugin) MainApp.getSpecificPlugin(LoopPlugin.class); - if (loopPlugin != null && !loopPlugin.isEnabled(PluginBase.LOOP)) { - loopPlugin.setFragmentEnabled(PluginBase.LOOP, true); - reply = MainApp.sResources.getString(R.string.smscommunicator_loophasbeenenabled); - sendSMS(new Sms(receivedSms.phoneNumber, reply, new Date())); - } - receivedSms.processed = true; - Answers.getInstance().logCustom(new CustomEvent("SMS_Loop_Start")); - break; - case "STATUS": - loopPlugin = (LoopPlugin) MainApp.getSpecificPlugin(LoopPlugin.class); - if (loopPlugin != null) { - if (loopPlugin.isEnabled(PluginBase.LOOP)) { - if (loopPlugin.isSuspended()) - reply = String.format(MainApp.sResources.getString(R.string.loopsuspendedfor), loopPlugin.minutesToEndOfSuspend()); - else - reply = MainApp.sResources.getString(R.string.smscommunicator_loopisenabled); - } else { - reply = MainApp.sResources.getString(R.string.smscommunicator_loopisdisabled); + if (splited.length > 1) + switch (splited[1].toUpperCase()) { + case "DISABLE": + case "STOP": + LoopPlugin loopPlugin = (LoopPlugin) MainApp.getSpecificPlugin(LoopPlugin.class); + if (loopPlugin != null && loopPlugin.isEnabled(PluginBase.LOOP)) { + loopPlugin.setFragmentEnabled(PluginBase.LOOP, false); + reply = MainApp.sResources.getString(R.string.smscommunicator_loophasbeendisabled); + sendSMS(new Sms(receivedSms.phoneNumber, reply, new Date())); } - sendSMS(new Sms(receivedSms.phoneNumber, reply, new Date())); - } - receivedSms.processed = true; - Answers.getInstance().logCustom(new CustomEvent("SMS_Loop_Status")); - break; - case "RESUME": - final LoopPlugin activeloop = MainApp.getConfigBuilder().getActiveLoop(); - activeloop.suspendTo(0); - MainApp.bus().post(new EventRefreshGui(false)); - reply = String.format(MainApp.sResources.getString(R.string.smscommunicator_loopresumed)); - sendSMSToAllNumbers(new Sms(receivedSms.phoneNumber, reply, new Date())); - Answers.getInstance().logCustom(new CustomEvent("SMS_Loop_Resume")); - break; - case "SUSPEND": - if (splited.length >= 3) - duration = SafeParse.stringToInt(splited[2]); - duration = Math.max(0, duration); - duration = Math.min(180, duration); - if (duration == 0) { - reply = MainApp.sResources.getString(R.string.smscommunicator_wrongduration); - sendSMS(new Sms(receivedSms.phoneNumber, reply, new Date())); - } else if (remoteCommandsAllowed) { - passCode = generatePasscode(); - reply = String.format(MainApp.sResources.getString(R.string.smscommunicator_suspendreplywithcode), duration, passCode); receivedSms.processed = true; - resetWaitingMessages(); - sendSMS(suspendWaitingForConfirmation = new Sms(receivedSms.phoneNumber, reply, new Date(), passCode)); - suspendWaitingForConfirmation.duration = duration; - Answers.getInstance().logCustom(new CustomEvent("SMS_Loop_Suspend")); - } else { - reply = MainApp.sResources.getString(R.string.smscommunicator_remotecommandnotallowed); - sendSMS(new Sms(receivedSms.phoneNumber, reply, new Date())); - } - break; - } + Answers.getInstance().logCustom(new CustomEvent("SMS_Loop_Stop")); + break; + case "ENABLE": + case "START": + loopPlugin = (LoopPlugin) MainApp.getSpecificPlugin(LoopPlugin.class); + if (loopPlugin != null && !loopPlugin.isEnabled(PluginBase.LOOP)) { + loopPlugin.setFragmentEnabled(PluginBase.LOOP, true); + reply = MainApp.sResources.getString(R.string.smscommunicator_loophasbeenenabled); + sendSMS(new Sms(receivedSms.phoneNumber, reply, new Date())); + } + receivedSms.processed = true; + Answers.getInstance().logCustom(new CustomEvent("SMS_Loop_Start")); + break; + case "STATUS": + loopPlugin = (LoopPlugin) MainApp.getSpecificPlugin(LoopPlugin.class); + if (loopPlugin != null) { + if (loopPlugin.isEnabled(PluginBase.LOOP)) { + if (loopPlugin.isSuspended()) + reply = String.format(MainApp.sResources.getString(R.string.loopsuspendedfor), loopPlugin.minutesToEndOfSuspend()); + else + reply = MainApp.sResources.getString(R.string.smscommunicator_loopisenabled); + } else { + reply = MainApp.sResources.getString(R.string.smscommunicator_loopisdisabled); + } + sendSMS(new Sms(receivedSms.phoneNumber, reply, new Date())); + } + receivedSms.processed = true; + Answers.getInstance().logCustom(new CustomEvent("SMS_Loop_Status")); + break; + case "RESUME": + final LoopPlugin activeloop = MainApp.getConfigBuilder().getActiveLoop(); + activeloop.suspendTo(0); + MainApp.bus().post(new EventRefreshGui(false)); + reply = String.format(MainApp.sResources.getString(R.string.smscommunicator_loopresumed)); + sendSMSToAllNumbers(new Sms(receivedSms.phoneNumber, reply, new Date())); + Answers.getInstance().logCustom(new CustomEvent("SMS_Loop_Resume")); + break; + case "SUSPEND": + if (splited.length >= 3) + duration = SafeParse.stringToInt(splited[2]); + duration = Math.max(0, duration); + duration = Math.min(180, duration); + if (duration == 0) { + reply = MainApp.sResources.getString(R.string.smscommunicator_wrongduration); + sendSMS(new Sms(receivedSms.phoneNumber, reply, new Date())); + } else if (remoteCommandsAllowed) { + passCode = generatePasscode(); + reply = String.format(MainApp.sResources.getString(R.string.smscommunicator_suspendreplywithcode), duration, passCode); + receivedSms.processed = true; + resetWaitingMessages(); + sendSMS(suspendWaitingForConfirmation = new Sms(receivedSms.phoneNumber, reply, new Date(), passCode)); + suspendWaitingForConfirmation.duration = duration; + Answers.getInstance().logCustom(new CustomEvent("SMS_Loop_Suspend")); + } else { + reply = MainApp.sResources.getString(R.string.smscommunicator_remotecommandnotallowed); + sendSMS(new Sms(receivedSms.phoneNumber, reply, new Date())); + } + break; + } break; case "TREATMENTS": - switch (splited[1].toUpperCase()) { - case "REFRESH": - Intent restartNSClient = new Intent(Intents.ACTION_RESTART); - MainApp.getDbHelper().resetTreatments(); - MainApp.instance().getApplicationContext().sendBroadcast(restartNSClient); - List q = MainApp.instance().getApplicationContext().getPackageManager().queryBroadcastReceivers(restartNSClient, 0); - reply = "TERATMENTS REFRESH " + q.size() + " receivers"; - sendSMS(new Sms(receivedSms.phoneNumber, reply, new Date())); - receivedSms.processed = true; - Answers.getInstance().logCustom(new CustomEvent("SMS_Treatments_Refresh")); - break; - } + if (splited.length > 1) + switch (splited[1].toUpperCase()) { + case "REFRESH": + Intent restartNSClient = new Intent(Intents.ACTION_RESTART); + MainApp.getDbHelper().resetTreatments(); + MainApp.instance().getApplicationContext().sendBroadcast(restartNSClient); + List q = MainApp.instance().getApplicationContext().getPackageManager().queryBroadcastReceivers(restartNSClient, 0); + reply = "TERATMENTS REFRESH " + q.size() + " receivers"; + sendSMS(new Sms(receivedSms.phoneNumber, reply, new Date())); + receivedSms.processed = true; + Answers.getInstance().logCustom(new CustomEvent("SMS_Treatments_Refresh")); + break; + } break; case "NSCLIENT": - switch (splited[1].toUpperCase()) { - case "RESTART": - Intent restartNSClient = new Intent(Intents.ACTION_RESTART); - MainApp.instance().getApplicationContext().sendBroadcast(restartNSClient); - List q = MainApp.instance().getApplicationContext().getPackageManager().queryBroadcastReceivers(restartNSClient, 0); - reply = "NSCLIENT RESTART " + q.size() + " receivers"; - sendSMS(new Sms(receivedSms.phoneNumber, reply, new Date())); - receivedSms.processed = true; - Answers.getInstance().logCustom(new CustomEvent("SMS_Nsclient_Restart")); - break; - } + if (splited.length > 1) + switch (splited[1].toUpperCase()) { + case "RESTART": + Intent restartNSClient = new Intent(Intents.ACTION_RESTART); + MainApp.instance().getApplicationContext().sendBroadcast(restartNSClient); + List q = MainApp.instance().getApplicationContext().getPackageManager().queryBroadcastReceivers(restartNSClient, 0); + reply = "NSCLIENT RESTART " + q.size() + " receivers"; + sendSMS(new Sms(receivedSms.phoneNumber, reply, new Date())); + receivedSms.processed = true; + Answers.getInstance().logCustom(new CustomEvent("SMS_Nsclient_Restart")); + break; + } break; case "DANAR": DanaRPlugin danaRPlugin = (DanaRPlugin) MainApp.getSpecificPlugin(DanaRPlugin.class); @@ -450,7 +453,7 @@ public class SmsCommunicatorPlugin implements PluginBase { PumpInterface pumpInterface = MainApp.getConfigBuilder(); if (pumpInterface != null) { danaRPlugin = (DanaRPlugin) MainApp.getSpecificPlugin(DanaRPlugin.class); - PumpEnactResult result = pumpInterface.deliverTreatment(MainApp.getConfigBuilder().getActiveInsulin() ,bolusWaitingForConfirmation.bolusRequested, 0, null); + PumpEnactResult result = pumpInterface.deliverTreatment(MainApp.getConfigBuilder().getActiveInsulin(), bolusWaitingForConfirmation.bolusRequested, 0, null); if (result.success) { reply = String.format(MainApp.sResources.getString(R.string.smscommunicator_bolusdelivered), result.bolusDelivered); if (danaRPlugin != null) From 037bb09d2379147c59271e89be4b90fbdc6617fe Mon Sep 17 00:00:00 2001 From: Milos Kozak Date: Wed, 3 May 2017 18:15:10 +0200 Subject: [PATCH 3/7] check for null --- .../IobCobCalculatorPlugin.java | 20 +++++++++++++++---- .../NSClientInternal/data/NSProfile.java | 4 ++-- 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/IobCobCalculator/IobCobCalculatorPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/IobCobCalculator/IobCobCalculatorPlugin.java index 725cd69a1e..d15435c1c1 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/IobCobCalculator/IobCobCalculatorPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/IobCobCalculator/IobCobCalculatorPlugin.java @@ -447,8 +447,20 @@ public class IobCobCalculatorPlugin implements PluginBase { Double[] deviations = new Double[deviationsArray.size()]; deviations = deviationsArray.toArray(deviations); + if (ConfigBuilderPlugin.getActiveProfile() == null || ConfigBuilderPlugin.getActiveProfile().getProfile() == null) { + log.debug("No profile available"); + return new AutosensResult(); + } + NSProfile profile = ConfigBuilderPlugin.getActiveProfile().getProfile(); + Double sens = profile.getIsf(NSProfile.secondsFromMidnight()); + + if (sens == null || profile.getMaxDailyBasal() == 0) { + log.debug("No profile available"); + return new AutosensResult(); + } + double ratio = 1; String ratioLimit = ""; String sensResult = ""; @@ -467,10 +479,10 @@ public class IobCobCalculatorPlugin implements PluginBase { double basalOff = 0; if (pSensitive < 0) { // sensitive - basalOff = pSensitive * (60 / 5) / NSProfile.toMgdl(profile.getIsf(NSProfile.secondsFromMidnight()), profile.getUnits()); + basalOff = pSensitive * (60 / 5) / NSProfile.toMgdl(sens, profile.getUnits()); sensResult = "Excess insulin sensitivity detected"; } else if (pResistant > 0) { // resistant - basalOff = pResistant * (60 / 5) / NSProfile.toMgdl(profile.getIsf(NSProfile.secondsFromMidnight()), profile.getUnits()); + basalOff = pResistant * (60 / 5) / NSProfile.toMgdl(sens, profile.getUnits()); sensResult = "Excess insulin resistance detected"; } else { sensResult = "Sensitivity normal"; @@ -487,9 +499,9 @@ public class IobCobCalculatorPlugin implements PluginBase { log.debug(ratioLimit); } - double newisf = Math.round(NSProfile.toMgdl(profile.getIsf(NSProfile.secondsFromMidnight()), profile.getUnits()) / ratio); + double newisf = Math.round(NSProfile.toMgdl(sens, profile.getUnits()) / ratio); if (ratio != 1) { - log.debug("ISF adjusted from " + NSProfile.toMgdl(profile.getIsf(NSProfile.secondsFromMidnight()), profile.getUnits()) + " to " + newisf); + log.debug("ISF adjusted from " + NSProfile.toMgdl(sens, profile.getUnits()) + " to " + newisf); } AutosensResult output = new AutosensResult(); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/data/NSProfile.java b/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/data/NSProfile.java index 9aee30e899..eb320ebfdb 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/data/NSProfile.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/data/NSProfile.java @@ -238,7 +238,7 @@ public class NSProfile { e.printStackTrace(); } } - return 0D; + return null; } public String getIsfList() { @@ -429,7 +429,7 @@ public class NSProfile { } } - public Double getMaxDailyBasal() { + public double getMaxDailyBasal() { Double max = 0d; for (Integer hour = 0; hour < 24; hour++) { double value = getBasal(hour * 60 * 60); From 37edc19509d5aa3662ef49c3d9fd5cbc219469d5 Mon Sep 17 00:00:00 2001 From: Milos Kozak Date: Wed, 3 May 2017 18:23:33 +0200 Subject: [PATCH 4/7] check for null --- .../plugins/IobCobCalculator/IobCobCalculatorPlugin.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/IobCobCalculator/IobCobCalculatorPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/IobCobCalculator/IobCobCalculatorPlugin.java index d15435c1c1..bbc06169b9 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/IobCobCalculator/IobCobCalculatorPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/IobCobCalculator/IobCobCalculatorPlugin.java @@ -234,7 +234,7 @@ public class IobCobCalculatorPlugin implements PluginBase { synchronized (dataLock) { NSProfile profile = ConfigBuilderPlugin.getActiveProfile() != null ? ConfigBuilderPlugin.getActiveProfile().getProfile() : null; - if (profile == null) { + if (profile == null || profile.getIsf(NSProfile.secondsFromMidnight()) == null || profile.getIc(NSProfile.secondsFromMidnight()) == null) { log.debug("calculateSensitivityData: No profile available"); return; } From 573256d7d4c8d620674b6240b3aa6a5619aa3fe7 Mon Sep 17 00:00:00 2001 From: Milos Kozak Date: Wed, 3 May 2017 18:30:18 +0200 Subject: [PATCH 5/7] catch missing sms permission --- .../nightscout/androidaps/plugins/Overview/Notification.java | 3 ++- .../plugins/SmsCommunicator/SmsCommunicatorPlugin.java | 3 +++ app/src/main/res/values-cs/strings.xml | 2 ++ app/src/main/res/values/strings.xml | 1 + 4 files changed, 8 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Notification.java b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Notification.java index 0508917312..3666573d0a 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Notification.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Notification.java @@ -23,7 +23,8 @@ public class Notification { public static final int OLD_NSCLIENT = 8; public static final int INVALID_PHONE_NUMBER = 9; public static final int APPROACHING_DAILY_LIMIT = 10; - public static final int NSCLIENT_NO_WRITE_PERMISSION = 10; + public static final int NSCLIENT_NO_WRITE_PERMISSION = 11; + public static final int MISSING_SMS_PERMISSION = 12; public int id; public Date date; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/SmsCommunicator/SmsCommunicatorPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/SmsCommunicator/SmsCommunicatorPlugin.java index b939c44e48..1a7501ba1a 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/SmsCommunicator/SmsCommunicatorPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/SmsCommunicator/SmsCommunicatorPlugin.java @@ -560,6 +560,9 @@ public class SmsCommunicatorPlugin implements PluginBase { } catch (IllegalArgumentException e) { Notification notification = new Notification(Notification.INVALID_PHONE_NUMBER, MainApp.sResources.getString(R.string.smscommunicator_invalidphonennumber), Notification.NORMAL); MainApp.bus().post(new EventNewNotification(notification)); + } catch (java.lang.SecurityException e) { + Notification notification = new Notification(Notification.MISSING_SMS_PERMISSION, MainApp.sResources.getString(R.string.smscommunicator_missingsmspermission), Notification.NORMAL); + MainApp.bus().post(new EventNewNotification(notification)); } } diff --git a/app/src/main/res/values-cs/strings.xml b/app/src/main/res/values-cs/strings.xml index 17af068120..2db034da62 100644 --- a/app/src/main/res/values-cs/strings.xml +++ b/app/src/main/res/values-cs/strings.xml @@ -544,4 +544,6 @@ Povolit superbolus Povolení superbolusu v kalkulátoru. Nepovolujte, dokud se nenaučíte, co to opravdu dělá. MŮŽE ZPŮSOBIT PŘEDÁVKOVÁNÍ INZULÍNEM PŘI NESPRÁVNÉM POUŽITÍ! O aplikaci + O aplikaci + Chybějící povolení SMS diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 8a868dfef3..439d5ee882 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -598,4 +598,5 @@ Last connection Bluetooh status About + Missing SMS permission From 10d5b914f3febd7b8f45e1636e4d6da925a5ba55 Mon Sep 17 00:00:00 2001 From: Milos Kozak Date: Wed, 3 May 2017 18:37:00 +0200 Subject: [PATCH 6/7] check for finished activity --- .../plugins/Actions/dialogs/NewTempBasalDialog.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Actions/dialogs/NewTempBasalDialog.java b/app/src/main/java/info/nightscout/androidaps/plugins/Actions/dialogs/NewTempBasalDialog.java index 2d5a4580c4..6930a0de21 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Actions/dialogs/NewTempBasalDialog.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Actions/dialogs/NewTempBasalDialog.java @@ -1,5 +1,6 @@ package info.nightscout.androidaps.plugins.Actions.dialogs; +import android.app.Activity; import android.content.Context; import android.content.DialogInterface; import android.os.Bundle; @@ -153,6 +154,12 @@ public class NewTempBasalDialog extends DialogFragment implements View.OnClickLi result = pump.setTempBasalAbsolute(finalBasal, finalDurationInMinutes); } if (!result.success) { + if (context instanceof Activity) { + Activity activity = (Activity) context; + if (activity.isFinishing()) { + return; + } + } AlertDialog.Builder builder = new AlertDialog.Builder(context); builder.setTitle(MainApp.sResources.getString(R.string.tempbasaldeliveryerror)); builder.setMessage(result.comment); From 6d5f2514d0e1461eb58b9c91a034010a2bb39f09 Mon Sep 17 00:00:00 2001 From: Milos Kozak Date: Wed, 3 May 2017 18:45:29 +0200 Subject: [PATCH 7/7] remove duplicated string --- app/src/main/res/values-cs/strings.xml | 1 - 1 file changed, 1 deletion(-) diff --git a/app/src/main/res/values-cs/strings.xml b/app/src/main/res/values-cs/strings.xml index 2db034da62..0ef84e446b 100644 --- a/app/src/main/res/values-cs/strings.xml +++ b/app/src/main/res/values-cs/strings.xml @@ -544,6 +544,5 @@ Povolit superbolus Povolení superbolusu v kalkulátoru. Nepovolujte, dokud se nenaučíte, co to opravdu dělá. MŮŽE ZPŮSOBIT PŘEDÁVKOVÁNÍ INZULÍNEM PŘI NESPRÁVNÉM POUŽITÍ! O aplikaci - O aplikaci Chybějící povolení SMS