Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: missing pending intents mutability for Android 12+ #1139

Merged
merged 7 commits into from
Nov 16, 2021
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
2 changes: 1 addition & 1 deletion parse/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ tasks.withType(Test) {
jacoco.includeNoLocationClasses = true
jacoco.excludes = ['jdk.internal.*']
testLogging {
events "passed", "skipped", "failed", "standardOut", "standardError"
events "failed"
}
}

Expand Down
4 changes: 3 additions & 1 deletion parse/src/main/java/com/parse/ParseCommandCache.java
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,9 @@ public static int getPendingCount() {
public void onDestroy() {
// TODO (grantland): pause #6484855

notifier.removeListener(listener);
if (notifier != null) {
notifier.removeListener(listener);
}
}

// Set the maximum number of times to retry before assuming disconnection.
Expand Down
15 changes: 7 additions & 8 deletions parse/src/main/java/com/parse/ParsePushBroadcastReceiver.java
Original file line number Diff line number Diff line change
Expand Up @@ -426,18 +426,17 @@ protected NotificationCompat.Builder getNotification(Context context, Intent int

Intent deleteIntent = getDeleteIntent(extras, packageName);

int pendingIntentFlags =
Build.VERSION.SDK_INT >= Build.VERSION_CODES.R
? PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE
: PendingIntent.FLAG_UPDATE_CURRENT;

PendingIntent pContentIntent =
PendingIntent.getBroadcast(
context,
contentIntentRequestCode,
contentIntent,
PendingIntent.FLAG_UPDATE_CURRENT);
context, contentIntentRequestCode, contentIntent, pendingIntentFlags);
PendingIntent pDeleteIntent =
PendingIntent.getBroadcast(
context,
deleteIntentRequestCode,
deleteIntent,
PendingIntent.FLAG_UPDATE_CURRENT);
context, deleteIntentRequestCode, deleteIntent, pendingIntentFlags);

String channelId = null;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
Expand Down
174 changes: 174 additions & 0 deletions parse/src/test/java/com/parse/ParsePushBroadcastReceiverTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
package com.parse;

import static androidx.core.app.NotificationCompat.EXTRA_TEXT;
import static androidx.core.app.NotificationCompat.EXTRA_TITLE;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

import android.content.Intent;
import androidx.core.app.NotificationCompat;
import java.util.HashMap;
import java.util.Map;
import org.json.JSONObject;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;

