# Push Notifications

Push notifications are sent for different types of events, such as someone following you, commenting on your activity or reacting to it.

Getting them working takes three things: a push provider configured on your dashboard, the provider named in the client's config, and the device's token registered with Stream.

## Dashboard configuration

Set up the provider you use (Firebase Cloud Messaging, APNs, Huawei Push Kit or Xiaomi Mi Push) under [push providers](https://getstream.io/docs/platform/push-providers/), and note the name you give the configuration. Registering a device against a provider that is not configured fails.

Which events produce a notification, and what they look like, is configured per feed group. See [Feed group push configuration](https://getstream.io/activity-feeds/docs/node/feed-group-push-configuration/) and [Push templates](https://getstream.io/activity-feeds/docs/node/push-template/).

## Client configuration

Name the provider configuration when you build the client:

```dart label="Dart"
// Tell the client which push provider configuration your app uses. The name
// is the one you gave the configuration in the Stream dashboard.
final client = StreamFeedsClient(
  apiKey: '<your_api_key>',
  user: const User(id: 'alice'),
  tokenProvider: TokenProvider.static(UserToken('<your_jwt_token>')),
  config: const FeedsConfig(
    pushNotificationsConfig: PushNotificationsConfig(
      pushProviderInfo: PushProviderInfo(
        name: 'my-app-firebase',
        pushProvider: PushNotificationsProvider.firebase,
      ),
    ),
  ),
);
await client.connect();
```

## Registering a device

Getting the device token itself is the platform's job, not this SDK's: `firebase_messaging` for FCM, or the APNs registration callback on iOS. Once you have it, hand it to [`createDevice`](https://getstream.io/docs/platform/push-devices/):

```dart label="Dart"
// The token comes from the platform: FCM on Android, APNs on iOS. Register
// it after connecting, and again whenever the platform rotates it.
const deviceToken = '<the token your app received from FCM or APNs>';

final result = await client.createDevice(
  id: deviceToken,
  pushProvider: PushNotificationsProvider.firebase,
  pushProviderName: 'my-app-firebase',
);

switch (result) {
  case Success():
    print('Device registered');
  case Failure(error: final error):
    print('Failed to register the device: $error');
}
```

Register the token after connecting, and again whenever the platform rotates it.

## Removing a device

Remove the device on sign-out, so its user stops receiving notifications there:

```dart label="Dart"
// On sign-out, so the user stops receiving notifications on this device
await client.deleteDevice(id: '<the device token>');
```

## Listing devices

```dart label="Dart"
final result = await client.queryDevices();

for (final device in result.getOrThrow().devices) {
  print('${device.id} (${device.pushProvider}/${device.pushProviderName})');
  print('  registered ${device.createdAt}');
  if (device.disabled ?? false) {
    print('  disabled: ${device.disabledReason}');
  }
}
```

`DeviceResponse` carries `id`, `pushProvider`, `pushProviderName`, `userId`, `createdAt`, and `disabled` with a `disabledReason` when the provider rejected the token.

## Sending an activity without a push

`skipPush` creates the activity without sending a notification for it:

```dart label="Dart"
final feed = client.feed(group: 'user', id: 'john');

// The activity is created, but no push notification is sent for it
await feed.addActivity(
  request: const FeedAddActivityRequest(
    type: 'post',
    text: 'A quiet post',
    skipPush: true,
  ),
);
```

`Feed.follow` takes `createNotificationActivity`, which is the related but distinct question of whether the follow puts an activity on the target's notification feed. See [Notification feeds](https://getstream.io/activity-feeds/docs/flutter/notification-feeds/).

## Receiving the notification

Displaying the notification is your app's job. The payload arrives through your push plugin's own handler (`FirebaseMessaging.onMessage` and `onBackgroundMessage` for FCM), and what it contains is set by the [push template](https://getstream.io/activity-feeds/docs/node/push-template/) for the feed group.

---

For the most recent version of this documentation, visit [https://getstream.io/activity-feeds/docs/flutter/push-notifications/](https://getstream.io/activity-feeds/docs/flutter/push-notifications/).