> ## Documentation Index
> Fetch the complete documentation index at: https://docs.castled.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Push Notification

> [!NOTE]
>
> **Prerequisites**
>
> * [Firebase account already setup and is added to your app](https://docs.castled.io/developer-resources/sdk-integration/android/fcm-private-key-setup.md)
> * [SDK integration completed](https://docs.castled.io/developer-resources/sdk-integration/android/getting-started.md)

Castled uses [Google Firebase Cloud Messaging(FCM)](https://firebase.google.com/docs/cloud-messaging) to send push notifications to Android devices. The following steps will walk you through the process of setting up your application
to receive push notification from Castled.

## Quick Demo

[https://www.loom.com/embed/1d11fbebfd58412c8be7fc3c603f80e3](https://www.loom.com/embed/1d11fbebfd58412c8be7fc3c603f80e3)

## Enabling Push Notification in SDK

Set the flag `enablePush` to `true` when initializing the SDK

```kotlin
// SDK initialization
CastledNotifications.initialize(
    this, CastledConfigs.Builder()
        .apiKey("<api-key>")
        .location(<location>)
        .enablePush(true)
        .build()
)
```

## Permissions

Starting from Android 13 (API level 33), a new runtime permission, `POST_NOTIFICATIONS`, has been introduced for apps to send non-exempt notifications, including those from Foreground Services (FGS).
You need to declare following permissions in the App's manifest file.

```xml AndroidManifest.xml
<manifest ...>
    <uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
    <application ...>
        ...
    </application>
</manifest>
```

Once the manifest file is updated, app should request the user for the permission at runtime.
[Here](https://developer.android.com/training/permissions/requesting) are some guidelines on requesting runtime permissions.

## Firebase push messaging handling service

By default SDK takes care of FCM push token fetch and notification handling once app gets the permission to post notification. In case the app has registered its own Firebase message service class for handling FCM token,
SDK needs to be notified of the new token and any push notification received from Castled platform. This can be done as follows:

Your app manifest would have a service class similar to `MyAppMessagingService` to handle Firebase messaging events.

```xml AndroidManifest.xml
<manifest ...>
    ...
    <application ...>

        <service
            android:name="io.castled.android.notifications.push.MyAppMessagingService"
            android:exported="false">
            <intent-filter>
                <action android:name="com.google.firebase.MESSAGING_EVENT" />
            </intent-filter>
        </service>
        ...
    </application>

</manifest>
```

Add the following code snippets in the overrided `onNewToken` and `onMessageReceived` methods of your FCM service class.

```kotlin MyAppMessagingService.kt
class MyAppMessagingService : FirebaseMessagingService() {
    ...

    override fun onNewToken(token: String) {
        super.onNewToken(token)
        // Notify SDK of new token
        CastledNotifications.onTokenFetch(token, PushTokenType.FCM)

        // Your custom token handling code goes here...
        ...
    }

    override fun onMessageReceived(remoteMessage: RemoteMessage) {
        if (CastledNotifications.isCastledPushMessage(remoteMessage)) {
            // Notification initiated from Castled platform. Handle message payload
            CastledNotifications.handlePushNotification(this, remoteMessage)
        } else {
            // Your custom push notification handling code goes here...
            ...
        }
    }
}
```

## Notification default configs

SDK provides option to specify default values for some of the push notification
payload fields. You need to create a `castled.xml` file in the `res/values`
folder of your app project. Default values takes effect only if push payload doesn't
have any values specified for these fields.

### Notification channels

Add the following values to `castled.xml` if you want to specify a default
channel for notifications from Castled. More details on android notifications
channels can be found here.

```xml castled.xml
<resources>
    ...

    <string name="io_castled_push_default_channel_id">YOUR_NOTIFICATION_CHANNEL_ID</string>
    <string name="io_castled_push_default_channel_name">YOUR_NOTIFICATION_CHANNEL_NAME</string>
    <string name="io_castled_push_default_channel_desc">YOUR_NOTIFICATION_CHANNEL_DESC</string>
    <integer name="io_castled_push_default_channel_importance">YOUR_NOTIFICATION_CHANNEL_IMPORTANCE_VALUE</integer>

    ...
</resources>
```

`YOUR_NOTIFICATION_CHANNEL_IMPORTANCE_VALUE` can be any integer in the range `[1,4]`, `1` being lowest importance and `5` being highest.

### Small and large default icons

You can also optionally specify default small and large icons for push notifications in `castled.xml`.

![](https://mintlify.s3-us-west-1.amazonaws.com/castled/images/push-1.png)

1. small icon 2. large icon

```xml castled.xml
<resources>
    ...

    <!-- Castled default small and large icons -->
    <drawable name="io_castled_push_default_small_icon">YOUR_NOTIFICATION_SMALL_ICON</drawable>
    <drawable name="io_castled_push_default_large_icon">YOUR_NOTIFICATION_LARGE_ICON</drawable>

    ...
</resources>
```

## Notification Listeners

App can listen to Castled push notification events by registering a listener. Listener object should implement the interface `CastledPushNotificationListener`.

Following code snippet uses an anonymous object as the listener.

```kotlin MyApplicationClass.kt
    // Listening to push notification events
    CastledNotifications.subscribeToPushNotificationEvents(object :
        CastledPushNotificationListener {

        // Push received
        override fun onCastledPushReceived(pushMessage: CastledPushMessage) {
            logger.debug("Received push message with id: ${pushMessage.getNotificationDisplayId()}")
        }

        // Push clicked
        override fun onCastledPushClicked(
            pushMessage: CastledPushMessage,
            actionContext: CastledActionContext
        ) {
            logger.debug("User clicked push message with id: ${pushMessage.getNotificationDisplayId()}")
        }

        // Push dismissed
        override fun onCastledPushDismissed(pushMessage: CastledPushMessage) {
            logger.debug("Dismissed push message with id: ${pushMessage.getNotificationDisplayId()}")
        }
    })

```

## FAQ

> **How to see all the logs from Castled SDK**
>
> You can view all messages logged by the SDK in **Android Studio Logcat** using the filter tag `CastledNotifications`

> **Push notification is not showing in the device after sending from Castled dashboard**
>
> There can be a lot of reasons why this could happen after a successfull SDK
> initialization. You can use the following checklist as a starter for debugging
> this issue.
>
> 1. Ensure mobile device has network connection.
> 2. Make sure `enablePush` config is set to `true`.
> 3. Firebase configs are setup in Castled dashboard.
> 4. Make sure app has granted push notification permission. You can
>    navigate to **Settings > Notifications > App Notifications > Your App** to see
>    the notification permission status.
> 5. If you are running the app in debug mode, make sure app is running. It can be in focus or out of focus.
> 6. If sending notification using a **Campaign** or **Workflow**, check out the
>    **Reports** section for the **Campaign** or **Workflow**. If `Skipped` counter
>    is non zero, it likely means SDK was not able to send push token to Castled
>    server. Try removing the app and re-installing. If problem persists contact
>    support.
> 7. Verify that the app is not force stopped. For e.g. some devices
>    have energy saving mode enabled that could kill the app. You can verify the
>    app status by running the following command in adb shell. `shell adb shell
>        dumpsys package com.company.myapp | grep stopped ` App state should be
>    `stopped=false` to receive push.
> 8. If you already tried the above checklist and the problem still persists, reach out to
>    `tech@castled.io` or ping us in our Slack channel.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.