NativeNotificationBridge.kt 3.26 KB
Newer Older
1
2
3
4
5
6
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

package mozilla.components.feature.webnotifications

7
import android.app.Activity
8
import android.app.Notification
9
import android.app.PendingIntent
10
import android.content.Context
11
import android.content.Intent
12
13
14
import android.graphics.Bitmap
import android.os.Build
import android.os.Build.VERSION.SDK_INT
15
import androidx.annotation.DrawableRes
16
17
18
19
20
import mozilla.components.browser.icons.BrowserIcons
import mozilla.components.browser.icons.Icon.Source
import mozilla.components.browser.icons.IconRequest
import mozilla.components.browser.icons.IconRequest.Size
import mozilla.components.concept.engine.webnotifications.WebNotification
21
import mozilla.components.support.ktx.kotlin.tryGetHostFromUrl
22
23

internal class NativeNotificationBridge(
24
25
    private val icons: BrowserIcons,
    @DrawableRes private val smallIcon: Int
26
) {
27
28
29
    companion object {
        private const val EXTRA_ON_CLICK = "mozac.feature.webnotifications.generic.onclick"
    }
30
31
32
33

    /**
     * Create a system [Notification] from this [WebNotification].
     */
34
    @Suppress("LongParameterList")
35
36
37
    suspend fun convertToAndroidNotification(
        notification: WebNotification,
        context: Context,
38
39
40
        channelId: String,
        activityClass: Class<out Activity>?,
        requestId: Int
41
42
43
44
45
46
47
48
49
    ): Notification {
        val builder = if (SDK_INT >= Build.VERSION_CODES.O) {
            Notification.Builder(context, channelId)
        } else {
            @Suppress("Deprecation")
            Notification.Builder(context)
        }

        with(notification) {
50
51
52
53
            activityClass?.let {
                val intent = Intent(context, activityClass).apply {
                    putExtra(EXTRA_ON_CLICK, tag)
                }
54

55
56
57
                PendingIntent.getActivity(context, requestId, intent, 0).apply {
                    builder.setContentIntent(this)
                }
58
59
            }

60
61
62
63
64
65
            builder.setSmallIcon(smallIcon)
                .setContentTitle(title)
                .setShowWhen(true)
                .setWhen(timestamp)
                .setAutoCancel(true)

66
67
68
69
            sourceUrl?.let {
                builder.setSubText(it.tryGetHostFromUrl())
            }

70
71
72
73
74
            body?.let {
                builder.setContentText(body)
                    .setStyle(Notification.BigTextStyle().bigText(body))
            }

75
            loadIcon(sourceUrl, iconUrl, Size.DEFAULT, true)?.let { iconBitmap ->
76
                builder.setLargeIcon(iconBitmap)
77
78
79
80
81
82
83
84
85
            }
        }

        return builder.build()
    }

    /**
     * Load an icon for a notification.
     */
86
    private suspend fun loadIcon(url: String?, iconUrl: String?, size: Size, isPrivate: Boolean): Bitmap? {
87
        url ?: return null
88
        iconUrl ?: return null
89
        val icon = icons.loadIcon(IconRequest(
90
            url = url,
91
92
            size = size,
            resources = listOf(IconRequest.Resource(
93
                url = iconUrl,
94
                type = IconRequest.Resource.Type.MANIFEST_ICON
Roger Yang's avatar
Roger Yang committed
95
96
            )),
            isPrivate = isPrivate
97
98
99
100
101
        )).await()

        return if (icon.source == Source.GENERATOR) null else icon.bitmap
    }
}