Skip to content

Commit bbd6545

Browse files
authored
Merge pull request #1469 from OneSignal/fix/outside_package_target_activities
Fix outside package target activities (Launch URL) not opening when notification is tapped on
2 parents 9bd948b + 17f6340 commit bbd6545

File tree

6 files changed

+147
-39
lines changed

6 files changed

+147
-39
lines changed

OneSignalSDK/onesignal/src/main/AndroidManifest.xml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,9 +136,16 @@
136136
android:name="com.onesignal.NotificationOpenedReceiver"
137137
android:noHistory="true"
138138
android:excludeFromRecents="true"
139+
android:taskAffinity=""
139140
android:theme="@android:style/Theme.Translucent.NoTitleBar"
140141
android:exported="true" />
141142

143+
<activity
144+
android:name="com.onesignal.NotificationOpenedReceiverAndroid22AndOlder"
145+
android:noHistory="true"
146+
android:excludeFromRecents="true"
147+
android:theme="@android:style/Theme.Translucent.NoTitleBar"
148+
android:exported="true" />
142149
</application>
143150

144151
<!-- NOTE: See release version for tags with placeholders -->

OneSignalSDK/onesignal/src/main/java/com/onesignal/GenerateNotificationOpenIntent.kt

Lines changed: 40 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3,43 +3,66 @@ package com.onesignal
33
import android.app.PendingIntent
44
import android.content.Context
55
import android.content.Intent
6+
import androidx.annotation.RequiresApi
67

78
class GenerateNotificationOpenIntent(
89
private val context: Context,
910
private val intent: Intent?,
1011
private val startApp: Boolean
1112
) {
1213

13-
private val notificationOpenedClass: Class<*> = NotificationOpenedReceiver::class.java
14+
private val notificationOpenedClassAndroid23Plus: Class<*> = NotificationOpenedReceiver::class.java
15+
private val notificationOpenedClassAndroid22AndOlder: Class<*> = NotificationOpenedReceiverAndroid22AndOlder::class.java
1416

1517
fun getNewBaseIntent(
1618
notificationId: Int,
1719
): Intent {
20+
val intent =
21+
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M)
22+
getNewBaseIntentAndroidAPI23Plus()
23+
else
24+
getNewBaseIntentAndroidAPI22AndOlder()
25+
26+
return intent
27+
.putExtra(
28+
GenerateNotification.BUNDLE_KEY_ANDROID_NOTIFICATION_ID,
29+
notificationId
30+
)
1831
// We use SINGLE_TOP and CLEAR_TOP as we don't want more than one OneSignal invisible click
1932
// tracking Activity instance around.
20-
var intentFlags =
33+
.addFlags(
2134
Intent.FLAG_ACTIVITY_SINGLE_TOP or
2235
Intent.FLAG_ACTIVITY_CLEAR_TOP
23-
if (!startApp) {
24-
// If we don't want the app to launch we put OneSignal's invisible click tracking Activity on it's own task
25-
// so it doesn't resume an existing one once it closes.
26-
intentFlags =
27-
intentFlags or (
28-
Intent.FLAG_ACTIVITY_NEW_TASK or
29-
Intent.FLAG_ACTIVITY_MULTIPLE_TASK or
30-
Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET
31-
)
32-
}
36+
)
37+
}
3338

