Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,14 @@ import android.content.pm.PackageManager
import android.database.Cursor
import android.net.Uri
import android.os.Bundle
import android.util.Log
import io.getstream.android.push.delegate.PushDelegateProvider.Companion.METADATA_VALUE
import io.getstream.android.push.delegate.PushDelegateProvider.Companion._delegates
import io.getstream.android.push.delegate.PushDelegateProvider.Companion.isInitialized
import io.getstream.log.taggedLogger

public class AndroidPushDelegateProvider : PushDelegateProvider, ContentProvider() {

private val logger by taggedLogger("Push:Delegate")
private val TAG = "Push:Delegate"

override fun onCreate(): Boolean {
initializeDelegates()
Expand Down Expand Up @@ -69,13 +69,12 @@ public class AndroidPushDelegateProvider : PushDelegateProvider, ContentProvider
?.getDeclaredConstructor()
?.newInstance() as? PushDelegate
} catch (e: ClassNotFoundException) {
logger.e(e) { "PushDelegate not created for '$this'" }
Log.e(TAG, "PushDelegate not created for '$this'", e)
null
} catch (e: NoSuchMethodException) {
logger.e(e) { "PushDelegate not created for '$this'" }
Log.e(TAG, "PushDelegate not created for '$this'", e)
null
}
.also { logger.d { "PushDelegate created for '$this' ($it)" } }

override fun query(
uri: Uri,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,33 +16,33 @@
package io.getstream.android.push.permissions

import android.app.Application
import io.getstream.log.taggedLogger
import android.util.Log

public class NotificationPermissionManager private constructor(
private val pushNotificationPermissionRequester: PushNotificationPermissionRequester,
private val requestPermissionOnAppLaunch: () -> Boolean,
private val onPermissionStatus: (NotificationPermissionStatus) -> Unit
) : PushNotificationPermissionRequester.PushNotificationPermissionCallback {
private val logger by taggedLogger("Push:Notifications-PM")
private val TAG = "Push:Notifications-PM"
private var started = false

private fun initialize() {
logger.d { "[initialize] no args" }
Log.d(TAG, "[initialize] no args")
pushNotificationPermissionRequester.addCallback(this)
}

public fun start() {
logger.d { "[start] no args" }
Log.d(TAG, "[start] no args")
requestPermission()
}

public fun stop() {
logger.d { "[stop] no args" }
Log.d(TAG, "[stop] no args")
started = false
}

override fun onAppLaunched() {
logger.d { "[onAppLaunched] no args" }
Log.d(TAG, "[onAppLaunched] no args")
if (requestPermissionOnAppLaunch()) {
requestPermission()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,125 +22,121 @@ import android.app.Application
import android.content.pm.PackageManager
import android.os.Build
import android.os.Bundle
import android.util.Log
import android.view.View
import android.view.ViewGroup
import androidx.activity.ComponentActivity
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContracts
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import io.getstream.log.taggedLogger
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch

internal class PushNotificationPermissionRequester private constructor() : ActivityLifecycleCallbacks() {
private val logger by taggedLogger("Push:CurrentActivityProvider")
private val TAG = "PnPermissionRequester"
private val pushNotificationPermissionCallbacks = mutableListOf<PushNotificationPermissionCallback>()
private var currentActivity: Activity? = null
private val permissionContract = ActivityResultContracts.RequestPermission()
private val uiScope by lazy { CoroutineScope(Dispatchers.Main) }

fun addCallback(callback: PushNotificationPermissionCallback) {
logger.d { "[addCallback] callback: $callback" }
pushNotificationPermissionCallbacks.add(callback)
}

override fun onActivityCreated(
activity: Activity,
bunlde: Bundle?
) {
logger.v { "[onActivityCreated] activity: $activity" }
Log.v(TAG, "[onActivityCreated] activity: $activity")
super.onActivityCreated(activity, bunlde)
currentActivity = activity
}

override fun onActivityStarted(activity: Activity) {
logger.v { "[onActivityStarted] activity: $activity" }
Log.v(TAG, "[onActivityStarted] activity: $activity")
currentActivity = activity
activity.registerPermissionCallback()
super.onActivityStarted(activity)
}

override fun onActivityResumed(activity: Activity) {
logger.v { "[onActivityResumed] activity: $activity" }
Log.v(TAG, "[onActivityResumed] activity: $activity")
currentActivity = activity
super.onActivityResumed(activity)
}

override fun onActivityStopped(activity: Activity) {
logger.v { "[onActivityStopped] activity: $activity" }
Log.v(TAG, "[onActivityStopped] activity: $activity")
activity.unregisterPermissionCallback()
super.onActivityStopped(activity)
}

override fun onFirstActivityStarted(activity: Activity) {
logger.i { "[onFirstActivityStarted] activity: $activity" }
Log.i(TAG, "[onFirstActivityStarted] activity: $activity")
super.onFirstActivityStarted(activity)
pushNotificationPermissionCallbacks.forEach { it.onAppLaunched() }
}

override fun onLastActivityStopped(activity: Activity) {
logger.i { "[onLastActivityStopped] activity: $activity" }
Log.i(TAG, "[onLastActivityStopped] activity: $activity")
super.onLastActivityStopped(activity)
currentActivity = null
}

internal fun requestPermission() {
logger.d { "[requestPermission]" }
uiScope.launch { currentActivity?.requestPermission() }
}

internal fun onPermissionStatus(permissionStatus: NotificationPermissionStatus) {
logger.d { "[onPermissionStatus] permissionStatus: $permissionStatus" }
Log.v(TAG, "[onPermissionStatus] permissionStatus: $permissionStatus")
pushNotificationPermissionCallbacks.forEach { it.onPermissionStatusChanged(permissionStatus) }
}

private fun Activity.registerPermissionCallback() {
if (this !is ComponentActivity) return
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) return
logger.i { "[registerPermissionCallback] activity: ${this::class.simpleName}" }
Log.i(TAG, "[registerPermissionCallback] activity: ${this::class.simpleName}")
val launcher =
registerForActivityResult(permissionContract) { isGranted: Boolean ->
logger.v { "[registerPermissionCallback] completed: $isGranted" }
when (isGranted) {
true -> onPermissionStatus(NotificationPermissionStatus.GRANTED)
else -> onPermissionStatus(NotificationPermissionStatus.DENIED)
}
}
logger.v { "[registerPermissionCallback] launcher: $launcher" }
Log.v(TAG, "[registerPermissionCallback] launcher: $launcher")
putActivityResultLauncher(launcher)
}

private fun Activity.unregisterPermissionCallback() {
if (this !is ComponentActivity) return
logger.i { "[unregisterPermissionCallback] activity: ${this::class.simpleName}" }
Log.i(TAG, "[unregisterPermissionCallback] activity: ${this::class.simpleName}")
val launcher = getActivityResultLauncher()
logger.v { "[unregisterPermissionCallback] found launcher: $launcher" }
Log.d(TAG, "[unregisterPermissionCallback] found launcher: $launcher")
launcher?.unregister()
}

private fun Activity.requestPermission() {
logger.d { "[requestPermission] no args" }
when {
Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU -> {
logger.w { "[requestPermission] not supported on this version" }
Log.w(TAG, "[requestPermission] not supported on this version")
onPermissionStatus(NotificationPermissionStatus.GRANTED)
}
ContextCompat.checkSelfPermission(
this,
Manifest.permission.POST_NOTIFICATIONS
) == PackageManager.PERMISSION_GRANTED -> {
logger.v { "[requestPermission] already granted" }
Log.v(TAG, "[requestPermission] already granted")
onPermissionStatus(NotificationPermissionStatus.GRANTED)
}
ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.POST_NOTIFICATIONS) -> {
logger.i { "[requestPermission] rationale requested" }
Log.i(TAG, "[requestPermission] rationale requested")
onPermissionStatus(NotificationPermissionStatus.RATIONALE_NEEDED)
}
else -> {
val launcher = (this as? ComponentActivity)?.getActivityResultLauncher()
logger.i { "[requestPermission] launcher: $launcher" }
Log.i(TAG, "[requestPermission] launcher: $launcher")
launcher?.launch(Manifest.permission.POST_NOTIFICATIONS)
onPermissionStatus(NotificationPermissionStatus.REQUESTED)
}
Expand Down