From 80b5763530f3206ceda99785ba40af712c0e3402 Mon Sep 17 00:00:00 2001 From: Yegor Vialov Date: Mon, 25 May 2020 14:09:45 +0000 Subject: [PATCH] FCM token update and waiting --- .../hassclient/MainActivity.java | 5 +- .../hassclient/MessagingService.java | 3 +- .../hassclient/UpdateTokenTask.java | 46 +++++ .../mobile_app_integration_manager.class.dart | 192 ++++++++++-------- 4 files changed, 156 insertions(+), 90 deletions(-) create mode 100644 android/app/src/main/java/com/keyboardcrumbs/hassclient/UpdateTokenTask.java diff --git a/android/app/src/main/java/com/keyboardcrumbs/hassclient/MainActivity.java b/android/app/src/main/java/com/keyboardcrumbs/hassclient/MainActivity.java index a187a8c..3952a1f 100644 --- a/android/app/src/main/java/com/keyboardcrumbs/hassclient/MainActivity.java +++ b/android/app/src/main/java/com/keyboardcrumbs/hassclient/MainActivity.java @@ -33,10 +33,9 @@ public class MainActivity extends FlutterActivity { public void onComplete(@NonNull Task task) { if (task.isSuccessful()) { Context context = getActivity(); - SharedPreferences.Editor editor = context.getSharedPreferences("FlutterSharedPreferences", Context.MODE_PRIVATE).edit(); String token = task.getResult().getToken(); - editor.putString("flutter.push-token", token); - editor.commit(); + UpdateTokenTask updateTokenTask = new UpdateTokenTask(context); + updateTokenTask.execute(token); } } }); diff --git a/android/app/src/main/java/com/keyboardcrumbs/hassclient/MessagingService.java b/android/app/src/main/java/com/keyboardcrumbs/hassclient/MessagingService.java index bcb5a83..0b7f1aa 100644 --- a/android/app/src/main/java/com/keyboardcrumbs/hassclient/MessagingService.java +++ b/android/app/src/main/java/com/keyboardcrumbs/hassclient/MessagingService.java @@ -40,7 +40,8 @@ public class MessagingService extends FirebaseMessagingService { @Override public void onNewToken(String token) { - //TODO update token + UpdateTokenTask updateTokenTask = new UpdateTokenTask(this); + updateTokenTask.execute(token); } private void sendNotification(Map data) { diff --git a/android/app/src/main/java/com/keyboardcrumbs/hassclient/UpdateTokenTask.java b/android/app/src/main/java/com/keyboardcrumbs/hassclient/UpdateTokenTask.java new file mode 100644 index 0000000..ff3c9a8 --- /dev/null +++ b/android/app/src/main/java/com/keyboardcrumbs/hassclient/UpdateTokenTask.java @@ -0,0 +1,46 @@ +package com.keyboardcrumbs.hassclient; + +import android.util.Log; +import android.os.AsyncTask; + +import java.net.URL; +import java.net.HttpURLConnection; +import java.io.OutputStream; + +import android.webkit.URLUtil; + +import org.json.JSONObject; +import android.content.SharedPreferences; +import android.content.Context; +import java.lang.ref.WeakReference; + + +public class UpdateTokenTask extends AsyncTask { + + private static final String TAG = "UpdateTokenTask"; + + private WeakReference contextRef; + + public UpdateTokenTask(Context context){ + contextRef = new WeakReference<>(context); + } + + @Override + protected void onPreExecute() { + super.onPreExecute(); + } + + @Override + protected String doInBackground(String... params) { + Log.d(TAG, "Updating push token"); + Context context = contextRef.get(); + if (context != null) { + String token = params[0]; + SharedPreferences prefs = context.getSharedPreferences("FlutterSharedPreferences", Context.MODE_PRIVATE); + SharedPreferences.Editor editor = prefs.edit(); + editor.putString("flutter.notification-token", token); + editor.commit(); + } + return null; + } +} \ No newline at end of file diff --git a/lib/managers/mobile_app_integration_manager.class.dart b/lib/managers/mobile_app_integration_manager.class.dart index 488a694..ad7fec2 100644 --- a/lib/managers/mobile_app_integration_manager.class.dart +++ b/lib/managers/mobile_app_integration_manager.class.dart @@ -21,97 +21,117 @@ class MobileAppIntegrationManager { return '${HomeAssistant().userName}\'s ${DeviceInfoManager().model}'; } - static Future checkAppRegistration() { + static Future checkAppRegistration() async { + int attempts = 1; + bool done = false; + Logger.d("[MobileAppIntegrationManager] Stratring mobile app integration check..."); + while (attempts <= 5 && !done) { + Logger.d("[MobileAppIntegrationManager] check attempt $attempts"); + String fcmToken = await AppSettings().loadSingle('notification-token'); + if (fcmToken != null) { + Logger.d("[MobileAppIntegrationManager] token exist"); + await _doCheck(fcmToken); + done = true; + } else { + Logger.d("[MobileAppIntegrationManager] no fcm token. Retry in 5 seconds"); + attempts++; + await Future.delayed(Duration(seconds: 5)); + } + } + if (!done) { + Logger.e("[MobileAppIntegrationManager] No FCM token"); + } + } + + static Future _doCheck(String fcmToken) { Completer completer = Completer(); _appRegistrationData["device_name"] = AppSettings().mobileAppDeviceName ?? getDefaultDeviceName(); - AppSettings().loadSingle('push-token').then((fcmToken) { - (_appRegistrationData["app_data"] as Map)["push_token"] = "$fcmToken"; - if (AppSettings().webhookId == null) { - Logger.d("Mobile app was not registered yet. Registering..."); - var registrationData = Map.from(_appRegistrationData); + (_appRegistrationData["app_data"] as Map)["push_token"] = "$fcmToken"; + if (AppSettings().webhookId == null) { + Logger.d("Mobile app was not registered yet. Registering..."); + var registrationData = Map.from(_appRegistrationData); + registrationData.addAll({ + "app_id": "ha_client", + "app_name": "$appName", + "os_name": DeviceInfoManager().osName, + "supports_encryption": false, + }); + if (AppSettings().haVersion >= 104) { registrationData.addAll({ - "app_id": "ha_client", - "app_name": "$appName", - "os_name": DeviceInfoManager().osName, - "supports_encryption": false, - }); - if (AppSettings().haVersion >= 104) { - registrationData.addAll({ - "device_id": "${DeviceInfoManager().unicDeviceId}" - }); - } - ConnectionManager().sendHTTPPost( - endPoint: "/api/mobile_app/registrations", - includeAuthHeader: true, - data: json.encode(registrationData) - ).then((response) { - Logger.d("Processing registration responce..."); - var responseObject = json.decode(response); - AppSettings().webhookId = responseObject["webhook_id"]; - AppSettings().save({ - 'app-webhook-id': responseObject["webhook_id"] - }).then((prefs) { - completer.complete(); - eventBus.fire(ShowPopupEvent( - popup: Popup( - title: "Mobile app Integration was created", - body: "HA Client was registered as MobileApp in your Home Assistant. To start using notifications you need to restart your Home Assistant", - positiveText: "Restart now", - negativeText: "Later", - onPositive: () { - ConnectionManager().callService(domain: "homeassistant", service: "restart"); - }, - ) - )); - }); - }).catchError((e) { - completer.complete(); - if (e is http.Response) { - Logger.e("Error registering the app: ${e.statusCode}: ${e.body}"); - } else { - Logger.e("Error registering the app: ${e?.toString()}"); - } - _showError(); - }); - } else { - Logger.d("App was previously registered. Checking..."); - var updateData = { - "type": "update_registration", - "data": _appRegistrationData - }; - ConnectionManager().sendHTTPPost( - endPoint: "/api/webhook/${AppSettings().webhookId}", - includeAuthHeader: false, - data: json.encode(updateData) - ).then((response) { - var registrationData; - try { - registrationData = json.decode(response); - } catch (e) { - registrationData = null; - } - if (registrationData == null || registrationData.isEmpty) { - Logger.w("No registration data in response. MobileApp integration was removed or broken"); - _askToRegisterApp(); - } else { - Logger.d('App registration works fine'); - } - completer.complete(); - }).catchError((e) { - if (e is http.Response && e.statusCode == 410) { - Logger.w("MobileApp integration was removed"); - _askToRegisterApp(); - } else if (e is http.Response) { - Logger.w("Error updating app registration: ${e.statusCode}: ${e.body}"); - _showError(); - } else { - Logger.w("Error updating app registration: ${e?.toString()}"); - _showError(); - } - completer.complete(); + "device_id": "${DeviceInfoManager().unicDeviceId}" }); } - }); + ConnectionManager().sendHTTPPost( + endPoint: "/api/mobile_app/registrations", + includeAuthHeader: true, + data: json.encode(registrationData) + ).then((response) { + Logger.d("Processing registration responce..."); + var responseObject = json.decode(response); + AppSettings().webhookId = responseObject["webhook_id"]; + AppSettings().save({ + 'app-webhook-id': responseObject["webhook_id"] + }).then((prefs) { + completer.complete(); + eventBus.fire(ShowPopupEvent( + popup: Popup( + title: "Mobile app Integration was created", + body: "HA Client was registered as MobileApp in your Home Assistant. To start using notifications you need to restart your Home Assistant", + positiveText: "Restart now", + negativeText: "Later", + onPositive: () { + ConnectionManager().callService(domain: "homeassistant", service: "restart"); + }, + ) + )); + }); + }).catchError((e) { + completer.complete(); + if (e is http.Response) { + Logger.e("Error registering the app: ${e.statusCode}: ${e.body}"); + } else { + Logger.e("Error registering the app: ${e?.toString()}"); + } + _showError(); + }); + } else { + Logger.d("App was previously registered. Checking..."); + var updateData = { + "type": "update_registration", + "data": _appRegistrationData + }; + ConnectionManager().sendHTTPPost( + endPoint: "/api/webhook/${AppSettings().webhookId}", + includeAuthHeader: false, + data: json.encode(updateData) + ).then((response) { + var registrationData; + try { + registrationData = json.decode(response); + } catch (e) { + registrationData = null; + } + if (registrationData == null || registrationData.isEmpty) { + Logger.w("No registration data in response. MobileApp integration was removed or broken"); + _askToRegisterApp(); + } else { + Logger.d('App registration works fine'); + } + completer.complete(); + }).catchError((e) { + if (e is http.Response && e.statusCode == 410) { + Logger.w("MobileApp integration was removed"); + _askToRegisterApp(); + } else if (e is http.Response) { + Logger.w("Error updating app registration: ${e.statusCode}: ${e.body}"); + _showError(); + } else { + Logger.w("Error updating app registration: ${e?.toString()}"); + _showError(); + } + completer.complete(); + }); + } return completer.future; }