diff --git a/app/src/main/java/com/eveningoutpost/dexdrip/cgm/carelinkfollow/CareLinkFollowDownloader.java b/app/src/main/java/com/eveningoutpost/dexdrip/cgm/carelinkfollow/CareLinkFollowDownloader.java index 9b990ec132..a7bf88176c 100644 --- a/app/src/main/java/com/eveningoutpost/dexdrip/cgm/carelinkfollow/CareLinkFollowDownloader.java +++ b/app/src/main/java/com/eveningoutpost/dexdrip/cgm/carelinkfollow/CareLinkFollowDownloader.java @@ -2,6 +2,7 @@ import android.os.PowerManager; +import com.eveningoutpost.dexdrip.R; import com.eveningoutpost.dexdrip.cgm.carelinkfollow.auth.CareLinkAuthenticator; import com.eveningoutpost.dexdrip.cgm.carelinkfollow.auth.CareLinkCredentialStore; import com.eveningoutpost.dexdrip.models.JoH; @@ -10,6 +11,7 @@ import com.eveningoutpost.dexdrip.utilitymodels.Inevitable; import com.eveningoutpost.dexdrip.cgm.carelinkfollow.client.CareLinkClient; import com.eveningoutpost.dexdrip.cgm.carelinkfollow.message.RecentData; +import com.eveningoutpost.dexdrip.xdrip; import static com.eveningoutpost.dexdrip.models.JoH.emptyString; @@ -64,7 +66,7 @@ public void doEverything(boolean refreshToken, boolean downloadData) { } private void downloadData() { - msg("Start download"); + msg(xdrip.gs(R.string.carelink_download_start)); if (checkCredentials(true, true, true)) { try { if (getCareLinkClient() != null) { @@ -72,30 +74,30 @@ private void downloadData() { backgroundProcessConnectData(); } else { UserError.Log.d(TAG, "Cannot get data as CareLinkClient is null"); - msg("Download data failed!"); + msg(xdrip.gs(R.string.carelink_download_failed)); } } catch (Exception e) { UserError.Log.e(TAG, "Got exception in getData() " + e); releaseWakeLock(); - msg("Download data failed!"); + msg(xdrip.gs(R.string.carelink_download_failed)); } } } private void refreshToken() { - msg("Start refreshing token"); + msg(xdrip.gs(R.string.carelink_refresh_token_start)); if (checkCredentials(true, false, true)) { try { if (new CareLinkAuthenticator(CareLinkCredentialStore.getInstance().getCredential().country, CareLinkCredentialStore.getInstance()).refreshToken()) { - UserError.Log.d(TAG, "Access token renewed!"); + UserError.Log.d(TAG, "Access renewed!"); msg(null); } else { UserError.Log.e(TAG, "Error renewing access token!"); - msg("Access refresh failed! Will try again!"); + msg(xdrip.gs(R.string.carelink_refresh_token_failed)); } } catch (Exception e) { UserError.Log.e(TAG, "Error renewing access token: " + e.getMessage()); - msg("Access refresh failed! Will try again!"); + msg(xdrip.gs(R.string.carelink_refresh_token_failed)); } } } @@ -103,15 +105,15 @@ private void refreshToken() { private boolean checkCredentials(boolean checkAuthenticated, boolean checkAccessExpired, boolean checkRefreshExpired) { // Not authenticated if (checkAuthenticated && CareLinkCredentialStore.getInstance().getAuthStatus() != CareLinkCredentialStore.AUTHENTICATED) { - msg("Not logged in! Please log in!"); + msg(xdrip.gs(R.string.carelink_credential_status_not_authenticated)); return false; } if (checkAccessExpired && CareLinkCredentialStore.getInstance().getAccessExpiresIn() <= 0) { - msg("Access expired!"); + msg(xdrip.gs(R.string.carelink_credential_status_access_expired)); return false; } if (checkRefreshExpired && CareLinkCredentialStore.getInstance().getRefreshExpiresIn() <= 0) { - msg("Login expired! Please log in!"); + msg(xdrip.gs(R.string.carelink_credential_status_refresh_expired)); return false; } return true; diff --git a/app/src/main/java/com/eveningoutpost/dexdrip/cgm/carelinkfollow/auth/CareLinkAuthenticator.java b/app/src/main/java/com/eveningoutpost/dexdrip/cgm/carelinkfollow/auth/CareLinkAuthenticator.java index e38e5bca38..e46ca44bf7 100644 --- a/app/src/main/java/com/eveningoutpost/dexdrip/cgm/carelinkfollow/auth/CareLinkAuthenticator.java +++ b/app/src/main/java/com/eveningoutpost/dexdrip/cgm/carelinkfollow/auth/CareLinkAuthenticator.java @@ -11,10 +11,14 @@ import android.support.v7.widget.LinearLayoutCompat; import android.view.ViewGroup; import android.webkit.CookieManager; +import android.webkit.WebResourceError; +import android.webkit.WebResourceRequest; import android.webkit.WebView; import android.webkit.WebViewClient; +import com.eveningoutpost.dexdrip.R; import com.eveningoutpost.dexdrip.models.UserError; +import com.eveningoutpost.dexdrip.xdrip; import com.google.gson.JsonArray; import com.google.gson.JsonElement; import com.google.gson.JsonObject; @@ -107,13 +111,10 @@ public class CareLinkAuthenticator { private String carelinkCountry; private CareLinkCredentialStore credentialStore; private CarePartnerAppConfig carepartnerAppConfig; - private String deviceId = null; - private String androidModel; - private String clientId = null; - private String clientSecret = null; - private String magIdentifier = null; private String authCode = null; private OkHttpClient httpClient = null; + private boolean authWebViewCancelled = false; + private boolean carelinkCommunicationError = false; public CareLinkAuthenticator(String carelinkCountry, CareLinkCredentialStore credentialStore) { @@ -126,6 +127,7 @@ public boolean authenticate(Activity context, CareLinkAuthType authType) throws if (Looper.myLooper() == Looper.getMainLooper()) throw new RuntimeException("don't call authenticate() from the main thread."); + //Execute authentication method of authentication type switch (authType) { case Browser: this.authenticateAsBrowser(context); @@ -135,6 +137,7 @@ public boolean authenticate(Activity context, CareLinkAuthType authType) throws break; } + //Return: is authenticated return (credentialStore.getAuthStatus() == CareLinkCredentialStore.AUTHENTICATED); } @@ -154,24 +157,31 @@ public boolean refreshToken() { } } - private void authenticateAsCpApp(Activity context) throws InterruptedException { + private void authenticateAsCpApp(Activity context) { + String deviceId; + String androidModel; + String clientId; + String clientSecret; + String magIdentifier; JsonObject clientCredential; - String codeVerifier = null; + String codeVerifier; String authUrl; - String idToken = null; - String idTokenType = null; + String idToken; + String idTokenType; try { - //Show progress dialog + carelinkCommunicationError = false; + + //Show progress dialog while preparing for login page this.showProgressDialog(context); - //Generate IDs, models + //Generate ID, models deviceId = generateDeviceId(); androidModel = this.generateAndroidModel(); - //Load App config + //Load application config this.loadAppConfig(); //Create client credential @@ -197,38 +207,62 @@ public void run() { }); available.acquire(); - //Show progress dialog - this.showProgressDialog(context); - - //Register device - UserError.Log.d(TAG, "Register device"); - Response registerResp = this.registerDevice(deviceId, androidModel, clientId, clientSecret, authCode, codeVerifier); - magIdentifier = registerResp.header("mag-identifier"); - idToken = registerResp.header("id-token"); - idTokenType = registerResp.header("id-token-type"); - - //Get access token - UserError.Log.d(TAG, "Get access token"); - JsonObject tokenObject = this.getAccessToken(clientId, clientSecret, magIdentifier, idToken, idTokenType); - - //Store credentials - UserError.Log.d(TAG, "Store credentials"); - this.credentialStore.setMobileAppCredential(this.carelinkCountry, - this.deviceId, this.androidModel, this.clientId, this.clientSecret, this.magIdentifier, - tokenObject.get("access_token").getAsString(), tokenObject.get("refresh_token").getAsString(), - //new Date(Calendar.getInstance().getTime().getTime() + 15 * 60000), - //new Date(Calendar.getInstance().getTime().getTime() + 30 * 60000)); - new Date(Calendar.getInstance().getTime().getTime() + (tokenObject.get("expires_in").getAsInt() * 1000)), - new Date(Calendar.getInstance().getTime().getTime() + (this.carepartnerAppConfig.getRefreshLifetimeSec() * 1000))); - - //Hide progress dialog - this.hideProgressDialog(); + //Continue if not cancelled and no error + if (!this.authWebViewCancelled && !carelinkCommunicationError) { + //Show progress dialog while completing authentication + this.showProgressDialog(context); + + //Register device + UserError.Log.d(TAG, "Register device"); + Response registerResp = this.registerDevice(deviceId, androidModel, clientId, clientSecret, authCode, codeVerifier); + magIdentifier = registerResp.header("mag-identifier"); + idToken = registerResp.header("id-token"); + idTokenType = registerResp.header("id-token-type"); + + //Get access token + UserError.Log.d(TAG, "Get access token"); + JsonObject tokenObject = this.getAccessToken(clientId, clientSecret, magIdentifier, idToken, idTokenType); + + //Store credentials + UserError.Log.d(TAG, "Store credentials"); + this.credentialStore.setMobileAppCredential(this.carelinkCountry, + deviceId, androidModel, clientId, clientSecret, magIdentifier, + tokenObject.get("access_token").getAsString(), tokenObject.get("refresh_token").getAsString(), + //new Date(Calendar.getInstance().getTime().getTime() + 15 * 60000), + //new Date(Calendar.getInstance().getTime().getTime() + 30 * 60000)); + new Date(Calendar.getInstance().getTime().getTime() + (tokenObject.get("expires_in").getAsInt() * 1000)), + new Date(Calendar.getInstance().getTime().getTime() + (this.carepartnerAppConfig.getRefreshLifetimeSec() * 1000))); + + //Hide progress dialog + this.hideProgressDialog(); + } } catch (Exception ex) { - UserError.Log.e(TAG, "Error authenticating as CpApp. Details: " + ex.getMessage()); + UserError.Log.e(TAG, "Error authenticating as CpApp. Details: \r\n " + ex.getMessage()); + carelinkCommunicationError = true; this.hideProgressDialog(); } + //Show communication error + if (carelinkCommunicationError) { + new Handler(Looper.getMainLooper()).post(new Runnable() { + @Override + public void run() { + new AlertDialog.Builder(context) + .setTitle("Communication error!") + .setMessage("Error communicating with CareLink Server! Please try again later!") + .setCancelable(true) + .setNeutralButton(R.string.ok, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialogInterface, int i) { + dialogInterface.cancel(); + } + }) + .show(); + } + }); + } + } private void authenticateAsBrowser(Activity context) throws InterruptedException { @@ -244,23 +278,20 @@ public void run() { } private OkHttpClient getHttpClient() { - return new OkHttpClient.Builder().build(); - } - - private boolean loadAppConfig() { - try { - if (carepartnerAppConfig == null) { - carepartnerAppConfig = new CarePartnerAppConfig(); - UserError.Log.d(TAG, "Get region config"); - carepartnerAppConfig.regionConfig = this.getCpAppRegionConfig(); - UserError.Log.d(TAG, "Get SSO config"); - carepartnerAppConfig.ssoConfig = this.getCpAppSSOConfig(carepartnerAppConfig.getSSOConfigUrl()); - } - return true; - } catch (Exception ex) { - UserError.Log.e(TAG, "Error getting AppConfig. Details: " + ex.getMessage()); - return false; + if (this.httpClient == null) + this.httpClient = new OkHttpClient(); + return this.httpClient; + } + + private boolean loadAppConfig() throws IOException { + if (carepartnerAppConfig == null) { + carepartnerAppConfig = new CarePartnerAppConfig(); + UserError.Log.d(TAG, "Get region config"); + carepartnerAppConfig.regionConfig = this.getCpAppRegionConfig(); + UserError.Log.d(TAG, "Get SSO config"); + carepartnerAppConfig.ssoConfig = this.getCpAppSSOConfig(carepartnerAppConfig.getSSOConfigUrl()); } + return true; } private JsonObject getAccessToken(String clientId, String clientSecret, String magIdentifier, String idToken, String idTokenType) throws IOException { @@ -273,8 +304,8 @@ private JsonObject refreshToken(String clientId, String clientSecret, String mag private JsonObject getToken(String clientId, String clientSecret, String magIdentifier, String idToken, String idTokenType, String refreshToken) throws IOException { - Request.Builder requestBuilder = null; - FormBody.Builder form = null; + Request.Builder requestBuilder; + FormBody.Builder form; //Common token request params form = new FormBody.Builder() @@ -300,42 +331,38 @@ private JsonObject getToken(String clientId, String clientSecret, String magIden } - private Response registerDevice(String deviceId, String androidModel, String clientId, String clientSecret, String authCode, String codeVerifier) { + private Response registerDevice(String deviceId, String androidModel, String clientId, String clientSecret, String authCode, String codeVerifier) throws IOException { String trimmedCsr = null; - Response response = null; - String cert = null; + //Create RSA2048 keypair and CSR try { - //Create RSA2048 keypair and CSR KeyPairGenerator keygen = KeyPairGenerator.getInstance("RSA"); keygen.initialize(2048); KeyPair keypair = keygen.genKeyPair(); trimmedCsr = createTrimmedCsr(keypair, "SHA256withRSA", "socialLogin", deviceId, androidModel, "Medtronic"); + } catch (Exception e) { + UserError.Log.e(TAG, "Error creating CSR! Details: \r\n" + e.getMessage()); + } + //Register device and get certificate for CSR + RequestBody body; + Request.Builder requestBuilder; - RequestBody body; - Request.Builder requestBuilder; - - body = RequestBody.create(null, trimmedCsr); - - requestBuilder = new Request.Builder() - .post(body) - .addHeader("device-id", Base64.encodeToString(deviceId.getBytes(StandardCharsets.UTF_8), Base64.NO_WRAP)) - .addHeader("device-name", Base64.encodeToString(androidModel.getBytes(StandardCharsets.UTF_8), Base64.NO_WRAP)) - .addHeader("authorization", "Bearer " + authCode) - .addHeader("client-authorization", "Basic " + Base64.encodeToString((clientId + ":" + clientSecret).getBytes(StandardCharsets.UTF_8), Base64.NO_WRAP)) - .addHeader("cert-format", "pem") - .addHeader("create-session", "true") - .addHeader("code-verifier", codeVerifier) - .addHeader("redirect-uri", carepartnerAppConfig.getOAuthRedirectUri()); + body = RequestBody.create(null, trimmedCsr); - return response = this.callSsoApi(requestBuilder, carepartnerAppConfig.getMagDeviceRegisterEndpoint(), null); + requestBuilder = new Request.Builder() + .post(body) + .addHeader("device-id", Base64.encodeToString(deviceId.getBytes(StandardCharsets.UTF_8), Base64.NO_WRAP)) + .addHeader("device-name", Base64.encodeToString(androidModel.getBytes(StandardCharsets.UTF_8), Base64.NO_WRAP)) + .addHeader("authorization", "Bearer " + authCode) + .addHeader("client-authorization", "Basic " + Base64.encodeToString((clientId + ":" + clientSecret).getBytes(StandardCharsets.UTF_8), Base64.NO_WRAP)) + .addHeader("cert-format", "pem") + .addHeader("create-session", "true") + .addHeader("code-verifier", codeVerifier) + .addHeader("redirect-uri", carepartnerAppConfig.getOAuthRedirectUri()); - } catch (Exception ex) { - ex.getMessage(); - return null; - } + return this.callSsoApi(requestBuilder, carepartnerAppConfig.getMagDeviceRegisterEndpoint(), null); } @@ -361,10 +388,10 @@ private String createTrimmedCsr(KeyPair keypair, String signAlgo, String cn, Str private String prepareAuth(String clientId, String codeVerifier) throws IOException { - Request.Builder requestBuilder = null; - Map queryParams = null; + Request.Builder requestBuilder; + Map queryParams; String codeChallenge = null; - JsonObject providers = null; + JsonObject providers; //Generate SHA-256 code challenge try { @@ -374,7 +401,7 @@ private String prepareAuth(String clientId, String codeVerifier) throws IOExcept } catch (Exception ex) { } - //Set query params + //Set params queryParams = new HashMap(); queryParams.put("client_id", clientId); queryParams.put("response_type", "code"); @@ -427,7 +454,7 @@ private String generateDeviceId() { stringBuilder.append(String.format("%02x", byteChar)); return stringBuilder.toString(); } catch (NoSuchAlgorithmException e) { - e.printStackTrace(); + UserError.Log.e(TAG, "Error generating deviceId! Details: \r\n" + e.getMessage()); } return null; @@ -482,10 +509,13 @@ private boolean refreshCpAppToken() { JsonObject tokenRefreshResult; try { + //Get config this.loadAppConfig(); + //Refresh token tokenRefreshResult = this.refreshToken( credentialStore.getCredential().clientId, credentialStore.getCredential().clientSecret, credentialStore.getCredential().magIdentifier, credentialStore.getCredential().refreshToken); + //Save token credentialStore.updateMobileAppCredential( tokenRefreshResult.get("access_token").getAsString(), //new Date(Calendar.getInstance().getTime().getTime() + 15 * 60000), @@ -493,9 +523,10 @@ private boolean refreshCpAppToken() { new Date(Calendar.getInstance().getTime().getTime() + (tokenRefreshResult.get("expires_in").getAsInt() * 1000)), new Date(Calendar.getInstance().getTime().getTime() + (this.carepartnerAppConfig.getRefreshLifetimeSec() * 1000)), tokenRefreshResult.get("refresh_token").getAsString()); + //Completed successfully return true; } catch (Exception ex) { - UserError.Log.e(TAG, "Error refreshing CpApp token! Details: " + ex.getMessage()); + UserError.Log.e(TAG, "Error refreshing CpApp token! Details: \r\n" + ex.getMessage()); return false; } } @@ -506,11 +537,11 @@ private boolean refreshBrowserToken() { if (credentialStore.getAuthStatus() == CareLinkCredentialStore.NOT_AUTHENTICATED) return false; - HttpUrl url = null; - OkHttpClient httpClient = null; - Request.Builder requestBuilder = null; - Response response = null; - EditableCookieJar cookieJar = null; + HttpUrl url; + OkHttpClient httpClient; + Request.Builder requestBuilder; + Response response; + EditableCookieJar cookieJar; //Build client with cookies from CredentialStore @@ -577,18 +608,16 @@ public void run() { } private void hideProgressDialog() { - if (this.progressDialog != null && this.progressDialog.isShowing()) { this.progressDialog.dismiss(); } - } private AlertDialog getProgressDialog(Activity context) { if (this.progressDialog == null) { AlertDialog.Builder builder; builder = new AlertDialog.Builder(context); - builder.setTitle("Login in progress..."); + builder.setTitle(xdrip.gs(R.string.carelink_auth_login_in_progress)); final ProgressBar progressBar = new ProgressBar(context); LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams( LinearLayout.LayoutParams.WRAP_CONTENT, @@ -602,7 +631,6 @@ private AlertDialog getProgressDialog(Activity context) { } private void showBrowserAuthPage(Activity context, String url) { - final Dialog authDialog = new Dialog(context); this.showAuthWebView(authDialog, url, new WebViewClient() { @Override @@ -624,13 +652,25 @@ private void showCpAppAuthPage(Activity context, String url) { @Override public void onPageStarted(WebView view, String url, Bitmap favicon) { if (CareLinkAuthenticator.this.extractCpAppAuthCode(url)) + //close browser dialog + authDialog.dismiss(); + } + + @Override + public void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error) { + //Connection error + if (error.getErrorCode() == WebViewClient.ERROR_CONNECT) { + carelinkCommunicationError = true; authDialog.dismiss(); + } } }); } private void showAuthWebView(Dialog authDialog, String url, WebViewClient webViewClient) { + this.authWebViewCancelled = false; + LinearLayoutCompat layout = new LinearLayoutCompat(authDialog.getContext()); WebView webView = new WebView(authDialog.getContext()); webView.setLayoutParams(new LinearLayoutCompat.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); @@ -643,6 +683,12 @@ public void onDismiss(DialogInterface dialog) { unlock(); } }); + authDialog.setOnCancelListener(new DialogInterface.OnCancelListener() { + @Override + public void onCancel(DialogInterface dialogInterface) { + authWebViewCancelled = true; + } + }); //Configure Webview webView.getSettings().setJavaScriptEnabled(true); @@ -650,7 +696,7 @@ public void onDismiss(DialogInterface dialog) { webView.loadUrl(url); webView.setWebViewClient(webViewClient); - //Set dialog display infos and show it + //Set dialog display params and show it authDialog.setCancelable(true); authDialog.getWindow().setLayout(LinearLayoutCompat.LayoutParams.MATCH_PARENT, LinearLayoutCompat.LayoutParams.MATCH_PARENT); authDialog.show(); @@ -659,7 +705,7 @@ public void onDismiss(DialogInterface dialog) { private boolean extractCpAppAuthCode(String url) { - //When directed to redirect uri => extract code + //Redirect url => extract code, completed if (url.contains(this.carepartnerAppConfig.getOAuthRedirectUri())) { try { UrlQuerySanitizer sanitizer = new UrlQuerySanitizer(); @@ -667,14 +713,16 @@ private boolean extractCpAppAuthCode(String url) { sanitizer.parseUrl(url); authCode = sanitizer.getValue("code"); } catch (Exception ex) { + UserError.Log.e(TAG, "Error extracting authCode! Details: \r\n" + ex.getMessage()); } return true; + //Other url => authentication not completed yet } else return false; } - private JsonObject getCpAppRegionConfig() { + private JsonObject getCpAppRegionConfig() throws IOException { //Get CarePartner app discover @@ -697,27 +745,20 @@ private JsonObject getCpAppRegionConfig() { } - private JsonObject getCpAppSSOConfig(String url) { + private JsonObject getCpAppSSOConfig(String url) throws IOException { return this.getConfigJson(url); } - private JsonObject getConfigJson(String url) { + private JsonObject getConfigJson(String url) throws IOException { - Request request = null; + Request request; request = new Request.Builder() .url(url) .get() .build(); - try { - Response response = this.getHttpClient().newCall(request).execute(); - if (response.isSuccessful()) { - return JsonParser.parseString(response.body().string()).getAsJsonObject(); - } - } catch (Exception ex) { - } - - return null; + Response response = this.getHttpClient().newCall(request).execute(); + return JsonParser.parseString(response.body().string()).getAsJsonObject(); } @@ -806,6 +847,7 @@ private void unlock() { private Date parseValidTo(String validToDateString) { for (SimpleDateFormat zonedFormat : VALIDTO_DATE_FORMATS) { + //try until translate is successful try { return zonedFormat.parse(validToDateString); } catch (Exception ex) { diff --git a/app/src/main/java/com/eveningoutpost/dexdrip/utilitymodels/BroadcastGlucose.java b/app/src/main/java/com/eveningoutpost/dexdrip/utilitymodels/BroadcastGlucose.java index 54fad3cb9d..3c3cc73957 100644 --- a/app/src/main/java/com/eveningoutpost/dexdrip/utilitymodels/BroadcastGlucose.java +++ b/app/src/main/java/com/eveningoutpost/dexdrip/utilitymodels/BroadcastGlucose.java @@ -143,6 +143,7 @@ public static void sendLocalBroadcast(final BgReading bgReading) { } bundle.putInt(Intents.EXTRA_SENSOR_BATTERY, BridgeBattery.getBestBridgeBattery()); + bundle.putLong(Intents.EXTRA_SENSOR_STARTED_AT, sensor.started_at); bundle.putLong(Intents.EXTRA_TIMESTAMP, bgReading.timestamp); //raw value diff --git a/app/src/main/java/com/eveningoutpost/dexdrip/utilitymodels/Intents.java b/app/src/main/java/com/eveningoutpost/dexdrip/utilitymodels/Intents.java index c6ee4c6827..6016857247 100644 --- a/app/src/main/java/com/eveningoutpost/dexdrip/utilitymodels/Intents.java +++ b/app/src/main/java/com/eveningoutpost/dexdrip/utilitymodels/Intents.java @@ -12,6 +12,7 @@ public interface Intents { String EXTRA_BG_SLOPE = "com.eveningoutpost.dexdrip.Extras.BgSlope"; String EXTRA_BG_SLOPE_NAME = "com.eveningoutpost.dexdrip.Extras.BgSlopeName"; String EXTRA_SENSOR_BATTERY = "com.eveningoutpost.dexdrip.Extras.SensorBattery"; + String EXTRA_SENSOR_STARTED_AT = "com.eveningoutpost.dexdrip.Extras.SensorStartedAt"; String EXTRA_TIMESTAMP = "com.eveningoutpost.dexdrip.Extras.Time"; String EXTRA_RAW = "com.eveningoutpost.dexdrip.Extras.Raw"; String EXTRA_NOISE = "com.eveningoutpost.dexdrip.Extras.Noise"; diff --git a/app/src/main/java/com/eveningoutpost/dexdrip/utils/Preferences.java b/app/src/main/java/com/eveningoutpost/dexdrip/utils/Preferences.java index 9499d389c3..93b3c1ce4d 100644 --- a/app/src/main/java/com/eveningoutpost/dexdrip/utils/Preferences.java +++ b/app/src/main/java/com/eveningoutpost/dexdrip/utils/Preferences.java @@ -1352,17 +1352,18 @@ public boolean onPreferenceClick(Preference preference) { public void run() { try { String country = Pref.getString("clfollow_country", "").toLowerCase(); - if (country.equals("")) - JoH.static_toast(preference.getContext(), "Country is required!", Toast.LENGTH_LONG); - else { + if (country.equals("")) { + JoH.static_toast(preference.getContext(), xdrip.gs(R.string.carelink_auth_country_required), Toast.LENGTH_LONG); + } else { CareLinkAuthenticator authenticator = new CareLinkAuthenticator(country, CareLinkCredentialStore.getInstance()); if (authenticator.authenticate(getActivity(), CareLinkAuthType.MobileApp)) { - JoH.static_toast(preference.getContext(), "Login completed!", Toast.LENGTH_LONG); + JoH.static_toast(preference.getContext(), xdrip.gs(R.string.carelink_auth_status_authenticated), Toast.LENGTH_LONG); CareLinkFollowService.resetInstanceAndInvalidateSession(); CollectionServiceStarter.restartCollectionServiceBackground(); } - else - JoH.static_toast(preference.getContext(), "Login failed!", Toast.LENGTH_LONG); + else { + JoH.static_toast(preference.getContext(), xdrip.gs(R.string.carelink_auth_status_not_authenticated), Toast.LENGTH_LONG); + } } } catch (InterruptedException e) { diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index d03343b5cc..771db17d39 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1849,4 +1849,15 @@ Send and receive data from Google Health Connect and Google Fit Google Health Connect ERROR: Health connect needs permissions! - try from settings menu again + Country is required! + Authenticated status! + Not authenticated status! + Login in progress... + Start access renewal + Access renewal failed! Will try again! + Start download + Download data failed! + Not logged in! Please log in! + Access expired! Will refresh! + Login expired! Please log in!