diff --git a/OneSignalSDK/onesignal/src/main/AndroidManifest.xml b/OneSignalSDK/onesignal/src/main/AndroidManifest.xml index 8cdd87ecc0..91482c8b43 100644 --- a/OneSignalSDK/onesignal/src/main/AndroidManifest.xml +++ b/OneSignalSDK/onesignal/src/main/AndroidManifest.xml @@ -136,9 +136,16 @@ android:name="com.onesignal.NotificationOpenedReceiver" android:noHistory="true" android:excludeFromRecents="true" + android:taskAffinity="" android:theme="@android:style/Theme.Translucent.NoTitleBar" android:exported="true" /> + diff --git a/OneSignalSDK/onesignal/src/main/java/com/onesignal/GenerateNotificationOpenIntent.kt b/OneSignalSDK/onesignal/src/main/java/com/onesignal/GenerateNotificationOpenIntent.kt index db6faefc37..8fb46098bd 100644 --- a/OneSignalSDK/onesignal/src/main/java/com/onesignal/GenerateNotificationOpenIntent.kt +++ b/OneSignalSDK/onesignal/src/main/java/com/onesignal/GenerateNotificationOpenIntent.kt @@ -3,6 +3,7 @@ package com.onesignal import android.app.PendingIntent import android.content.Context import android.content.Intent +import androidx.annotation.RequiresApi class GenerateNotificationOpenIntent( private val context: Context, @@ -10,36 +11,58 @@ class GenerateNotificationOpenIntent( private val startApp: Boolean ) { - private val notificationOpenedClass: Class<*> = NotificationOpenedReceiver::class.java + private val notificationOpenedClassAndroid23Plus: Class<*> = NotificationOpenedReceiver::class.java + private val notificationOpenedClassAndroid22AndOlder: Class<*> = NotificationOpenedReceiverAndroid22AndOlder::class.java fun getNewBaseIntent( notificationId: Int, ): Intent { + val intent = + if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) + getNewBaseIntentAndroidAPI23Plus() + else + getNewBaseIntentAndroidAPI22AndOlder() + + return intent + .putExtra( + GenerateNotification.BUNDLE_KEY_ANDROID_NOTIFICATION_ID, + notificationId + ) // We use SINGLE_TOP and CLEAR_TOP as we don't want more than one OneSignal invisible click // tracking Activity instance around. - var intentFlags = + .addFlags( Intent.FLAG_ACTIVITY_SINGLE_TOP or Intent.FLAG_ACTIVITY_CLEAR_TOP - if (!startApp) { - // If we don't want the app to launch we put OneSignal's invisible click tracking Activity on it's own task - // so it doesn't resume an existing one once it closes. - intentFlags = - intentFlags or ( - Intent.FLAG_ACTIVITY_NEW_TASK or - Intent.FLAG_ACTIVITY_MULTIPLE_TASK or - Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET - ) - } + ) + } + @RequiresApi(android.os.Build.VERSION_CODES.M) + private fun getNewBaseIntentAndroidAPI23Plus(): Intent { return Intent( context, - notificationOpenedClass + notificationOpenedClassAndroid23Plus ) - .putExtra( - GenerateNotification.BUNDLE_KEY_ANDROID_NOTIFICATION_ID, - notificationId + } + + // See NotificationOpenedReceiverAndroid22AndOlder.kt for details + @Deprecated("Use getNewBaseIntentAndroidAPI23Plus instead for Android 6+") + private fun getNewBaseIntentAndroidAPI22AndOlder(): Intent { + val intent = Intent( + context, + notificationOpenedClassAndroid22AndOlder ) - .addFlags(intentFlags) + + if (getIntentVisible() == null) { + // If we don't show a visible Activity put OneSignal's invisible click tracking + // Activity on it's own task so it doesn't resume an existing one once it closes. + intent.addFlags( + Intent.FLAG_ACTIVITY_NEW_TASK or + Intent.FLAG_ACTIVITY_MULTIPLE_TASK or + Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET + ) + } + + return intent } /** diff --git a/OneSignalSDK/onesignal/src/main/java/com/onesignal/NotificationOpenedReceiver.kt b/OneSignalSDK/onesignal/src/main/java/com/onesignal/NotificationOpenedReceiver.kt new file mode 100644 index 0000000000..c3d29de7bb --- /dev/null +++ b/OneSignalSDK/onesignal/src/main/java/com/onesignal/NotificationOpenedReceiver.kt @@ -0,0 +1,29 @@ +/** + * Modified MIT License + * + * Copyright 2021 OneSignal + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * 1. The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * 2. All copies of substantial portions of the Software may only be used in connection + * with services provided by OneSignal. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.onesignal + +class NotificationOpenedReceiver : NotificationOpenedReceiverBase() diff --git a/OneSignalSDK/onesignal/src/main/java/com/onesignal/NotificationOpenedReceiverAndroid22AndOlder.kt b/OneSignalSDK/onesignal/src/main/java/com/onesignal/NotificationOpenedReceiverAndroid22AndOlder.kt new file mode 100644 index 0000000000..9f446b063a --- /dev/null +++ b/OneSignalSDK/onesignal/src/main/java/com/onesignal/NotificationOpenedReceiverAndroid22AndOlder.kt @@ -0,0 +1,39 @@ +/** + * Modified MIT License + * + * Copyright 2021 OneSignal + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * 1. The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * 2. All copies of substantial portions of the Software may only be used in connection + * with services provided by OneSignal. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.onesignal + +/** + * This is the same as NotificationOpenedReceiver expect it doesn't contain + * android:taskAffinity="" in it's AndroidManifest.xml entry. This is to + * account for the resume behavior not working on Android API 22 and older. + * + * In Android 5.x and older, android:taskAffinity="" starts a new task as + * expected, however the allowTaskReparenting behavior does not happen which + * results in the app not resuming, when using reverse Activity trampoline. + * Oddly enough cold starts of the app were not a problem. + */ +class NotificationOpenedReceiverAndroid22AndOlder : NotificationOpenedReceiverBase() diff --git a/OneSignalSDK/onesignal/src/main/java/com/onesignal/NotificationOpenedReceiver.java b/OneSignalSDK/onesignal/src/main/java/com/onesignal/NotificationOpenedReceiverBase.kt similarity index 67% rename from OneSignalSDK/onesignal/src/main/java/com/onesignal/NotificationOpenedReceiver.java rename to OneSignalSDK/onesignal/src/main/java/com/onesignal/NotificationOpenedReceiverBase.kt index 4fc18fd5e3..585c650e2f 100644 --- a/OneSignalSDK/onesignal/src/main/java/com/onesignal/NotificationOpenedReceiver.java +++ b/OneSignalSDK/onesignal/src/main/java/com/onesignal/NotificationOpenedReceiverBase.kt @@ -1,7 +1,7 @@ /** * Modified MIT License * - * Copyright 2017 OneSignal + * Copyright 2021 OneSignal * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -24,27 +24,22 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ +package com.onesignal -package com.onesignal; +import android.app.Activity +import android.content.Intent +import android.os.Bundle -import android.app.Activity; -import android.content.Intent; -import android.os.Bundle; - -public class NotificationOpenedReceiver extends Activity { - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - NotificationOpenedProcessor.processFromContext(this, getIntent()); - finish(); - } - - @Override - protected void onNewIntent(Intent intent) { - super.onNewIntent(intent); - NotificationOpenedProcessor.processFromContext(this, getIntent()); - finish(); - } +abstract class NotificationOpenedReceiverBase : Activity() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + NotificationOpenedProcessor.processFromContext(this, intent) + finish() + } + override fun onNewIntent(intent: Intent) { + super.onNewIntent(intent) + NotificationOpenedProcessor.processFromContext(this, getIntent()) + finish() + } } \ No newline at end of file diff --git a/OneSignalSDK/unittest/src/test/java/com/test/onesignal/GenerateNotificationRunner.java b/OneSignalSDK/unittest/src/test/java/com/test/onesignal/GenerateNotificationRunner.java index 97f320924b..ad2212e423 100644 --- a/OneSignalSDK/unittest/src/test/java/com/test/onesignal/GenerateNotificationRunner.java +++ b/OneSignalSDK/unittest/src/test/java/com/test/onesignal/GenerateNotificationRunner.java @@ -1130,6 +1130,21 @@ public void shouldSetButtonsCorrectly() throws Exception { assertEquals("id1", new JSONObject(json_data).optString(BUNDLE_KEY_ACTION_ID)); } + @Test + @Config(sdk = 23, shadows = { ShadowGenerateNotification.class }) + public void shouldUseCorrectActivityForAndroid23Plus() throws Exception { + NotificationBundleProcessor_ProcessFromFCMIntentService(blankActivity, getBaseNotifBundle()); + threadAndTaskWait(); + + Intent[] intents = lastNotificationIntents(); + assertEquals("android.intent.action.MAIN", intents[0].getAction()); + assertEquals( + com.onesignal.NotificationOpenedReceiver.class.getName(), + intents[1].getComponent().getClassName() + ); + assertEquals(2, intents.length); + } + @Test @Config(shadows = { ShadowGenerateNotification.class }) public void shouldSetContentIntentForLaunchURL() throws Exception { @@ -1180,7 +1195,7 @@ private void generateNotificationWithLaunchURL() throws Exception { } private void assertNotificationOpenedReceiver(@NonNull Intent intent) { - assertEquals("com.onesignal.NotificationOpenedReceiver", intent.getComponent().getClassName()); + assertEquals(com.onesignal.NotificationOpenedReceiverAndroid22AndOlder.class.getName(), intent.getComponent().getClassName()); } private void assertOpenMainActivityIntent(@NonNull Intent intent) {