@RunWith(RobolectricTestRunner.class)
public class ParsePushBroadcastReceiverTest extends ResetPluginsParseTest {

@Before
public void setUp() throws Exception {
super.setUp();

Parse.Configuration configuration =
new Parse.Configuration.Builder(RuntimeEnvironment.application)
.applicationId(BuildConfig.LIBRARY_PACKAGE_NAME)
.server("https://api.parse.com/1")
.build();

ParsePlugins plugins = mock(ParsePlugins.class);
when(plugins.configuration()).thenReturn(configuration);
when(plugins.applicationContext()).thenReturn(RuntimeEnvironment.application);
Parse.initialize(configuration, plugins);
}

@After
public void tearDown() throws Exception {
super.tearDown();
ParseCorePlugins.getInstance().reset();
ParsePlugins.reset();
Parse.destroy();
}

@Test
public void testBuildNotification() {
final ParsePushBroadcastReceiver broadcastReceiver = new ParsePushBroadcastReceiver();
final Map<String, String> map = new HashMap();
map.put("alert", "alert");
map.put("title", "title");

final String notificationPayload = new JSONObject(map).toString();

final Intent intent = new Intent();
intent.putExtra(ParsePushBroadcastReceiver.KEY_PUSH_DATA, notificationPayload);

final NotificationCompat.Builder notification =
broadcastReceiver.getNotification(
RuntimeEnvironment.getApplication().getApplicationContext(), intent);

assertNotNull(notification);
}

@Test
public void testBuildNotificationReturnsNullOnInvalidPayload() {
final ParsePushBroadcastReceiver broadcastReceiver = new ParsePushBroadcastReceiver();
final Intent intent = new Intent();
intent.putExtra(ParsePushBroadcastReceiver.KEY_PUSH_DATA, "{\"json\": broken json}");

final NotificationCompat.Builder notification =
broadcastReceiver.getNotification(
RuntimeEnvironment.getApplication().getApplicationContext(), intent);

assertNull(notification);
}

@Test
public void testBuildNotificationReturnsNullOnMissingTitleAndAlert() {
final ParsePushBroadcastReceiver broadcastReceiver = new ParsePushBroadcastReceiver();
final Map<String, String> map = new HashMap();

final String notificationPayload = new JSONObject(map).toString();

final Intent intent = new Intent();
intent.putExtra(ParsePushBroadcastReceiver.KEY_PUSH_DATA, notificationPayload);

final NotificationCompat.Builder notification =
broadcastReceiver.getNotification(
RuntimeEnvironment.getApplication().getApplicationContext(), intent);

assertNull(notification);
}

@Test
public void testNotificationBuilderWhenAlertNotProvidedSetFallback() {
final ParsePushBroadcastReceiver broadcastReceiver = new ParsePushBroadcastReceiver();
final Map<String, String> map = new HashMap();
map.put("title", "title");

final String notificationPayload = new JSONObject(map).toString();

final Intent intent = new Intent();
intent.putExtra(ParsePushBroadcastReceiver.KEY_PUSH_DATA, notificationPayload);

final NotificationCompat.Builder notification =
broadcastReceiver.getNotification(
RuntimeEnvironment.getApplication().getApplicationContext(), intent);

assertNotNull(notification);
assertEquals("Notification received.", notification.build().extras.getString(EXTRA_TEXT));
}

@Test
public void testNotificationBuilderWhenAlertIsSetWhenProvided() {
final ParsePushBroadcastReceiver broadcastReceiver = new ParsePushBroadcastReceiver();
final Map<String, String> map = new HashMap();
map.put("alert", "This is an alert");

final String notificationPayload = new JSONObject(map).toString();

final Intent intent = new Intent();
intent.putExtra(ParsePushBroadcastReceiver.KEY_PUSH_DATA, notificationPayload);

final NotificationCompat.Builder notification =
broadcastReceiver.getNotification(
RuntimeEnvironment.getApplication().getApplicationContext(), intent);

assertNotNull(notification);
assertEquals("This is an alert", notification.build().extras.getString(EXTRA_TEXT));
}

@Test
public void testNotificationBuilderWhenTitleNotProvidedSetFallback() {
final ParsePushBroadcastReceiver broadcastReceiver = new ParsePushBroadcastReceiver();
final Map<String, String> map = new HashMap();
map.put("alert", "alert");

final String notificationPayload = new JSONObject(map).toString();

final Intent intent = new Intent();
intent.putExtra(ParsePushBroadcastReceiver.KEY_PUSH_DATA, notificationPayload);

final NotificationCompat.Builder notification =
broadcastReceiver.getNotification(
RuntimeEnvironment.getApplication().getApplicationContext(), intent);

assertNotNull(notification);
assertEquals("com.parse.test", notification.build().extras.getString(EXTRA_TITLE));
}

@Test
public void testNotificationBuilderWhenTitleIsSetWhenProvided() {
final ParsePushBroadcastReceiver broadcastReceiver = new ParsePushBroadcastReceiver();
final Map<String, String> map = new HashMap();
map.put("title", "Application name");

final String notificationPayload = new JSONObject(map).toString();

final Intent intent = new Intent();
intent.putExtra(ParsePushBroadcastReceiver.KEY_PUSH_DATA, notificationPayload);

final NotificationCompat.Builder notification =
broadcastReceiver.getNotification(
RuntimeEnvironment.getApplication().getApplicationContext(), intent);

assertNotNull(notification);
assertEquals("Application name", notification.build().extras.getString(EXTRA_TITLE));
}
}