Experimental support for background notifications

This commit is contained in:
Christian Pauly 2020-05-05 12:51:38 +02:00
parent 481dfeaf75
commit 6f281bc0cd
7 changed files with 209 additions and 109 deletions

View file

@ -95,6 +95,7 @@ flutter {
dependencies { dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation 'com.google.firebase:firebase-messaging:20.1.6'
testImplementation 'junit:junit:4.12' testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test:runner:1.1.1' androidTestImplementation 'androidx.test:runner:1.1.1'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1' androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1'

View file

@ -11,7 +11,7 @@
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<application <application
android:name="io.flutter.app.FlutterApplication" android:name=".Application"
android:label="FluffyChat" android:label="FluffyChat"
android:icon="@mipmap/launcher_icon"> android:icon="@mipmap/launcher_icon">
<activity <activity

View file

@ -0,0 +1,31 @@
package chat.fluffy.fluffychat
import io.flutter.app.FlutterApplication
import io.flutter.plugin.common.PluginRegistry
import io.flutter.plugin.common.PluginRegistry.PluginRegistrantCallback
import io.flutter.plugins.firebasemessaging.FirebaseMessagingPlugin
import io.flutter.view.FlutterMain
import io.flutter.plugins.firebasemessaging.FlutterFirebaseMessagingService
import com.dexterous.flutterlocalnotifications.FlutterLocalNotificationsPlugin
import com.tekartik.sqflite.SqflitePlugin
import com.it_nomads.fluttersecurestorage.FlutterSecureStoragePlugin
import io.flutter.plugins.pathprovider.PathProviderPlugin
class Application : FlutterApplication(), PluginRegistrantCallback {
override fun onCreate() {
super.onCreate()
FlutterFirebaseMessagingService.setPluginRegistrant(this);
FlutterMain.startInitialization(this)
}
override fun registerWith(registry: PluginRegistry?) {
if (!registry!!.hasPlugin("io.flutter.plugins.firebasemessaging")) {
FirebaseMessagingPlugin.registerWith(registry!!.registrarFor("io.flutter.plugins.firebasemessaging.FirebaseMessagingPlugin"));
FlutterLocalNotificationsPlugin.registerWith(registry.registrarFor("com.dexterous.flutterlocalnotifications.FlutterLocalNotificationsPlugin"));
SqflitePlugin.registerWith(registry.registrarFor("com.tekartik.sqflite.SqflitePlugin"));
PathProviderPlugin.registerWith(registry.registrarFor("io.flutter.plugins.pathprovider.PathProviderPlugin"));
FlutterSecureStoragePlugin.registerWith(registry.registrarFor("com.it_nomads.fluttersecurestorage"));
}
}
}

View file

@ -36,6 +36,7 @@ class I18n {
} }
static I18n of(BuildContext context) { static I18n of(BuildContext context) {
if (context == null) return I18n('en');
return Localizations.of<I18n>(context, I18n); return Localizations.of<I18n>(context, I18n);
} }

View file

@ -14,6 +14,7 @@ import 'package:path_provider/path_provider.dart';
import 'package:famedlysdk/famedlysdk.dart'; import 'package:famedlysdk/famedlysdk.dart';
import '../utils/event_extension.dart'; import '../utils/event_extension.dart';
import '../utils/room_extension.dart'; import '../utils/room_extension.dart';
import 'famedlysdk_store.dart';
abstract class FirebaseController { abstract class FirebaseController {
static FirebaseMessaging _firebaseMessaging = FirebaseMessaging(); static FirebaseMessaging _firebaseMessaging = FirebaseMessaging();
@ -40,7 +41,7 @@ abstract class FirebaseController {
await client.setPushers( await client.setPushers(
token, token,
"http", "http",
"chat.fluffy.fluffychat", "chat.fluffy.fluffychat.data",
clientName, clientName,
client.deviceName, client.deviceName,
"en", "en",
@ -83,9 +84,17 @@ abstract class FirebaseController {
onSelectNotification: goToRoom); onSelectNotification: goToRoom);
_firebaseMessaging.configure( _firebaseMessaging.configure(
onMessage: (Map<String, dynamic> message) async { onMessage: _onMessage,
onBackgroundMessage: _onMessage,
onResume: goToRoom,
onLaunch: goToRoom,
);
debugPrint("[Push] Firebase initialized");
return;
}
static Future<dynamic> _onMessage(Map<String, dynamic> message) async {
try { try {
print(message);
final data = message['data'] ?? message; final data = message['data'] ?? message;
final String roomId = data["room_id"]; final String roomId = data["room_id"];
final String eventId = data["event_id"]; final String eventId = data["event_id"];
@ -96,9 +105,30 @@ abstract class FirebaseController {
await _flutterLocalNotificationsPlugin.cancelAll(); await _flutterLocalNotificationsPlugin.cancelAll();
return null; return null;
} }
if (Matrix.of(context).activeRoomId == roomId) return null; if (context != null && Matrix.of(context).activeRoomId == roomId) {
return null;
}
// Get the client
print("Get client");
Client client;
if (context != null) {
client = Matrix.of(context).client;
} else {
final platform = kIsWeb ? "Web" : Platform.operatingSystem;
final clientName = "FluffyChat $platform";
print("Clientname: $clientName");
client = Client(clientName, debug: false);
client.storeAPI = ExtendedStore(client);
await client.onLoginStateChanged.stream
.firstWhere((l) => l == LoginState.logged)
.timeout(
Duration(seconds: 2),
);
}
// Get the room // Get the room
print("Get room");
Room room = client.getRoomById(roomId); Room room = client.getRoomById(roomId);
if (room == null) { if (room == null) {
await client.onRoomUpdate.stream await client.onRoomUpdate.stream
@ -110,6 +140,7 @@ abstract class FirebaseController {
} }
// Get the event // Get the event
print("Get event");
Event event = await client.store.getEventById(eventId, room); Event event = await client.store.getEventById(eventId, room);
if (event == null) { if (event == null) {
final EventUpdate eventUpdate = await client.onEvent.stream final EventUpdate eventUpdate = await client.onEvent.stream
@ -127,8 +158,8 @@ abstract class FirebaseController {
// Calculate title // Calculate title
final String title = unread > 1 final String title = unread > 1
? I18n.of(context).unreadMessagesInChats( ? I18n.of(context)
unreadEvents.toString(), unread.toString()) .unreadMessagesInChats(unreadEvents.toString(), unread.toString())
: I18n.of(context).unreadMessages(unreadEvents.toString()); : I18n.of(context).unreadMessages(unreadEvents.toString());
// Calculate the body // Calculate the body
@ -172,26 +203,62 @@ abstract class FirebaseController {
var iOSPlatformChannelSpecifics = IOSNotificationDetails(); var iOSPlatformChannelSpecifics = IOSNotificationDetails();
var platformChannelSpecifics = NotificationDetails( var platformChannelSpecifics = NotificationDetails(
androidPlatformChannelSpecifics, iOSPlatformChannelSpecifics); androidPlatformChannelSpecifics, iOSPlatformChannelSpecifics);
await _flutterLocalNotificationsPlugin.show( await _flutterLocalNotificationsPlugin.show(0,
0, room.getLocalizedDisplayname(context), body, platformChannelSpecifics,
room.getLocalizedDisplayname(context),
body,
platformChannelSpecifics,
payload: roomId); payload: roomId);
} catch (exception) { } catch (exception) {
debugPrint("[Push] Error while processing notification: " + debugPrint("[Push] Error while processing notification: " +
exception.toString()); exception.toString());
} }
return null; return null;
}, }
onResume: goToRoom,
// Currently fires unexpectetly... https://github.com/FirebaseExtended/flutterfire/issues/1060 static Future<dynamic> _handleOnBackgroundMessage(
//onLaunch: goToRoom, Map<String, dynamic> message) async {
); try {
debugPrint("[Push] Firebase initialized"); FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
FlutterLocalNotificationsPlugin();
// Init notifications framework
var initializationSettingsAndroid =
AndroidInitializationSettings('notifications_icon');
var initializationSettingsIOS = IOSInitializationSettings();
var initializationSettings = InitializationSettings(
initializationSettingsAndroid, initializationSettingsIOS);
await flutterLocalNotificationsPlugin.initialize(initializationSettings);
// Notification data and matrix data
Map<dynamic, dynamic> data = message['data'] ?? message;
String eventID = data["event_id"];
String roomID = data["room_id"];
final int unread = data.containsKey("counts")
? json.decode(data["counts"])["unread"]
: 1;
await flutterLocalNotificationsPlugin.cancelAll();
if (unread == 0 || roomID == null || eventID == null) {
return; return;
} }
// Display notification
var androidPlatformChannelSpecifics = AndroidNotificationDetails(
'fluffychat_push',
'FluffyChat push channel',
'Push notifications for FluffyChat',
importance: Importance.Max,
priority: Priority.High);
var iOSPlatformChannelSpecifics = IOSNotificationDetails();
var platformChannelSpecifics = NotificationDetails(
androidPlatformChannelSpecifics, iOSPlatformChannelSpecifics);
final String title = "$unread ungelesene Unterhaltungen";
await flutterLocalNotificationsPlugin.show(1, title,
'App öffnen, um Nachricht zu entschlüsseln', platformChannelSpecifics,
payload: roomID);
} catch (exception) {
debugPrint("[Push] Error while processing background notification: " +
exception.toString());
}
return Future<void>.value();
}
static Future<String> downloadAndSaveAvatar(Uri content, Client client, static Future<String> downloadAndSaveAvatar(Uri content, Client client,
{int width, int height}) async { {int width, int height}) async {
final bool thumbnail = width == null && height == null ? false : true; final bool thumbnail = width == null && height == null ? false : true;

View file

@ -142,7 +142,7 @@ packages:
name: firebase_messaging name: firebase_messaging
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "6.0.9" version: "6.0.13"
flutter: flutter:
dependency: "direct main" dependency: "direct main"
description: flutter description: flutter
@ -168,7 +168,7 @@ packages:
name: flutter_local_notifications name: flutter_local_notifications
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "0.9.1+2" version: "0.8.4+3"
flutter_localizations: flutter_localizations:
dependency: "direct main" dependency: "direct main"
description: flutter description: flutter

View file

@ -38,8 +38,8 @@ dependencies:
url_launcher_web: ^0.1.0 url_launcher_web: ^0.1.0
sqflite: ^1.2.0 sqflite: ^1.2.0
flutter_advanced_networkimage: any flutter_advanced_networkimage: any
firebase_messaging: ^6.0.9 firebase_messaging: ^6.0.13
flutter_local_notifications: ^0.9.1+2 flutter_local_notifications: ^0.8.4
link_text: ^0.1.1 link_text: ^0.1.1
path_provider: ^1.5.1 path_provider: ^1.5.1
webview_flutter: ^0.3.19+9 webview_flutter: ^0.3.19+9