Merge pull request #561 from estevez-dev/actionable_notifications
Actionable notifications
This commit is contained in:
		| @@ -79,6 +79,8 @@ flutter { | ||||
|  | ||||
| dependencies { | ||||
|     implementation 'com.google.firebase:firebase-analytics:17.2.2' | ||||
|     implementation 'com.google.firebase:firebase-messaging:20.2.0' | ||||
|     implementation 'androidx.work:work-runtime:2.3.4' | ||||
|     testImplementation 'junit:junit:4.12' | ||||
|     androidTestImplementation 'com.android.support.test:runner:1.0.2' | ||||
|     androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' | ||||
|   | ||||
| @@ -43,16 +43,26 @@ | ||||
|             <meta-data | ||||
|                 android:name="io.flutter.embedding.android.NormalTheme" | ||||
|                 android:resource="@style/NormalTheme" /> | ||||
|             <intent-filter> | ||||
|                 <action android:name="FLUTTER_NOTIFICATION_CLICK" /> | ||||
|                 <category android:name="android.intent.category.DEFAULT" /> | ||||
|             </intent-filter> | ||||
|             <intent-filter> | ||||
|                 <action android:name="android.intent.action.MAIN"/> | ||||
|                 <category android:name="android.intent.category.LAUNCHER"/> | ||||
|             </intent-filter> | ||||
|         </activity> | ||||
|  | ||||
|         <service | ||||
|             android:name=".MessagingService" | ||||
|             android:exported="false"> | ||||
|             <intent-filter> | ||||
|                 <action android:name="com.google.firebase.MESSAGING_EVENT" /> | ||||
|             </intent-filter> | ||||
|         </service> | ||||
|         <receiver android:name=".NotificationActionReceiver"  android:exported="true"> | ||||
|             <intent-filter> | ||||
|                 <action android:name="android.intent.action.BOOT_COMPLETED"/> | ||||
|                 <action android:name="android.intent.action.INPUT_METHOD_CHANGED" /> | ||||
|             </intent-filter> | ||||
|         </receiver> | ||||
|      | ||||
|         <service | ||||
|             android:name="io.flutter.plugins.androidalarmmanager.AlarmService" | ||||
|             android:permission="android.permission.BIND_JOB_SERVICE" | ||||
|   | ||||
| @@ -5,6 +5,18 @@ import io.flutter.embedding.android.FlutterActivity; | ||||
| import io.flutter.embedding.engine.FlutterEngine; | ||||
| import io.flutter.plugins.GeneratedPluginRegistrant; | ||||
|  | ||||
| import android.content.Context; | ||||
|  | ||||
| import android.content.SharedPreferences; | ||||
| import android.content.SharedPreferences.Editor; | ||||
| import android.os.Bundle; | ||||
|  | ||||
| import com.google.android.gms.tasks.OnCompleteListener; | ||||
| import com.google.android.gms.tasks.Task; | ||||
| import com.google.firebase.iid.FirebaseInstanceId; | ||||
| import com.google.firebase.iid.InstanceIdResult; | ||||
| import com.google.firebase.messaging.FirebaseMessaging; | ||||
|  | ||||
| public class MainActivity extends FlutterActivity { | ||||
|    | ||||
|     @Override | ||||
| @@ -12,4 +24,22 @@ public class MainActivity extends FlutterActivity { | ||||
|         GeneratedPluginRegistrant.registerWith(flutterEngine); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     protected void onCreate(Bundle savedInstanceState) { | ||||
|         super.onCreate(savedInstanceState); | ||||
|         FirebaseInstanceId.getInstance().getInstanceId() | ||||
|             .addOnCompleteListener(new OnCompleteListener<InstanceIdResult>() { | ||||
|                 @Override | ||||
|                 public void onComplete(@NonNull Task<InstanceIdResult> 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.fcm-token", token); | ||||
|                         editor.commit(); | ||||
|                     } | ||||
|                 } | ||||
|             }); | ||||
|     } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -0,0 +1,131 @@ | ||||
| package com.keyboardcrumbs.hassclient; | ||||
|  | ||||
| import java.util.Map; | ||||
| import java.net.URL; | ||||
| import java.net.URLConnection; | ||||
| import java.io.IOException; | ||||
| import java.io.InputStream; | ||||
|  | ||||
| import android.app.NotificationChannel; | ||||
| import android.app.NotificationManager; | ||||
| import android.app.PendingIntent; | ||||
| import android.content.Context; | ||||
| import android.content.Intent; | ||||
| import android.media.RingtoneManager; | ||||
| import android.net.Uri; | ||||
| import android.os.Build; | ||||
| import androidx.core.app.NotificationCompat; | ||||
| import android.util.Log; | ||||
|  | ||||
| import com.google.firebase.messaging.FirebaseMessagingService; | ||||
| import com.google.firebase.messaging.RemoteMessage; | ||||
|  | ||||
| import android.graphics.Bitmap; | ||||
| import android.graphics.BitmapFactory; | ||||
| import android.webkit.URLUtil; | ||||
|  | ||||
|  | ||||
| public class MessagingService extends FirebaseMessagingService { | ||||
|  | ||||
|     private static final String TAG = "MessagingService"; | ||||
|  | ||||
|     @Override | ||||
|     public void onMessageReceived(RemoteMessage remoteMessage) { | ||||
|         Log.d(TAG, "From: " + remoteMessage.getFrom()); | ||||
|         Map<String, String> data = remoteMessage.getData(); | ||||
|         if (data.size() > 0) { | ||||
|            Log.d(TAG, "Message data payload: " + data); | ||||
|            if (data.containsKey("body") || data.containsKey("title")) { | ||||
|                 sendNotification(data); | ||||
|            } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void onNewToken(String token) { | ||||
|         Log.d(TAG, "Refreshed token: " + token); | ||||
|         //TODO update token | ||||
|     } | ||||
|  | ||||
|     private void sendNotification(Map<String, String> data) { | ||||
|         String channelId, messageBody, messageTitle, imageUrl; | ||||
|         String nTag; | ||||
|         if (!data.containsKey("channelId")) { | ||||
|             channelId = "ha_notify"; | ||||
|         } else { | ||||
|             channelId = data.get("channelId"); | ||||
|         } | ||||
|         if (!data.containsKey("body")) { | ||||
|             messageBody = ""; | ||||
|         } else { | ||||
|             messageBody = data.get("body"); | ||||
|         } | ||||
|         if (!data.containsKey("title")) { | ||||
|             messageTitle = "HA Client"; | ||||
|         } else { | ||||
|             messageTitle = data.get("title"); | ||||
|         } | ||||
|         if (!data.containsKey("tag")) { | ||||
|             nTag = String.valueOf(System.currentTimeMillis()); | ||||
|         } else { | ||||
|             nTag = data.get("tag"); | ||||
|         } | ||||
|         Log.d(TAG, "Notification tag: " + nTag); | ||||
|         imageUrl = data.get("image"); | ||||
|         Intent intent = new Intent(this, MainActivity.class); | ||||
|         intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); | ||||
|         PendingIntent pendingIntent = PendingIntent.getActivity(this, 0 /* Request code */, intent, | ||||
|                 PendingIntent.FLAG_ONE_SHOT); | ||||
|         Uri defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION); | ||||
|         NotificationCompat.Builder notificationBuilder = | ||||
|                 new NotificationCompat.Builder(this, channelId) | ||||
|                         .setSmallIcon(R.drawable.mini_icon) | ||||
|                         .setContentTitle(messageTitle) | ||||
|                         .setContentText(messageBody) | ||||
|                         .setAutoCancel(true) | ||||
|                         .setSound(defaultSoundUri) | ||||
|                         .setContentIntent(pendingIntent); | ||||
|         if (URLUtil.isValidUrl(imageUrl)) { | ||||
|             Bitmap image = getBitmapFromURL(imageUrl); | ||||
|             if (image != null) { | ||||
|                 notificationBuilder.setStyle(new NotificationCompat.BigPictureStyle().bigPicture(image).bigLargeIcon(BitmapFactory.decodeResource(getResources(), R.drawable.blank_icon))); | ||||
|                 notificationBuilder.setLargeIcon(image); | ||||
|             } | ||||
|         } | ||||
|         for (int i = 1; i <= 3; i++) { | ||||
|             if (data.containsKey("action" + i)) { | ||||
|                 Intent broadcastIntent = new Intent(this, NotificationActionReceiver.class); | ||||
|                 Log.d(TAG, "Putting a tag to the action: " + nTag); | ||||
|                 broadcastIntent.putExtra("tag", nTag); | ||||
|                 broadcastIntent.putExtra("actionData", data.get("action" + i + "_data")); | ||||
|                 PendingIntent actionIntent = PendingIntent.getBroadcast(this, i, broadcastIntent, 0); | ||||
|                 notificationBuilder.addAction(R.drawable.mini_icon, data.get("action" + i), actionIntent); | ||||
|             }    | ||||
|         } | ||||
|         NotificationManager notificationManager = | ||||
|                 (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); | ||||
|  | ||||
|         // Since android Oreo notification channel is needed. | ||||
|         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { | ||||
|             NotificationChannel channel = new NotificationChannel(channelId, | ||||
|                     "Home Assistant notifications", | ||||
|                     NotificationManager.IMPORTANCE_DEFAULT); | ||||
|             notificationManager.createNotificationChannel(channel); | ||||
|         } | ||||
|  | ||||
|         notificationManager.notify(nTag, 0 /* ID of notification */, notificationBuilder.build()); | ||||
|     } | ||||
|  | ||||
|     private Bitmap getBitmapFromURL(String imageUrl) { | ||||
|         try { | ||||
|             URL url = new URL(imageUrl); | ||||
|             URLConnection connection = url.openConnection(); | ||||
|             connection.setDoInput(true); | ||||
|             connection.connect(); | ||||
|             InputStream input = connection.getInputStream(); | ||||
|             return BitmapFactory.decodeStream(input); | ||||
|         } catch (IOException e) { | ||||
|             return null; | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,69 @@ | ||||
| package com.keyboardcrumbs.hassclient; | ||||
|  | ||||
| import android.content.Context; | ||||
| import androidx.annotation.NonNull; | ||||
| import android.util.Log; | ||||
| import android.content.BroadcastReceiver; | ||||
| import android.content.Intent; | ||||
|  | ||||
| import android.app.NotificationManager; | ||||
|  | ||||
| import android.webkit.URLUtil; | ||||
|  | ||||
| import org.json.JSONObject; | ||||
| import android.content.SharedPreferences; | ||||
|  | ||||
| public class NotificationActionReceiver extends BroadcastReceiver { | ||||
|  | ||||
|     private static final String TAG = "NotificationActionReceiver"; | ||||
|  | ||||
|     @Override | ||||
|     public void onReceive(Context context, Intent intent) { | ||||
|         String rawActionData = intent.getStringExtra("actionData"); | ||||
|         String notificationTag = intent.getStringExtra("tag"); | ||||
|         Log.d(TAG, "Has 'tag': " + intent.hasExtra("tag")); | ||||
|         Log.d(TAG, "Canceling notification by tag: " + notificationTag); | ||||
|         NotificationManager notificationManager = (NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE); | ||||
|         notificationManager.cancel(notificationTag, 0); | ||||
|         SharedPreferences prefs = context.getSharedPreferences("FlutterSharedPreferences", Context.MODE_PRIVATE); | ||||
|         String webhookId = prefs.getString("flutter.app-webhook-id", null); | ||||
|         if (webhookId != null) { | ||||
|             try { | ||||
|                 Log.d(TAG, "Got webhook id"); | ||||
|                 String requestUrl = prefs.getString("flutter.hassio-res-protocol", "") + | ||||
|                     "://" + | ||||
|                     prefs.getString("flutter.hassio-domain", "") + | ||||
|                     ":" + | ||||
|                     prefs.getString("flutter.hassio-port", "") + "/api/webhook/" + webhookId; | ||||
|                 JSONObject actionData = new JSONObject(rawActionData); | ||||
|                 Log.d(TAG, "request url: " + requestUrl); | ||||
|                 if (URLUtil.isValidUrl(requestUrl)) { | ||||
|                     JSONObject dataToSend = new JSONObject(); | ||||
|                     JSONObject requestData = new JSONObject(); | ||||
|                     if (actionData.getString("action").equals("call-service")) { | ||||
|                         dataToSend.put("type", "call_service"); | ||||
|                         requestData.put("domain", actionData.getString("service").split("\\.")[0]); | ||||
|                         requestData.put("service", actionData.getString("service").split("\\.")[1]); | ||||
|                         if (actionData.has("service_data")) { | ||||
|                             requestData.put("service_data", actionData.get("service_data")); | ||||
|                         } | ||||
|                     } else { | ||||
|                         dataToSend.put("type", "fire_event"); | ||||
|                         requestData.put("event_type", "ha_client_event"); | ||||
|                     } | ||||
|                     dataToSend.put("data", requestData); | ||||
|                     String stringRequest = dataToSend.toString(); | ||||
|                     Log.d(TAG, "Data to send home: " + stringRequest); | ||||
|                     SendTask sendTask = new SendTask(); | ||||
|                     sendTask.execute(requestUrl, stringRequest); | ||||
|                 } else { | ||||
|                     Log.w(TAG, "Invalid url"); | ||||
|                 } | ||||
|             } catch (Exception e) { | ||||
|                 Log.e(TAG, "Error handling notification action", e);     | ||||
|             } | ||||
|         } else { | ||||
|             Log.d(TAG, "Webhook id not found"); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,48 @@ | ||||
| package com.keyboardcrumbs.hassclient; | ||||
|  | ||||
| import android.util.Log; | ||||
| import android.os.AsyncTask; | ||||
|  | ||||
| import java.net.URL; | ||||
| import java.net.HttpURLConnection; | ||||
| import java.io.OutputStream; | ||||
|  | ||||
| public class SendTask extends AsyncTask<String, String, String> { | ||||
|  | ||||
|     private static final String TAG = "SendTask"; | ||||
|  | ||||
|     public SendTask(){ | ||||
|         //set context variables if required | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     protected void onPreExecute() { | ||||
|         super.onPreExecute(); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     protected String doInBackground(String... params) { | ||||
|         String urlString = params[0]; | ||||
|         String data = params[1]; | ||||
|  | ||||
|         try { | ||||
|             Log.d(TAG, "Connecting and sending..."); | ||||
|             URL url = new URL(urlString); | ||||
|             HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection(); | ||||
|             urlConnection.setRequestMethod("POST"); | ||||
|             urlConnection.setRequestProperty("Content-Type", "application/json"); | ||||
|             urlConnection.setDoOutput(true); | ||||
|             byte[] outputBytes = data.getBytes("UTF-8"); | ||||
|             OutputStream os = urlConnection.getOutputStream(); | ||||
|             os.write(outputBytes); | ||||
|  | ||||
|             int responseCode = urlConnection.getResponseCode(); | ||||
|  | ||||
|             Log.d(TAG, "responseCode: " + responseCode); | ||||
|             urlConnection.disconnect(); | ||||
|         } catch (Exception e) { | ||||
|             Log.e(TAG, "Error sending data", e);  | ||||
|         } | ||||
|         return null; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										
											BIN
										
									
								
								android/app/src/main/res/drawable/blank_icon.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								android/app/src/main/res/drawable/blank_icon.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 461 B | 
| @@ -22,8 +22,6 @@ class HomeAssistant { | ||||
|   Map services; | ||||
|   bool autoUi = false; | ||||
|  | ||||
|   String fcmToken; | ||||
|  | ||||
|   Map _rawLovelaceData; | ||||
|   var _rawStates; | ||||
|   var _rawUserInfo; | ||||
|   | ||||
| @@ -16,10 +16,10 @@ import 'package:http/http.dart' as http; | ||||
| import 'package:charts_flutter/flutter.dart' as charts; | ||||
| import 'package:flutter_markdown/flutter_markdown.dart'; | ||||
| import 'package:flutter_custom_tabs/flutter_custom_tabs.dart'; | ||||
| import 'package:firebase_messaging/firebase_messaging.dart'; | ||||
| //import 'package:firebase_messaging/firebase_messaging.dart'; | ||||
| import 'package:flutter_secure_storage/flutter_secure_storage.dart'; | ||||
| import 'package:device_info/device_info.dart'; | ||||
| import 'package:flutter_local_notifications/flutter_local_notifications.dart'; | ||||
| //import 'package:flutter_local_notifications/flutter_local_notifications.dart'; | ||||
| import 'package:in_app_purchase/in_app_purchase.dart'; | ||||
| import 'plugins/dynamic_multi_column_layout.dart'; | ||||
| import 'plugins/spoiler_card.dart'; | ||||
| @@ -157,8 +157,8 @@ part 'cards/badges.dart'; | ||||
| part 'managers/app_settings.dart'; | ||||
|  | ||||
| EventBus eventBus = new EventBus(); | ||||
| final FirebaseMessaging _firebaseMessaging = FirebaseMessaging(); | ||||
| FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin = new FlutterLocalNotificationsPlugin(); | ||||
| //final FirebaseMessaging _firebaseMessaging = FirebaseMessaging(); | ||||
| //FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin = new FlutterLocalNotificationsPlugin(); | ||||
| const String appName = 'HA Client'; | ||||
| const String appVersion = String.fromEnvironment('versionName', defaultValue: '0.0.0'); | ||||
| const whatsNewUrl = 'http://ha-client.app/service/whats_new_1.1.0.md'; | ||||
|   | ||||
| @@ -20,6 +20,7 @@ class AppSettings { | ||||
|   String tempToken; | ||||
|   String oauthUrl; | ||||
|   String webhookId; | ||||
|   String fcmToken; | ||||
|   double haVersion; | ||||
|   bool scrollBadges; | ||||
|   int appIntegrationVersion; | ||||
| @@ -40,6 +41,7 @@ class AppSettings { | ||||
|     if (full) { | ||||
|       Logger.d('Loading settings...'); | ||||
|       SharedPreferences prefs = await SharedPreferences.getInstance(); | ||||
|       fcmToken = prefs.getString('fcm-token'); | ||||
|       _domain = prefs.getString('hassio-domain'); | ||||
|       _port = prefs.getString('hassio-port'); | ||||
|       webhookId = prefs.getString('app-webhook-id'); | ||||
|   | ||||
| @@ -12,7 +12,7 @@ class MobileAppIntegrationManager { | ||||
|     "os_version": DeviceInfoManager().osVersion, | ||||
|     "app_data": { | ||||
|       "push_token": "", | ||||
|       "push_url": "https://us-central1-ha-client-c73c4.cloudfunctions.net/pushNotifyV2" | ||||
|       "push_url": "https://us-central1-ha-client-c73c4.cloudfunctions.net/pushNotifyV3" | ||||
|     } | ||||
|   }; | ||||
|  | ||||
| @@ -26,7 +26,7 @@ class MobileAppIntegrationManager { | ||||
|   static Future checkAppRegistration() { | ||||
|     Completer completer = Completer(); | ||||
|     _appRegistrationData["device_name"] = AppSettings().mobileAppDeviceName ?? getDefaultDeviceName(); | ||||
|     (_appRegistrationData["app_data"] as Map)["push_token"] = "${HomeAssistant().fcmToken}"; | ||||
|     (_appRegistrationData["app_data"] as Map)["push_token"] = "${AppSettings().fcmToken}"; | ||||
|     if (AppSettings().webhookId == null) { | ||||
|       Logger.d("Mobile app was not registered yet. Registering..."); | ||||
|       var registrationData = Map.from(_appRegistrationData); | ||||
|   | ||||
| @@ -33,35 +33,8 @@ class _MainPageState extends State<MainPage> with WidgetsBindingObserver, Ticker | ||||
|     super.initState(); | ||||
|     WidgetsBinding.instance.addObserver(this); | ||||
|  | ||||
|     _firebaseMessaging.configure( | ||||
|         onLaunch: (data) { | ||||
|           Logger.d("Notification [onLaunch]: $data"); | ||||
|           return Future.value(); | ||||
|         }, | ||||
|         onMessage: (data) { | ||||
|           Logger.d("Notification [onMessage]: $data"); | ||||
|           return _showNotification(title: data["notification"]["title"], text: data["notification"]["body"]); | ||||
|         }, | ||||
|         onResume: (data) { | ||||
|           Logger.d("Notification [onResume]: $data"); | ||||
|           return Future.value(); | ||||
|         } | ||||
|     ); | ||||
|  | ||||
|     _bottomInfoBarController = BottomInfoBarController(); | ||||
|  | ||||
|     _firebaseMessaging.requestNotificationPermissions(const IosNotificationSettings(sound: true, badge: true, alert: true)); | ||||
|  | ||||
|     // initialise the plugin. app_icon needs to be a added as a drawable resource to the Android head project | ||||
|     var initializationSettingsAndroid = | ||||
|     new AndroidInitializationSettings('mini_icon'); | ||||
|     var initializationSettingsIOS = new IOSInitializationSettings( | ||||
|         onDidReceiveLocalNotification: null); | ||||
|     var initializationSettings = new InitializationSettings( | ||||
|         initializationSettingsAndroid, initializationSettingsIOS); | ||||
|     flutterLocalNotificationsPlugin.initialize(initializationSettings, | ||||
|         onSelectNotification: onSelectNotification); | ||||
|  | ||||
|     _settingsSubscription = eventBus.on<SettingsChangedEvent>().listen((event) { | ||||
|       Logger.d("Settings change event: reconnect=${event.reconnect}"); | ||||
|       if (event.reconnect) { | ||||
| @@ -73,31 +46,13 @@ class _MainPageState extends State<MainPage> with WidgetsBindingObserver, Ticker | ||||
|     _fullLoad(); | ||||
|   } | ||||
|  | ||||
|   Future onSelectNotification(String payload) async { | ||||
|     if (payload != null) { | ||||
|       Logger.d('Notification clicked: ' + payload); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   Future _showNotification({String title, String text}) async { | ||||
|     var androidPlatformChannelSpecifics = new AndroidNotificationDetails( | ||||
|         'ha_notify', 'Home Assistant notifications', 'Notifications from Home Assistant notify service', | ||||
|         importance: Importance.Max, priority: Priority.High); | ||||
|     var iOSPlatformChannelSpecifics = new IOSNotificationDetails(); | ||||
|     var platformChannelSpecifics = new NotificationDetails( | ||||
|         androidPlatformChannelSpecifics, iOSPlatformChannelSpecifics); | ||||
|     await flutterLocalNotificationsPlugin.show( | ||||
|         0, | ||||
|         title ?? appName, | ||||
|         text, | ||||
|         platformChannelSpecifics | ||||
|     ); | ||||
|   } | ||||
|  | ||||
|   void _fullLoad() { | ||||
|     _bottomInfoBarController.showInfoBottomBar(progress: true,); | ||||
|     Logger.d('[loading] fullLoad'); | ||||
|     _subscribe().then((_) { | ||||
|       Logger.d('[loading] subscribed'); | ||||
|       ConnectionManager().init(loadSettings: true, forceReconnect: true).then((__){ | ||||
|         Logger.d('[loading] COnnection manager initialized'); | ||||
|         SharedPreferences.getInstance().then((prefs) { | ||||
|           HomeAssistant().currentDashboardPath = prefs.getString('lovelace_dashboard_url') ?? HomeAssistant.DEFAULT_DASHBOARD; | ||||
|           _fetchData(useCache: true); | ||||
| @@ -155,9 +110,7 @@ class _MainPageState extends State<MainPage> with WidgetsBindingObserver, Ticker | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   Future _subscribe() { | ||||
|     Completer completer = Completer(); | ||||
|  | ||||
|   Future _subscribe() async { | ||||
|     if (_stateSubscription == null) { | ||||
|       _stateSubscription = eventBus.on<StateChangedEvent>().listen((event) { | ||||
|         if (event.needToRebuildUI) { | ||||
| @@ -238,11 +191,10 @@ class _MainPageState extends State<MainPage> with WidgetsBindingObserver, Ticker | ||||
|       }); | ||||
|     } | ||||
|  | ||||
|     _firebaseMessaging.getToken().then((String token) { | ||||
|     /*_firebaseMessaging.getToken().then((String token) { | ||||
|       HomeAssistant().fcmToken = token; | ||||
|       completer.complete(); | ||||
|     }); | ||||
|     return completer.future; | ||||
|     });*/ | ||||
|   } | ||||
|  | ||||
|   void _showOAuth() { | ||||
|   | ||||
| @@ -23,10 +23,8 @@ dependencies: | ||||
|   flutter_custom_tabs: ^0.6.0 | ||||
|   flutter_webview_plugin: ^0.3.10+1 | ||||
|   webview_flutter: ^0.3.19+7 | ||||
|   firebase_messaging: ^6.0.15 | ||||
|   flutter_secure_storage: ^3.3.3 | ||||
|   device_info: ^0.4.1+4 | ||||
|   flutter_local_notifications: ^1.1.6 | ||||
|   geolocator: ^5.3.1 | ||||
|   workmanager: ^0.2.2 | ||||
|   battery: ^1.0.0 | ||||
|   | ||||
		Reference in New Issue
	
	Block a user