Skip to content

feat: Add support for push notifications via ParsePush, ParseNotification #914

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 13 commits into from
May 22, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions packages/flutter/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
## [5.1.0](https://github.com/parse-community/Parse-SDK-Flutter/compare/flutter-5.0.1...flutter-5.1.0) (2023-05-22)

### Features

* Add support for push notifications via `ParsePush`, `ParseNotification` ([#914](https://github.com/parse-community/Parse-SDK-Flutter/pull/914))

## [5.0.1](https://github.com/parse-community/Parse-SDK-Flutter/compare/flutter-5.0.0...flutter-5.0.1) (2023-05-20)

### Bug Fixes
Expand Down
76 changes: 76 additions & 0 deletions packages/flutter/PUSH.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
# Push Notifications

Push notifications are a great way to keep your users engaged and informed about your app. You can reach your user base quickly and effectively. This guide will help you through the setup process and the general usage of Parse Platform to send push notifications.

To configure push notifications in Parse Server, check out the [push notification guide](https://docs.parseplatform.org/parse-server/guide/#push-notifications).

## Installation

1. Install [Firebase Core](https://firebase.flutter.dev/docs/overview) and [Cloud Messaging](https://firebase.flutter.dev/docs/messaging/overview). For more details review the [Firebase Core Manual](https://firebase.flutter.dev/docs/manual-installation/).

2. Add the following code after `Parse().initialize(...);`:

```dart
ParsePush.instance.initialize(FirebaseMessaging.instance);
FirebaseMessaging.onMessage.listen((message) => ParsePush.instance.onMessage(message));
```

3. For you app to process push notification while in the background, add the following code:

```dart
FirebaseMessaging.onBackgroundMessage(onBackgroundMessage);
```

```dart
Future<void> onBackgroundMessage(RemoteMessage message) async => ParsePush.instance.onMessage(message);
```

## Implementation Example

The following is a code example for a simple implementation of push notifications:

```dart
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();

// Initialize Firebase Core
await Firebase.initializeApp(
options: DefaultFirebaseOptions.currentPlatform,
);

// Initialize Parse
await Parse().initialize("applicationId", "serverUrl",
clientKey: "clientKey", debug: true);

// Initialize Parse push notifications
ParsePush.instance.initialize(FirebaseMessaging.instance);
FirebaseMessaging.onMessage
.listen((message) => ParsePush.instance.onMessage(message));

// Process push notifications while app is in the background
FirebaseMessaging.onBackgroundMessage(onBackgroundMessage);

runApp(const MyApp());
}

Future<void> onBackgroundMessage(RemoteMessage message) async =>
ParsePush.instance.onMessage(message);

class MyApp extends StatelessWidget {
const MyApp({super.key});

// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
useMaterial3: true,
),
home: const MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
...
```
6 changes: 5 additions & 1 deletion packages/flutter/lib/parse_server_sdk_flutter.dart
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
library flutter_parse_sdk_flutter;

import 'dart:convert';
import 'dart:async';
import 'dart:io';

import 'dart:math';
import 'package:awesome_notifications/awesome_notifications.dart';
import 'package:connectivity_plus/connectivity_plus.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
Expand All @@ -20,6 +22,8 @@ export 'package:parse_server_sdk/parse_server_sdk.dart'
part 'src/storage/core_store_sp_impl.dart';
part 'src/utils/parse_live_grid.dart';
part 'src/utils/parse_live_list.dart';
part 'src/notification/parse_notification.dart';
part 'src/push//parse_push.dart';

class Parse extends sdk.Parse
with WidgetsBindingObserver
Expand Down
33 changes: 33 additions & 0 deletions packages/flutter/lib/src/notification/parse_notification.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
part of flutter_parse_sdk_flutter;

class ParseNotification {
static final ParseNotification instance = ParseNotification._internal();
static String keyNotificationChannelName = "parse";

factory ParseNotification() {
return instance;
}

ParseNotification._internal() {
// Initialize notifications helper package
AwesomeNotifications().initialize(
null,
[
NotificationChannel(
channelKey: keyNotificationChannelName,
channelName: keyNotificationChannelName,
channelDescription: 'Notification channel for parse')
],
);
}

/// Show notification
void showNotification(title) {
AwesomeNotifications().createNotification(
content: NotificationContent(
id: Random().nextInt(1000),
channelKey: keyNotificationChannelName,
title: title,
));
}
}
86 changes: 86 additions & 0 deletions packages/flutter/lib/src/push/parse_push.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
part of flutter_parse_sdk_flutter;

class ParsePush {
static final ParsePush instance = ParsePush._internal();

static String keyType = "gcm";
static String keyPushType = 'pushType';

factory ParsePush() {
return instance;
}

ParsePush._internal();

/// Initialize ParsePush; for web a [vapidKey] is required.
Future<void> initialize(
firebaseMessaging, {
String? vapidKey,
}) async {
// Get Google Cloud Messaging (GCM) token
firebaseMessaging
.getToken(vapidKey: vapidKey)
.asStream()
.listen((event) async {
// Set token in installation
sdk.ParseInstallation parseInstallation =
await sdk.ParseInstallation.currentInstallation();

parseInstallation.deviceToken = event;
parseInstallation.set(keyPushType, keyType);

await parseInstallation.save();
});
}

/// Handle push notification message
void onMessage(message) {
String pushId = message.data["push_id"] ?? "";
String timestamp = message.data["time"] ?? "";
String dataString = message.data["data"] ?? "";
String channel = message.data["channel"] ?? "";

Map<String, dynamic>? data;
try {
data = json.decode(dataString);
} catch (_) {}

_handlePush(pushId, timestamp, channel, data);
}

void _handlePush(String pushId, String timestamp, String channel,
Map<String, dynamic>? data) {
if (pushId.isEmpty || timestamp.isEmpty) {
return;
}

if (data != null) {
// Show push notification
ParseNotification.instance.showNotification(data["alert"]);
}
}

/// Subscribes the device to a channel of push notifications
Future<void> subscribeToChannel(String value) async {
sdk.ParseInstallation parseInstallation =
await sdk.ParseInstallation.currentInstallation();

await parseInstallation.subscribeToChannel(value);
}

/// Unsubscribes the device to a channel of push notifications
Future<void> unsubscribeFromChannel(String value) async {
sdk.ParseInstallation parseInstallation =
await sdk.ParseInstallation.currentInstallation();

await parseInstallation.unsubscribeFromChannel(value);
}

/// Returns an <List<String>> containing all the channel names this device is subscribed to
Future<List<dynamic>> getSubscribedChannels() async {
sdk.ParseInstallation parseInstallation =
await sdk.ParseInstallation.currentInstallation();

return await parseInstallation.getSubscribedChannels();
}
}
5 changes: 3 additions & 2 deletions packages/flutter/pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name: parse_server_sdk_flutter
description: The Flutter SDK to connect to Parse Server. Build your apps faster with Parse Platform, the complete application stack.
version: 5.0.1
version: 5.1.0
homepage: https://github.com/parse-community/Parse-SDK-Flutter

environment:
Expand All @@ -10,7 +10,7 @@ dependencies:
flutter:
sdk: flutter

parse_server_sdk: ^5.1.0
parse_server_sdk: ^5.1.1
# Uncomment for local testing
#parse_server_sdk:
# path: ../dart
Expand All @@ -28,6 +28,7 @@ dependencies:
sembast: ^3.4.0+6
sembast_web: ^2.1.0+4
path: ^1.8.2 # required for transitive use only
awesome_notifications: ^0.7.4+1

dev_dependencies:
flutter_lints: ^2.0.1
Expand Down