Skip to content

Commit fbe8d87

Browse files
authored
fix: missing pending intents mutability for Android 12+ (#1139)
1 parent 8d9691e commit fbe8d87

File tree

4 files changed

+185
-10
lines changed

4 files changed

+185
-10
lines changed

parse/build.gradle

+1-1
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ tasks.withType(Test) {
8181
jacoco.includeNoLocationClasses = true
8282
jacoco.excludes = ['jdk.internal.*']
8383
testLogging {
84-
events "passed", "skipped", "failed", "standardOut", "standardError"
84+
events "failed"
8585
}
8686
}
8787

parse/src/main/java/com/parse/ParseCommandCache.java

+3-1
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,9 @@ public static int getPendingCount() {
144144
public void onDestroy() {
145145
// TODO (grantland): pause #6484855
146146

147-
notifier.removeListener(listener);
147+
if (notifier != null) {
148+
notifier.removeListener(listener);
149+
}
148150
}
149151

150152
// Set the maximum number of times to retry before assuming disconnection.

parse/src/main/java/com/parse/ParsePushBroadcastReceiver.java

+7-8
Original file line numberDiff line numberDiff line change
@@ -426,18 +426,17 @@ protected NotificationCompat.Builder getNotification(Context context, Intent int
426426

427427
Intent deleteIntent = getDeleteIntent(extras, packageName);
428428

429+
int pendingIntentFlags =
430+
Build.VERSION.SDK_INT >= Build.VERSION_CODES.R
431+
? PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE
432+
: PendingIntent.FLAG_UPDATE_CURRENT;
433+
429434
PendingIntent pContentIntent =
430435
PendingIntent.getBroadcast(
431-
context,
432-
contentIntentRequestCode,
433-
contentIntent,
434-
PendingIntent.FLAG_UPDATE_CURRENT);
436+
context, contentIntentRequestCode, contentIntent, pendingIntentFlags);
435437
PendingIntent pDeleteIntent =
436438
PendingIntent.getBroadcast(
437-
context,
438-
deleteIntentRequestCode,
439-
deleteIntent,
440-
PendingIntent.FLAG_UPDATE_CURRENT);
439+
context, deleteIntentRequestCode, deleteIntent, pendingIntentFlags);
441440

442441
String channelId = null;
443442
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
1+
package com.parse;
2+
3+
import static androidx.core.app.NotificationCompat.EXTRA_TEXT;
4+
import static androidx.core.app.NotificationCompat.EXTRA_TITLE;
5+
import static org.junit.Assert.assertEquals;
6+
import static org.junit.Assert.assertNotNull;
7+
import static org.junit.Assert.assertNull;
8+
import static org.mockito.Mockito.mock;
9+
import static org.mockito.Mockito.when;
10+
11+
import android.content.Intent;
12+
import androidx.core.app.NotificationCompat;
13+
import java.util.HashMap;
14+
import java.util.Map;
15+
import org.json.JSONObject;
16+
import org.junit.After;
17+
import org.junit.Before;
18+
import org.junit.Test;
19+
import org.junit.runner.RunWith;
20+
import org.robolectric.RobolectricTestRunner;
21+
import org.robolectric.RuntimeEnvironment;
22+
23+
@RunWith(RobolectricTestRunner.class)
24+
public class ParsePushBroadcastReceiverTest extends ResetPluginsParseTest {
25+
26+
@Before
27+
public void setUp() throws Exception {
28+
super.setUp();
29+
30+
Parse.Configuration configuration =
31+
new Parse.Configuration.Builder(RuntimeEnvironment.application)
32+
.applicationId(BuildConfig.LIBRARY_PACKAGE_NAME)
33+
.server("https://api.parse.com/1")
34+
.build();
35+
36+
ParsePlugins plugins = mock(ParsePlugins.class);
37+
when(plugins.configuration()).thenReturn(configuration);
38+
when(plugins.applicationContext()).thenReturn(RuntimeEnvironment.application);
39+
Parse.initialize(configuration, plugins);
40+
}
41+
42+
@After
43+
public void tearDown() throws Exception {
44+
super.tearDown();
45+
ParseCorePlugins.getInstance().reset();
46+
ParsePlugins.reset();
47+
Parse.destroy();
48+
}
49+
50+
@Test
51+
public void testBuildNotification() {
52+
final ParsePushBroadcastReceiver broadcastReceiver = new ParsePushBroadcastReceiver();
53+
final Map<String, String> map = new HashMap();
54+
map.put("alert", "alert");
55+
map.put("title", "title");
56+
57+
final String notificationPayload = new JSONObject(map).toString();
58+
59+
final Intent intent = new Intent();
60+
intent.putExtra(ParsePushBroadcastReceiver.KEY_PUSH_DATA, notificationPayload);
61+
62+
final NotificationCompat.Builder notification =
63+
broadcastReceiver.getNotification(
64+
RuntimeEnvironment.getApplication().getApplicationContext(), intent);
65+
66+
assertNotNull(notification);
67+
}
68+
69+
@Test
70+
public void testBuildNotificationReturnsNullOnInvalidPayload() {
71+
final ParsePushBroadcastReceiver broadcastReceiver = new ParsePushBroadcastReceiver();
72+
final Intent intent = new Intent();
73+
intent.putExtra(ParsePushBroadcastReceiver.KEY_PUSH_DATA, "{\"json\": broken json}");
74+
75+
final NotificationCompat.Builder notification =
76+
broadcastReceiver.getNotification(
77+
RuntimeEnvironment.getApplication().getApplicationContext(), intent);
78+
79+
assertNull(notification);
80+
}
81+
82+
@Test
83+
public void testBuildNotificationReturnsNullOnMissingTitleAndAlert() {
84+
final ParsePushBroadcastReceiver broadcastReceiver = new ParsePushBroadcastReceiver();
85+
final Map<String, String> map = new HashMap();
86+
87+
final String notificationPayload = new JSONObject(map).toString();
88+
89+
final Intent intent = new Intent();
90+
intent.putExtra(ParsePushBroadcastReceiver.KEY_PUSH_DATA, notificationPayload);
91+
92+
final NotificationCompat.Builder notification =
93+
broadcastReceiver.getNotification(
94+
RuntimeEnvironment.getApplication().getApplicationContext(), intent);
95+
96+
assertNull(notification);
97+
}
98+
99+
@Test
100+
public void testNotificationBuilderWhenAlertNotProvidedSetFallback() {
101+
final ParsePushBroadcastReceiver broadcastReceiver = new ParsePushBroadcastReceiver();
102+
final Map<String, String> map = new HashMap();
103+
map.put("title", "title");
104+
105+
final String notificationPayload = new JSONObject(map).toString();
106+
107+
final Intent intent = new Intent();
108+
intent.putExtra(ParsePushBroadcastReceiver.KEY_PUSH_DATA, notificationPayload);
109+
110+
final NotificationCompat.Builder notification =
111+
broadcastReceiver.getNotification(
112+
RuntimeEnvironment.getApplication().getApplicationContext(), intent);
113+
114+
assertNotNull(notification);
115+
assertEquals("Notification received.", notification.build().extras.getString(EXTRA_TEXT));
116+
}
117+
118+
@Test
119+
public void testNotificationBuilderWhenAlertIsSetWhenProvided() {
120+
final ParsePushBroadcastReceiver broadcastReceiver = new ParsePushBroadcastReceiver();
121+
final Map<String, String> map = new HashMap();
122+
map.put("alert", "This is an alert");
123+
124+
final String notificationPayload = new JSONObject(map).toString();
125+
126+
final Intent intent = new Intent();
127+
intent.putExtra(ParsePushBroadcastReceiver.KEY_PUSH_DATA, notificationPayload);
128+
129+
final NotificationCompat.Builder notification =
130+
broadcastReceiver.getNotification(
131+
RuntimeEnvironment.getApplication().getApplicationContext(), intent);
132+
133+
assertNotNull(notification);
134+
assertEquals("This is an alert", notification.build().extras.getString(EXTRA_TEXT));
135+
}
136+
137+
@Test
138+
public void testNotificationBuilderWhenTitleNotProvidedSetFallback() {
139+
final ParsePushBroadcastReceiver broadcastReceiver = new ParsePushBroadcastReceiver();
140+
final Map<String, String> map = new HashMap();
141+
map.put("alert", "alert");
142+
143+
final String notificationPayload = new JSONObject(map).toString();
144+
145+
final Intent intent = new Intent();
146+
intent.putExtra(ParsePushBroadcastReceiver.KEY_PUSH_DATA, notificationPayload);
147+
148+
final NotificationCompat.Builder notification =
149+
broadcastReceiver.getNotification(
150+
RuntimeEnvironment.getApplication().getApplicationContext(), intent);
151+
152+
assertNotNull(notification);
153+
assertEquals("com.parse.test", notification.build().extras.getString(EXTRA_TITLE));
154+
}
155+
156+
@Test
157+
public void testNotificationBuilderWhenTitleIsSetWhenProvided() {
158+
final ParsePushBroadcastReceiver broadcastReceiver = new ParsePushBroadcastReceiver();
159+
final Map<String, String> map = new HashMap();
160+
map.put("title", "Application name");
161+
162+
final String notificationPayload = new JSONObject(map).toString();
163+
164+
final Intent intent = new Intent();
165+
intent.putExtra(ParsePushBroadcastReceiver.KEY_PUSH_DATA, notificationPayload);
166+
167+
final NotificationCompat.Builder notification =
168+
broadcastReceiver.getNotification(
169+
RuntimeEnvironment.getApplication().getApplicationContext(), intent);
170+
171+
assertNotNull(notification);
172+
assertEquals("Application name", notification.build().extras.getString(EXTRA_TITLE));
173+
}
174+
}

0 commit comments

Comments
 (0)