Android AppPush Setup

Retrieve FCM Service Account Key

If your app does not already have Firebase set up or Firebase Cloud Messaging configured, please follow the linked guides to do so.

Once Firebase has been configured, follow these steps to obtain the Firebase Cloud Messaging Service Account Key:

  1. Go to http://console.firebase.com/ and click on your app
  2. Click on the cog icon in the upper right, then Project Settings
  3. Click Service Accounts, then Generate New Private Key and save the .JSON file

Upload App Push Certificate

Once the FCM Service Account Key (.JSON file) has been obtained, it must be uploaded to Wunderkind via Connect:

  1. Visit https://connect.wunderkind.co/websites/WEBSITEID/settings?tab=msdk (replacing WEBSITEID with your Website ID)
  2. Under Android > Push Notification Certificate, click Click to Upload a .JSON File and upload your .JSON file
  3. After a few seconds, the screen will update to show the time the certificate was uploaded

If the uploaded certificate needs to be removed, please reach out to Wunderkind for assistance.

App Setup

Add the code inside each function to the function that it is found in, if the function is absent, add the function as well. :

1. Update MainActivity.kt

private val requestPermissionLauncher = registerForActivityResult(
    ActivityResultContracts.RequestPermission()
) { isGranted: Boolean ->
    if (isGranted) {
        Wunderkind.getInstance().trackAppPushOptIn()
    } else {
        Wunderkind.getInstance().trackAppPushOptOut()
    }
}

private fun askNotificationPermission() {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
        if (ContextCompat.checkSelfPermission(this, Manifest.permission.POST_NOTIFICATIONS) ==
            PackageManager.PERMISSION_GRANTED
        ) {
            Wunderkind.getInstance().trackAppPushOptIn()
        } else if (shouldShowRequestPermissionRationale(Manifest.permission.POST_NOTIFICATIONS)) {
            Wunderkind.getInstance().trackAppPushOptOut()
        } else {
            requestPermissionLauncher.launch(Manifest.permission.POST_NOTIFICATIONS)
        }
    }
}

override fun onResume() {
    super.onResume()
    FirebaseMessaging.getInstance().token.addOnCompleteListener { task ->
        if (task.isSuccessful) {
            val token = task.result
            Wunderkind.getInstance().trackAppPushTokenSet(token)
        }
    }
    CheckDeliveredWunderkindAppPush(this)
    CheckOpenedWunderkindAppPush()
}

fun CheckDeliveredWunderkindAppPush(context: Context) {
    val sharedPreferences: SharedPreferences = context.getSharedPreferences(
        "wk_ap",
        Context.MODE_PRIVATE
    )
    val gson = Gson()
    val arrayMapJson = sharedPreferences.getString("wunderkind_apppush", null)
    val type = object : TypeToken<List<Map<String, String>>>() {}.type
    val arrayMap: List<Map<String, String>> = gson.fromJson(arrayMapJson, type) ?: emptyList()

    for (map in arrayMap) {
        Wunderkind.getInstance().trackAppPushDelivered(map)
    }
    val editor = sharedPreferences.edit()
    editor.remove("wunderkind_apppush")
    editor.apply()
}

fun CheckOpenedWunderkindAppPush() {
    val intent = intent
    val extras = intent.extras
    val keys = extras?.keySet()
    val wunderkindPayload = mutableMapOf<String, String>()

    keys?.forEach { key ->
        if (key.contains("wunderkind", ignoreCase = true)) {
            val stringValue: String? = intent.extras?.get(key) as? String
            if (stringValue != null) {
                wunderkindPayload[key] = stringValue
            }
            if (key.equals("wunderkindItemIds")) {
                if (stringValue != null) {
                    if (stringValue.contains(",")) {
                        val stringArray = stringValue.split(",")
                        println(stringArray) // Multiple ItemIds
                    } else {
                        println(stringValue) // Single ItemId
                    }
                }
            }
        }
    }

    if (wunderkindPayload.isNotEmpty()) {
        val stringValue: String? = intent.extras?.get("google.message_id") as? String
        if (stringValue != null) {
            wunderkindPayload["appPushId"] = stringValue
        }
        Wunderkind.getInstance().trackAppPushOpened(wunderkindPayload)
    }
}

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)
    Wunderkind.getInstance().initialize(this, MY_WEBSITE_ID, true)
    initUI()
    askNotificationPermission()
}

2. Create MyFirebaseMessagingService.kt

class MyFirebaseMessagingService : FirebaseMessagingService() {

    fun addMapToArrayMapInSharedPreferences(newMap: Map<String, String>, context: Context) {
        val sharedPreferences: SharedPreferences = context.getSharedPreferences(
            "wk_ap",
            Context.MODE_PRIVATE
        )
        val existingArrayMapJson = sharedPreferences.getString("wunderkind_apppush", null)

        val gson = Gson()
        val type = object : TypeToken<MutableList<Map<String, String>>>() {}.type

        val existingArrayMap: MutableList<Map<String, String>> = gson.fromJson(existingArrayMapJson, type)
            ?: mutableListOf()
        existingArrayMap.add(newMap)

        val editor = sharedPreferences.edit()
        val updatedArrayMapJson = gson.toJson(existingArrayMap)
        editor.putString("wunderkind_apppush", updatedArrayMapJson)
        editor.apply()
    }

    override fun onMessageReceived(remoteMessage: RemoteMessage) {
        val messageId = remoteMessage.messageId
        val appPushData = remoteMessage.data.toMutableMap()
        appPushData["appPushId"] = messageId ?: ""

        if (isAppInForeground()) {
            if (remoteMessage.data["wunderkindData"] != null) {
                Wunderkind.getInstance().trackAppPushDelivered(appPushData)
            }
        } else {
            addMapToArrayMapInSharedPreferences(appPushData, applicationContext)
        }
    }
}

3. Update AndroidManifest.xml

Ensure your file includes the MyFirebaseMessagingService service and a com.google.firebase.messaging.default_notification_channel_id metadata:

<service 
    android:name=".MyFirebaseMessagingService" 
    android:exported="false">
    <intent-filter>
        <action android:name="com.google.firebase.MESSAGING_EVENT" />
    </intent-filter>
</service>

<meta-data
    android:name="com.google.firebase.messaging.default_notification_channel_id"
    android:value="@string/default_notification_channel_id" />