39+
@RequiresApi(android.os.Build.VERSION_CODES.M)
40+
private fun getNewBaseIntentAndroidAPI23Plus(): Intent {
3441
return Intent(
3542
context,
36-
notificationOpenedClass
43+
notificationOpenedClassAndroid23Plus
3744
)
38-
.putExtra(
39-
GenerateNotification.BUNDLE_KEY_ANDROID_NOTIFICATION_ID,
40-
notificationId
45+
}
46+
47+
// See NotificationOpenedReceiverAndroid22AndOlder.kt for details
48+
@Deprecated("Use getNewBaseIntentAndroidAPI23Plus instead for Android 6+")
49+
private fun getNewBaseIntentAndroidAPI22AndOlder(): Intent {
50+
val intent = Intent(
51+
context,
52+
notificationOpenedClassAndroid22AndOlder
4153
)
42-
.addFlags(intentFlags)
54+
55+
if (getIntentVisible() == null) {
56+
// If we don't show a visible Activity put OneSignal's invisible click tracking
57+
// Activity on it's own task so it doesn't resume an existing one once it closes.
58+
intent.addFlags(
59+
Intent.FLAG_ACTIVITY_NEW_TASK or
60+
Intent.FLAG_ACTIVITY_MULTIPLE_TASK or
61+
Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET
62+
)
63+
}
64+
65+
return intent
4366
}
4467

4568
/**
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/**
2+
* Modified MIT License
3+
*
4+
* Copyright 2021 OneSignal
5+
*
6+
* Permission is hereby granted, free of charge, to any person obtaining a copy
7+
* of this software and associated documentation files (the "Software"), to deal
8+
* in the Software without restriction, including without limitation the rights
9+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+
* copies of the Software, and to permit persons to whom the Software is
11+
* furnished to do so, subject to the following conditions:
12+
*
13+
* 1. The above copyright notice and this permission notice shall be included in
14+
* all copies or substantial portions of the Software.
15+
*
16+
* 2. All copies of substantial portions of the Software may only be used in connection
17+
* with services provided by OneSignal.
18+
*
19+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25+
* THE SOFTWARE.
26+
*/
27+
package com.onesignal
28+
29+
class NotificationOpenedReceiver : NotificationOpenedReceiverBase()
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/**
2+
* Modified MIT License
3+
*
4+
* Copyright 2021 OneSignal
5+
*
6+
* Permission is hereby granted, free of charge, to any person obtaining a copy
7+
* of this software and associated documentation files (the "Software"), to deal
8+
* in the Software without restriction, including without limitation the rights
9+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+
* copies of the Software, and to permit persons to whom the Software is
11+
* furnished to do so, subject to the following conditions:
12+
*
13+
* 1. The above copyright notice and this permission notice shall be included in
14+
* all copies or substantial portions of the Software.
15+
*
16+
* 2. All copies of substantial portions of the Software may only be used in connection
17+
* with services provided by OneSignal.
18+
*
19+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25+
* THE SOFTWARE.
26+
*/
27+
package com.onesignal
28+
29+
/**
30+
* This is the same as NotificationOpenedReceiver expect it doesn't contain
31+
* android:taskAffinity="" in it's AndroidManifest.xml entry. This is to
32+
* account for the resume behavior not working on Android API 22 and older.
33+
*
34+
* In Android 5.x and older, android:taskAffinity="" starts a new task as
35+
* expected, however the allowTaskReparenting behavior does not happen which
36+
* results in the app not resuming, when using reverse Activity trampoline.
37+
* Oddly enough cold starts of the app were not a problem.
38+
*/
39+
class NotificationOpenedReceiverAndroid22AndOlder : NotificationOpenedReceiverBase()
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/**
22
* Modified MIT License
33
*
4-
* Copyright 2017 OneSignal
4+
* Copyright 2021 OneSignal
55
*
66
* Permission is hereby granted, free of charge, to any person obtaining a copy
77
* of this software and associated documentation files (the "Software"), to deal
@@ -24,27 +24,22 @@
2424
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
2525
* THE SOFTWARE.
2626
*/
27+
package com.onesignal
2728

28-
package com.onesignal;
29+
import android.app.Activity
30+
import android.content.Intent
31+
import android.os.Bundle
2932

30-
import android.app.Activity;
31-
import android.content.Intent;
32-
import android.os.Bundle;
33-
34-
public class NotificationOpenedReceiver extends Activity {
35-
36-
@Override
37-
protected void onCreate(Bundle savedInstanceState) {
38-
super.onCreate(savedInstanceState);
39-
NotificationOpenedProcessor.processFromContext(this, getIntent());
40-
finish();
41-
}
42-
43-
@Override
44-
protected void onNewIntent(Intent intent) {
45-
super.onNewIntent(intent);
46-
NotificationOpenedProcessor.processFromContext(this, getIntent());
47-
finish();
48-
}
33+
abstract class NotificationOpenedReceiverBase : Activity() {
34+
override fun onCreate(savedInstanceState: Bundle?) {
35+
super.onCreate(savedInstanceState)
36+
NotificationOpenedProcessor.processFromContext(this, intent)
37+
finish()
38+
}
4939

40+
override fun onNewIntent(intent: Intent) {
41+
super.onNewIntent(intent)
42+
NotificationOpenedProcessor.processFromContext(this, getIntent())
43+
finish()
44+
}
5045
}

OneSignalSDK/unittest/src/test/java/com/test/onesignal/GenerateNotificationRunner.java

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1130,6 +1130,21 @@ public void shouldSetButtonsCorrectly() throws Exception {
11301130
assertEquals("id1", new JSONObject(json_data).optString(BUNDLE_KEY_ACTION_ID));
11311131
}
11321132

1133+
@Test
1134+
@Config(sdk = 23, shadows = { ShadowGenerateNotification.class })
1135+
public void shouldUseCorrectActivityForAndroid23Plus() throws Exception {
1136+
NotificationBundleProcessor_ProcessFromFCMIntentService(blankActivity, getBaseNotifBundle());
1137+
threadAndTaskWait();
1138+
1139+
Intent[] intents = lastNotificationIntents();
1140+
assertEquals("android.intent.action.MAIN", intents[0].getAction());
1141+
assertEquals(
1142+
com.onesignal.NotificationOpenedReceiver.class.getName(),
1143+
intents[1].getComponent().getClassName()
1144+
);
1145+
assertEquals(2, intents.length);
1146+
}
1147+
11331148
@Test
11341149
@Config(shadows = { ShadowGenerateNotification.class })
11351150
public void shouldSetContentIntentForLaunchURL() throws Exception {
@@ -1180,7 +1195,7 @@ private void generateNotificationWithLaunchURL() throws Exception {
11801195
}
11811196

11821197
private void assertNotificationOpenedReceiver(@NonNull Intent intent) {
1183-
assertEquals("com.onesignal.NotificationOpenedReceiver", intent.getComponent().getClassName());
1198+
assertEquals(com.onesignal.NotificationOpenedReceiverAndroid22AndOlder.class.getName(), intent.getComponent().getClassName());
11841199
}
11851200

11861201
private void assertOpenMainActivityIntent(@NonNull Intent intent) {

0 commit comments

Comments
 (0)