Documentation

Flutter Setup


To start sending push notifications to your Flutter app with Pushy, please follow our detailed instructions below.

At any time, you may refer to our Flutter demo project for a working demo.

Create an App

The first step involves signing up and creating your first app on Pushy.

If you have already created your app on Pushy for another platform, simply configure your existing app with your Android Package Name & iOS Bundle ID in the App Settings tab and proceed to the next step.

Note: You can upgrade to our Pro plan at any time by setting up a payment method in the Billing page.


Click Create and proceed to the next step.

Get the SDK

Install version 1.0.1 of our Flutter SDK by editing the pubspec.yaml in the root directory of your project and adding the following under the dependencies section:

pushy_flutter: 1.0.1

Run flutter pub get to fetch the dependency.

Enable Swift Frameworks (iOS)

Edit the ios/Podfile file in your project and find:

target 'Runner' do

Add the following line below to configure Swift framework support:

use_frameworks!

Save and close the file.

Enable Push Capability (iOS)

Enable the Push Notifications capability manually for your iOS app to register for and receive push notifications. Open your Flutter iOS app in Xcode by running the following command in your project root:

open ios/*.xcworkspace

Then, visit the project editor, select the Runner target, select the Capabilities tab, and turn on the Push Notifications capability:

Note: Xcode should display two checkmarks indicating that the capability was successfully enabled.

Add Blank Swift File

To avoid a compilation error, please add a blank .swift file to your Xcode project, under the Runner target. This file can be empty. When prompted, you may decline the creation of a bridging header for your project.


You may close the Xcode workspace now.

Modify AndroidManifest

Add the following lines to your android/app/src/main/AndroidManifest.xml, inside the <manifest> tag:

<!-- Pushy Permissions -->
                                    
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

<!-- End Pushy Permissions -->

You should manually omit any permission declarations that your app already asks for.

Note: android.permission.WRITE_EXTERNAL_STORAGE is optional - it is necessary only for persisting device tokens in the external storage for when your app is reinstalled, so we don't charge you twice for the same device. If this permission is not declared, the SDK will persist device tokens only within your app's SharedPreferences, which are cleared when your app is uninstalled.


Additionally, add the following declarations inside the <application> tag:

<!-- Pushy Declarations -->

<!-- Pushy Notification Receiver -->
<!-- Incoming push notifications will invoke the following BroadcastReceiver -->
<receiver android:name="me.pushy.sdk.flutter.PushReceiver" android:exported="false">
    <intent-filter>
        <!-- Do not modify this -->
        <action android:name="pushy.me" />
    </intent-filter>
</receiver>

<!-- Internal Notification Receiver -->
<!-- Do not modify - internal BroadcastReceiver that sends notifications to your Flutter app -->
<receiver android:name="me.pushy.sdk.flutter.internal.PushyInternalReceiver" android:exported="false">
    <intent-filter>
        <!-- Do not modify this -->
        <action android:name="pushy.me" />
    </intent-filter>
</receiver>

<!-- Pushy Update Receiver -->
<!-- Do not modify - internal BroadcastReceiver that restarts the listener service -->
<receiver android:name="me.pushy.sdk.receivers.PushyUpdateReceiver" android:exported="false">
    <intent-filter>
        <action android:name="android.intent.action.MY_PACKAGE_REPLACED" />
    </intent-filter>
</receiver>

<!-- Pushy Boot Receiver -->
<!-- Do not modify - internal BroadcastReceiver that restarts the listener service -->
<receiver android:name="me.pushy.sdk.receivers.PushyBootReceiver" android:exported="false">
    <intent-filter>
        <action android:name="android.intent.action.BOOT_COMPLETED"/>
    </intent-filter>
</receiver>

<!-- Pushy Socket Service -->
<!-- Do not modify - internal service -->
<service android:name="me.pushy.sdk.services.PushySocketService"/>

<!-- Pushy Job Service (added in Pushy SDK 1.0.35) -->
<!-- Do not modify - internal service -->
<service android:name="me.pushy.sdk.services.PushyJobService"
    android:permission="android.permission.BIND_JOB_SERVICE"
    android:exported="true" />

<!-- End Pushy Declarations -->
Modify Flutter App

Import pushy_flutter by adding the following to the top of your lib/main.dart file:

import 'package:flutter/services.dart';
import 'package:pushy_flutter/pushy_flutter.dart';

Invoke Pushy.listen() in your lib/main.dart file's initState() method so that Pushy's internal notification listening service will start itself, if necessary:

// Start the Pushy service
Pushy.listen();

Note: If your main.dart does not yet have an initState(), simply define it under your State<> class, e.g. _MyHomePageState:

@override
void initState() {
    super.initState();
    
    // Start the Pushy service
    Pushy.listen();
}
Android 6.0+ Compatibility

Android 6.0 and newer versions require apps with a targetSdkVersion >= 23 to explicitly request permissions from users via permission dialogs.

Since Pushy persists device tokens in the external storage (to survive app reinstallation), you should add the following code to ask the user to grant your app permission to access the external storage.

Find:
Pushy.listen();
Add Below:
// Request the WRITE_EXTERNAL_STORAGE permission on Android so that the Pushy SDK will be able to persist the device token in the external storage
Pushy.requestStoragePermission();
Register Devices

Devices need to be uniquely identified to receive push notifications.

Every device is assigned a unique token that you can use to push it at any given time. Once the device has been assigned a token, it should be stored in your application's backend database. When you're ready to push the device, your backend server will send its token to our REST API, and we'll deliver the push notification to the corresponding device.


Add the following method to your application to register the device for notifications:

Future pushyRegister() async {
    try {
        // Register the device for push notifications
        String deviceToken = await Pushy.register();

        // Print token to console/logcat
        print('Device token: $deviceToken');

        // Display an alert with the device token
        showDialog(
        context: context,
        builder: (BuildContext context) {
            return AlertDialog(
                title: Text('Pushy'),
                content: Text('Pushy device token: $deviceToken'),
                actions: [ FlatButton( child: Text('OK'), onPressed: () { Navigator.of(context, rootNavigator: true).pop('dialog'); } )]
            );
        }
        );
        
        // Optionally send the token to your backend server via an HTTP GET request
        // ...
    } on PlatformException catch (error) {
        // Display an alert with the error message
        showDialog(
        context: context,
        builder: (BuildContext context) {
            return AlertDialog(
                title: Text('Error'),
                content: Text(error.message),
                actions: [ FlatButton( child: Text('OK'), onPressed: () { Navigator.of(context, rootNavigator: true).pop('dialog'); } )]
            );
        }
        );
    }
}

Then, invoke this method, possibly in initState():

@override
void initState() {
    super.initState();

    // ...

    // Register the device for push notifications
    pushyRegister();
}
Listen for Notifications

Call the Pushy.setNotificationListener(data) method from your application to handle incoming push notifications:

// Listen for push notifications
Pushy.setNotificationListener((Map<String, dynamic> data) {
    // Print notification payload data
    print('Received notification: $data');

    // Extract notification messsage
    String message = data['message'] ?? 'Hello World!';

    // Display an alert with the "message" payload value
    showDialog(
        context: context,
        builder: (BuildContext context) {
        return AlertDialog(
            title: Text('Pushy'),
            content: Text(message),
            actions: [ FlatButton( child: Text('OK'), onPressed: () { Navigator.of(context, rootNavigator: true).pop('dialog'); } )]
        );
    });

    // Clear iOS app badge number
    Pushy.clearBadge();
});

Feel free to modify this sample code to suit your own needs.

Note: This callback is only invoked if incoming notifications are received while your app is in foreground. Otherwise, this callback will be invoked the next time your app goes to foreground.

Custom Notification Icon (Android)

Optionally configure a custom notification icon for incoming Android notifications by placing icon file(s) in android/app/src/main/res/mipmap-* and calling:

Pushy.setNotificationIcon('ic_notification');

Please invoke this method after Pushy.listen() and replace ic_notification with the resource file name, excluding the extension.

Note: If you don't call this method, or an invalid resource is provided, a generic icon will be used instead.

Parse Notification Data

Any payload data that you send with your push notifications is made available to your app via the data parameter of your notification listener.

If you were to send a push notification with the following data:

{"id": 1, "success": true, "message": "Hello World"}

Then you'd be able to retrieve each value from within your notification listener callback like so:

int id = data['id']; // number
bool success = data['success']; // bool
String message = data['message']; // string

Note: Unlike GCM / FCM, we do not stringify your payload data, except if you supply JSON objects or arrays.

Subscribe to Topics (Optional)

Optionally subscribe the device to one or more topics to target multiple users with a shared interest when sending notifications.

Depending on your app's notification criteria, you may be able to leverage topics to simply the process of sending the same notification to multiple users. If your app only sends personalized notifications, skip this step and simply target individual devices by specifying their tokens.


Add the following code to your application to subscribe a registered device to a topic:

try {
    // Make sure the device is registered
    if (await Pushy.isRegistered()) {
        // Subscribe the device to a topic
        await Pushy.subscribe('news');

        // Subscribe successful
        print('Subscribed to topic successfully');
    }
} on PlatformException catch (error) {
    // Subscribe failed, notify the user
    showDialog(
        context: context,
        builder: (BuildContext context) {
        return AlertDialog(
            title: Text('Subscribe failed'),
            content: Text(error.message),
            actions: [ FlatButton( child: Text('OK'), onPressed: () { Navigator.of(context, rootNavigator: true).pop('dialog'); } )]
            );
        }
    );
}

Note: Replace news with your own case-sensitive topic name that matches the following regular expression: [a-zA-Z0-9-_.]+.


You can then notify multiple devices subscribed to a certain topic by specifying the topic name (prefixed with /topics/) as the to parameter in the Send Notifications API.

Modify the Android Push Receiver (Optional)

Optionally modify the default Android push BroadcastReceiver implementation to handle incoming notifications differently.

The built-in push receiver emits a system notification with your app name and icon, and extracts the message from the {"message": "..."} JSON data payload value. If this behavior is sufficient for your app, you may skip this step.


Create a file PushReceiver.java in the following path:

android/app/src/main/java/PushReceiver.java

Paste the contents of the default PushReceiver.java into this file.

Note: You will need to update the package declaration to reflect your app's package name.


When you are done modifying the default implementation, modify your android/app/src/main/AndroidManifest.xml, replacing me.pushy.sdk.flutter.PushReceiver with .PushReceiver in the following declaration:

<!-- Pushy Notification Receiver -->
<!-- Incoming push notifications will invoke the following BroadcastReceiver -->
<receiver android:name="me.pushy.sdk.flutter.PushReceiver" android:exported="false">
    <intent-filter>
        <!-- Do not modify this -->
        <action android:name="pushy.me" />
    </intent-filter>
</receiver>
Setup APNs Authentication (iOS)

Configure the Pushy dashboard with an APNs Auth Key in order to send notifications to your iOS users.

Pushy routes your iOS push notifications through APNs, the Apple Push Notification Service. To send push notifications with APNs, we need to be able to authenticate on behalf of your app. This is achieved by generating an APNs Auth Key and uploading it to the Dashboard.


In the Apple Developer Center, visit the Auth Keys creation page, enter a key name, and choose Apple Push Notifications service (APNs).

Click Continue and download the .p8 key file:



Note: Keep track of the assigned Key ID for the next step.


Visit the Pushy Dashboard -> Your app -> App Settings -> Configure APNs Auth ().

Fill in the following:

  1. APNs Auth Key - drag and drop the auth key .p8 file from the previous step
  2. Key ID - the Key ID assigned to the key you downloaded in the previous step
  3. Team ID - the Team ID of your Apple Developer Account, available in Membership Details

Click Submit to finish setting up APNs authentication for your app.

Note: Avoid revoking your APNs Auth Key in the Apple Developer Center. Otherwise, you will not be able to send notifications with Pushy. If you think your key was compromised, generate a new one in the Apple Developer Center. Then, upload it to the Dashboard. Finally, revoke your old key in the Apple Developer Center.

Build and Test

Run your app on each platform to make sure everything works as expected:

flutter run
Send Test Notification

Input a device token and select your app to send a test push notification:

Note: You can specify a topic instead of a device token (i.e. /topics/news). Also, if your app is not automatically detected, please manually copy the Secret API Key from the Dashboard and paste it into the form.

Check if your device received the notification. Did it work? If not, contact us, we'll be glad to help.

Integration Complete


Congratulations on implementing Pushy in your app!

Now, all that's left is to setup your backend. Head on over to the Backend Setup guide to begin persisting device tokens as well as implementing the logic for sending push notifications to your users.