OneSignal / OneSignal-Android-SDK

OneSignal is a free push notification service for mobile apps. This plugin makes it easy to integrate your native Android or Amazon app with OneSignal. https://onesignal.com
Other
605 stars 371 forks source link

[question]: I am not able to ask for notification permission on app start #2159

Open Kalo2412 opened 3 months ago

Kalo2412 commented 3 months ago

How can we help?

Description:

I have an Android Jetpack Compose App with indeed has a login page -> because of that I need to wait for a user to login and than retrieve the credentials together with the appID

Therefore here is my code

class MainActivity : ComponentActivity() {
                private val Context.dataStore by preferencesDataStore(name = "settings")
                override fun onCreate(savedInstanceState: Bundle?) {
                    super.onCreate(savedInstanceState)
                    val environmentManager = EnvironmentManager()
                    val dataStorageRepository = DataStorageRepository(dataStore)
                    val context = applicationContext

                    // Should be removed when releasing
                    OneSignal.Debug.logLevel = LogLevel.VERBOSE
                    OneSignal.initWithContext(context)

                    CoroutineScope(Dispatchers.IO).launch {
                        OneSignal.Notifications.requestPermission(true)
                    }

                    setContent {
                        ....
                    }
                }
            }

The problem is that as soon as I start the app I get in the logcat those errors

FATAL EXCEPTION: DefaultDispatcher-worker-3
Process: com.ts.org, PID: 32008
java.lang.Exception: Must call 'initWithContext' before use
        at com.onesignal.internal.OneSignalImp.getNotifications(OneSignalImp.kt:99)
        at com.onesignal.OneSignal.getNotifications(OneSignal.kt:62)
        at com.ts.org.app.host.MainActivity$onCreate$1.invokeSuspend(MainActivity.kt:53)
        at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
        at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:108)
        at kotlinx.coroutines.internal.LimitedDispatcher$Worker.run(LimitedDispatcher.kt:115)
        at kotlinx.coroutines.scheduling.TaskImpl.run(Tasks.kt:103)
        at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:584)
        at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:793)
        at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:697)
        at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:684)
        Suppressed: kotlinx.coroutines.internal.DiagnosticCoroutineContextException: [StandaloneCoroutine{Cancelling}@bb53738, Dispatchers.IO]

Furthermore, when a user is logged in - in another class I do this

fun subscribe(creds: ...., appID: String) {
        OneSignal.Debug.logLevel = LogLevel.VERBOSE
        OneSignal.initWithContext(context, appID)

        CoroutineScope(Dispatchers.IO).launch {
            val accepted = OneSignal.Notifications.requestPermission(true)
            if (accepted) {
                Log.i(TAG, "User accepted notifications")
                OneSignal.login(creds.userID)
            }
        }
    }

In the other class I never get the popup dialog for accepting the permissions for push notifications.
Version: 5.1.18 Question: What is wrong how can I proceed?

Code of Conduct

jkasten2 commented 3 months ago

@Kalo2412 to avoid the java.lang.Exception: Must call 'initWithContext' before use error and to prevent other initialization issues you should call OneSignal.initWithContext in your Application.onCreate instead of your Activity.onCreate.

Note that OneSignal.Notifications.requestPermission() only prompts on Android 13 and newer devices, as notifications are enabled by default on older devices. It's possible for all versions of Android to turn off notifications so calling OneSignal.Notifications.requestPermission(true) will take them to the settings if they turned it off.

Kalo2412 commented 3 months ago

I have now moved the logic in the MyApplication

** class MyApplication : Application() { override fun onCreate() { super.onCreate()

    // Initialize OneSignal
    OneSignal.Debug.logLevel = LogLevel.VERBOSE
    OneSignal.initWithContext(this)

    CoroutineScope(Dispatchers.IO).launch {
        OneSignal.Notifications.requestPermission(true)
    }
}

} **

I still get this error: FATAL EXCEPTION: DefaultDispatcher-worker-1 Process: com.ts.org, PID: 17941 java.lang.Exception: Must call 'initWithContext' before use at com.onesignal.internal.OneSignalImp.getNotifications(OneSignalImp.kt:99) at com.onesignal.OneSignal.getNotifications(OneSignal.kt:62) at com.ts.org.app.host.MyApplication$onCreate$1.invokeSuspend(MainApplication.kt:21) at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33) at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:108) at kotlinx.coroutines.internal.LimitedDispatcher$Worker.run(LimitedDispatcher.kt:115) at kotlinx.coroutines.scheduling.TaskImpl.run(Tasks.kt:103) at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:584) at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:793) at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:697) at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:684) Suppressed: kotlinx.coroutines.internal.DiagnosticCoroutineContextException: [StandaloneCoroutine{Cancelling}@c16b1d9, Dispatchers.IO]

Device is on Android 14

Kalo2412 commented 3 months ago

@jkasten2 What is the difference between this two methods

@kotlin.jvm.JvmStatic public final fun initWithContext(context: android.content.Context): kotlin.Boolean { /* compiled code */ }

@kotlin.jvm.JvmStatic public final fun initWithContext(context: android.content.Context, appId: kotlin.String): kotlin.Unit { /* compiled code */ }

Why should some one call initWithContext without to pass the appID if so can we pass the appid later in the application in some service class

Furthermore I do not find any docs page for the android sdk for the link provided in the README I receive page not found https://documentation.onesignal.com/docs/android-native-sdk

Kalo2412 commented 1 month ago

Any progress here?

jinliu9508 commented 3 weeks ago

Hello @Kalo2412, it looks like you are calling initWithContext with an empty app ID. The error "must call initWithContext before use" is expected when you try to access OneSignal without supplying a valid app ID.