Merge pull request #561 from estevez-dev/actionable_notifications
Actionable notifications
This commit is contained in:
		| @@ -79,6 +79,8 @@ flutter { | |||||||
|  |  | ||||||
| dependencies { | dependencies { | ||||||
|     implementation 'com.google.firebase:firebase-analytics:17.2.2' |     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' |     testImplementation 'junit:junit:4.12' | ||||||
|     androidTestImplementation 'com.android.support.test:runner:1.0.2' |     androidTestImplementation 'com.android.support.test:runner:1.0.2' | ||||||
|     androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' |     androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' | ||||||
|   | |||||||
| @@ -43,16 +43,26 @@ | |||||||
|             <meta-data |             <meta-data | ||||||
|                 android:name="io.flutter.embedding.android.NormalTheme" |                 android:name="io.flutter.embedding.android.NormalTheme" | ||||||
|                 android:resource="@style/NormalTheme" /> |                 android:resource="@style/NormalTheme" /> | ||||||
|             <intent-filter> |  | ||||||
|                 <action android:name="FLUTTER_NOTIFICATION_CLICK" /> |  | ||||||
|                 <category android:name="android.intent.category.DEFAULT" /> |  | ||||||
|             </intent-filter> |  | ||||||
|             <intent-filter> |             <intent-filter> | ||||||
|                 <action android:name="android.intent.action.MAIN"/> |                 <action android:name="android.intent.action.MAIN"/> | ||||||
|                 <category android:name="android.intent.category.LAUNCHER"/> |                 <category android:name="android.intent.category.LAUNCHER"/> | ||||||
|             </intent-filter> |             </intent-filter> | ||||||
|         </activity> |         </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 |         <service | ||||||
|             android:name="io.flutter.plugins.androidalarmmanager.AlarmService" |             android:name="io.flutter.plugins.androidalarmmanager.AlarmService" | ||||||
|             android:permission="android.permission.BIND_JOB_SERVICE" |             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.embedding.engine.FlutterEngine; | ||||||
| import io.flutter.plugins.GeneratedPluginRegistrant; | 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 { | public class MainActivity extends FlutterActivity { | ||||||
|    |    | ||||||
|     @Override |     @Override | ||||||
| @@ -12,4 +24,22 @@ public class MainActivity extends FlutterActivity { | |||||||
|         GeneratedPluginRegistrant.registerWith(flutterEngine); |         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; |   Map services; | ||||||
|   bool autoUi = false; |   bool autoUi = false; | ||||||
|  |  | ||||||
|   String fcmToken; |  | ||||||
|  |  | ||||||
|   Map _rawLovelaceData; |   Map _rawLovelaceData; | ||||||
|   var _rawStates; |   var _rawStates; | ||||||
|   var _rawUserInfo; |   var _rawUserInfo; | ||||||
|   | |||||||
| @@ -16,10 +16,10 @@ import 'package:http/http.dart' as http; | |||||||
| import 'package:charts_flutter/flutter.dart' as charts; | import 'package:charts_flutter/flutter.dart' as charts; | ||||||
| import 'package:flutter_markdown/flutter_markdown.dart'; | import 'package:flutter_markdown/flutter_markdown.dart'; | ||||||
| import 'package:flutter_custom_tabs/flutter_custom_tabs.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:flutter_secure_storage/flutter_secure_storage.dart'; | ||||||
| import 'package:device_info/device_info.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 'package:in_app_purchase/in_app_purchase.dart'; | ||||||
| import 'plugins/dynamic_multi_column_layout.dart'; | import 'plugins/dynamic_multi_column_layout.dart'; | ||||||
| import 'plugins/spoiler_card.dart'; | import 'plugins/spoiler_card.dart'; | ||||||
| @@ -157,8 +157,8 @@ part 'cards/badges.dart'; | |||||||
| part 'managers/app_settings.dart'; | part 'managers/app_settings.dart'; | ||||||
|  |  | ||||||
| EventBus eventBus = new EventBus(); | EventBus eventBus = new EventBus(); | ||||||
| final FirebaseMessaging _firebaseMessaging = FirebaseMessaging(); | //final FirebaseMessaging _firebaseMessaging = FirebaseMessaging(); | ||||||
| FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin = new FlutterLocalNotificationsPlugin(); | //FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin = new FlutterLocalNotificationsPlugin(); | ||||||
| const String appName = 'HA Client'; | const String appName = 'HA Client'; | ||||||
| const String appVersion = String.fromEnvironment('versionName', defaultValue: '0.0.0'); | const String appVersion = String.fromEnvironment('versionName', defaultValue: '0.0.0'); | ||||||
| const whatsNewUrl = 'http://ha-client.app/service/whats_new_1.1.0.md'; | const whatsNewUrl = 'http://ha-client.app/service/whats_new_1.1.0.md'; | ||||||
|   | |||||||
| @@ -20,6 +20,7 @@ class AppSettings { | |||||||
|   String tempToken; |   String tempToken; | ||||||
|   String oauthUrl; |   String oauthUrl; | ||||||
|   String webhookId; |   String webhookId; | ||||||
|  |   String fcmToken; | ||||||
|   double haVersion; |   double haVersion; | ||||||
|   bool scrollBadges; |   bool scrollBadges; | ||||||
|   int appIntegrationVersion; |   int appIntegrationVersion; | ||||||
| @@ -40,6 +41,7 @@ class AppSettings { | |||||||
|     if (full) { |     if (full) { | ||||||
|       Logger.d('Loading settings...'); |       Logger.d('Loading settings...'); | ||||||
|       SharedPreferences prefs = await SharedPreferences.getInstance(); |       SharedPreferences prefs = await SharedPreferences.getInstance(); | ||||||
|  |       fcmToken = prefs.getString('fcm-token'); | ||||||
|       _domain = prefs.getString('hassio-domain'); |       _domain = prefs.getString('hassio-domain'); | ||||||
|       _port = prefs.getString('hassio-port'); |       _port = prefs.getString('hassio-port'); | ||||||
|       webhookId = prefs.getString('app-webhook-id'); |       webhookId = prefs.getString('app-webhook-id'); | ||||||
|   | |||||||
| @@ -12,7 +12,7 @@ class MobileAppIntegrationManager { | |||||||
|     "os_version": DeviceInfoManager().osVersion, |     "os_version": DeviceInfoManager().osVersion, | ||||||
|     "app_data": { |     "app_data": { | ||||||
|       "push_token": "", |       "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() { |   static Future checkAppRegistration() { | ||||||
|     Completer completer = Completer(); |     Completer completer = Completer(); | ||||||
|     _appRegistrationData["device_name"] = AppSettings().mobileAppDeviceName ?? getDefaultDeviceName(); |     _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) { |     if (AppSettings().webhookId == null) { | ||||||
|       Logger.d("Mobile app was not registered yet. Registering..."); |       Logger.d("Mobile app was not registered yet. Registering..."); | ||||||
|       var registrationData = Map.from(_appRegistrationData); |       var registrationData = Map.from(_appRegistrationData); | ||||||
|   | |||||||
| @@ -33,35 +33,8 @@ class _MainPageState extends State<MainPage> with WidgetsBindingObserver, Ticker | |||||||
|     super.initState(); |     super.initState(); | ||||||
|     WidgetsBinding.instance.addObserver(this); |     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(); |     _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) { |     _settingsSubscription = eventBus.on<SettingsChangedEvent>().listen((event) { | ||||||
|       Logger.d("Settings change event: reconnect=${event.reconnect}"); |       Logger.d("Settings change event: reconnect=${event.reconnect}"); | ||||||
|       if (event.reconnect) { |       if (event.reconnect) { | ||||||
| @@ -73,31 +46,13 @@ class _MainPageState extends State<MainPage> with WidgetsBindingObserver, Ticker | |||||||
|     _fullLoad(); |     _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() { |   void _fullLoad() { | ||||||
|     _bottomInfoBarController.showInfoBottomBar(progress: true,); |     _bottomInfoBarController.showInfoBottomBar(progress: true,); | ||||||
|  |     Logger.d('[loading] fullLoad'); | ||||||
|     _subscribe().then((_) { |     _subscribe().then((_) { | ||||||
|  |       Logger.d('[loading] subscribed'); | ||||||
|       ConnectionManager().init(loadSettings: true, forceReconnect: true).then((__){ |       ConnectionManager().init(loadSettings: true, forceReconnect: true).then((__){ | ||||||
|  |         Logger.d('[loading] COnnection manager initialized'); | ||||||
|         SharedPreferences.getInstance().then((prefs) { |         SharedPreferences.getInstance().then((prefs) { | ||||||
|           HomeAssistant().currentDashboardPath = prefs.getString('lovelace_dashboard_url') ?? HomeAssistant.DEFAULT_DASHBOARD; |           HomeAssistant().currentDashboardPath = prefs.getString('lovelace_dashboard_url') ?? HomeAssistant.DEFAULT_DASHBOARD; | ||||||
|           _fetchData(useCache: true); |           _fetchData(useCache: true); | ||||||
| @@ -155,9 +110,7 @@ class _MainPageState extends State<MainPage> with WidgetsBindingObserver, Ticker | |||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   Future _subscribe() { |   Future _subscribe() async { | ||||||
|     Completer completer = Completer(); |  | ||||||
|  |  | ||||||
|     if (_stateSubscription == null) { |     if (_stateSubscription == null) { | ||||||
|       _stateSubscription = eventBus.on<StateChangedEvent>().listen((event) { |       _stateSubscription = eventBus.on<StateChangedEvent>().listen((event) { | ||||||
|         if (event.needToRebuildUI) { |         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; |       HomeAssistant().fcmToken = token; | ||||||
|       completer.complete(); |       completer.complete(); | ||||||
|     }); |     });*/ | ||||||
|     return completer.future; |  | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   void _showOAuth() { |   void _showOAuth() { | ||||||
|   | |||||||
| @@ -23,10 +23,8 @@ dependencies: | |||||||
|   flutter_custom_tabs: ^0.6.0 |   flutter_custom_tabs: ^0.6.0 | ||||||
|   flutter_webview_plugin: ^0.3.10+1 |   flutter_webview_plugin: ^0.3.10+1 | ||||||
|   webview_flutter: ^0.3.19+7 |   webview_flutter: ^0.3.19+7 | ||||||
|   firebase_messaging: ^6.0.15 |  | ||||||
|   flutter_secure_storage: ^3.3.3 |   flutter_secure_storage: ^3.3.3 | ||||||
|   device_info: ^0.4.1+4 |   device_info: ^0.4.1+4 | ||||||
|   flutter_local_notifications: ^1.1.6 |  | ||||||
|   geolocator: ^5.3.1 |   geolocator: ^5.3.1 | ||||||
|   workmanager: ^0.2.2 |   workmanager: ^0.2.2 | ||||||
|   battery: ^1.0.0 |   battery: ^1.0.0 | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user