Skip to content

Commit

Permalink
fix: notification opening app for Android 12 (#301)
Browse files Browse the repository at this point in the history
  • Loading branch information
helenaford committed Jan 26, 2022
1 parent 4a3a97f commit ed22c8f
Show file tree
Hide file tree
Showing 18 changed files with 407 additions and 29 deletions.
8 changes: 8 additions & 0 deletions android/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,14 @@
android:name=".ReceiverService"
android:exported="false" />

<activity
android:name="app.notifee.core.NotificationReceiverActivity"
android:noHistory="true"
android:excludeFromRecents="true"
android:taskAffinity=""
android:theme="@android:style/Theme.Translucent.NoTitleBar"
android:exported="true" />

<!-- Foreground Service -->
<service
android:name=".ForegroundService"
Expand Down
56 changes: 43 additions & 13 deletions android/src/main/java/app/notifee/core/NotificationManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@

import static app.notifee.core.ContextHolder.getApplicationContext;
import static app.notifee.core.ReceiverService.ACTION_PRESS_INTENT;
import static app.notifee.core.event.NotificationEvent.TYPE_ACTION_PRESS;
import static app.notifee.core.event.NotificationEvent.TYPE_PRESS;
import static java.lang.Integer.parseInt;

import android.app.Notification;
Expand Down Expand Up @@ -101,13 +103,26 @@ private static Task<NotificationCompat.Builder> notificationBundleToBuilder(
ReceiverService.DELETE_INTENT,
new String[] {"notification"},
notificationModel.toBundle()));

builder.setContentIntent(
ReceiverService.createIntent(
ReceiverService.PRESS_INTENT,
new String[] {"notification", "pressAction"},
notificationModel.toBundle(),
androidModel.getPressAction()));
int targetSdkVersion =
ContextHolder.getApplicationContext().getApplicationInfo().targetSdkVersion;
if (targetSdkVersion >= Build.VERSION_CODES.S
&& Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
builder.setContentIntent(
NotificationPendingIntent.createIntent(
notificationModel.getHashCode(),
androidModel.getPressAction(),
TYPE_PRESS,
new String[] {"notification", "pressAction"},
notificationModel.toBundle(),
androidModel.getPressAction()));
} else {
builder.setContentIntent(
ReceiverService.createIntent(
ReceiverService.PRESS_INTENT,
new String[] {"notification", "pressAction"},
notificationModel.toBundle(),
androidModel.getPressAction()));
}

if (notificationModel.getTitle() != null) {
builder.setContentTitle(TextUtils.fromHtml(notificationModel.getTitle()));
Expand Down Expand Up @@ -326,12 +341,27 @@ private static Task<NotificationCompat.Builder> notificationBundleToBuilder(
}

for (NotificationAndroidActionModel actionBundle : actionBundles) {
PendingIntent pendingIntent =
ReceiverService.createIntent(
ACTION_PRESS_INTENT,
new String[] {"notification", "pressAction"},
notificationModel.toBundle(),
actionBundle.getPressAction().toBundle());
PendingIntent pendingIntent = null;
int targetSdkVersion =
ContextHolder.getApplicationContext().getApplicationInfo().targetSdkVersion;
if (targetSdkVersion >= Build.VERSION_CODES.S
&& Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
pendingIntent =
NotificationPendingIntent.createIntent(
notificationModel.getHashCode(),
actionBundle.getPressAction().toBundle(),
TYPE_ACTION_PRESS,
new String[] {"notification", "pressAction"},
notificationModel.toBundle(),
actionBundle.getPressAction().toBundle());
} else {
pendingIntent =
ReceiverService.createIntent(
ACTION_PRESS_INTENT,
new String[] {"notification", "pressAction"},
notificationModel.toBundle(),
actionBundle.getPressAction().toBundle());
}

String icon = actionBundle.getIcon();
Bitmap iconBitmap = null;
Expand Down
160 changes: 160 additions & 0 deletions android/src/main/java/app/notifee/core/NotificationPendingIntent.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
package app.notifee.core;

/*
* Copyright (c) 2016-present Invertase Limited & Contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this library except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/

import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import app.notifee.core.event.MainComponentEvent;
import app.notifee.core.model.NotificationAndroidPressActionModel;
import app.notifee.core.utility.IntentUtils;
import java.util.concurrent.atomic.AtomicInteger;

public class NotificationPendingIntent {
public static final String EVENT_TYPE_INTENT_KEY = "notifee_event_type";
public static final String NOTIFICATION_ID_INTENT_KEY = "notification_id";
private static final AtomicInteger uniqueIds = new AtomicInteger(0);
private static final String TAG = "NotificationPendingIntent";

/**
* Creates a PendingIntent, which when sent triggers this class.
*
* @param notificationId int
* @param pressActionModelBundle NotificationAndroidPressActionModel.
* @param extraKeys Array of strings
* @param extraBundles One or more bundles
*/
static PendingIntent createIntent(
int notificationId,
Bundle pressActionModelBundle,
int eventType,
String[] extraKeys,
Bundle... extraBundles) {
Context context = ContextHolder.getApplicationContext();

// Get launch activity intent
Intent launchActivityIntent = null;
if (pressActionModelBundle != null) {
launchActivityIntent =
createLaunchActivityIntent(
context,
notificationId,
NotificationAndroidPressActionModel.fromBundle(pressActionModelBundle));
}

// Create an activity to receive notification events
Intent receiverIntent = new Intent(context, NotificationReceiverActivity.class);

// Set extras for each intent
setIntentExtras(launchActivityIntent, eventType, notificationId, extraKeys, extraBundles);
setIntentExtras(receiverIntent, eventType, notificationId, extraKeys, extraBundles);

// Create pending intent with activities
int uniqueInt = uniqueIds.getAndIncrement();
Intent[] intents;

if (launchActivityIntent != null) {
intents = new Intent[2];
intents[0] = launchActivityIntent;

receiverIntent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP);
intents[1] = receiverIntent;
} else {
intents = new Intent[1];
receiverIntent.setFlags(
Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_MULTIPLE_TASK
| Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);

intents[0] = receiverIntent;
}

return PendingIntent.getActivities(
context,
uniqueInt,
intents,
PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_MUTABLE);
}

static void setIntentExtras(
Intent intent,
int eventType,
int notificationId,
String[] extraKeys,
Bundle... extraBundles) {
if (intent == null) {
return;
}

intent.putExtra(EVENT_TYPE_INTENT_KEY, eventType);
intent.putExtra(NOTIFICATION_ID_INTENT_KEY, notificationId);

for (int i = 0; i < extraKeys.length; i++) {
String key = extraKeys[i];

if (i <= extraBundles.length - 1) {
Bundle bundle = extraBundles[i];
intent.putExtra(key, bundle);
} else {
intent.putExtra(key, (String) null);
}
}
}

static Intent createLaunchActivityIntent(
Context context, int notificationId, NotificationAndroidPressActionModel pressActionModel) {
try {
Intent launchActivityIntent =
context.getPackageManager().getLaunchIntentForPackage(context.getPackageName());

String launchActivity = null;
if (pressActionModel != null) {
launchActivity = pressActionModel.getLaunchActivity();
}

if (launchActivityIntent == null && launchActivity != null) {
Class<?> launchActivityClass = IntentUtils.getLaunchActivity(launchActivity);
launchActivityIntent = new Intent(context, launchActivityClass);

launchActivityIntent.setPackage(null);

launchActivityIntent.setFlags(
Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
}

if (pressActionModel.getLaunchActivityFlags() != -1) {
launchActivityIntent.setFlags(pressActionModel.getLaunchActivityFlags());
}

if (pressActionModel.getMainComponent() != null) {
launchActivityIntent.putExtra("mainComponent", pressActionModel.getMainComponent());
EventBus.postSticky(new MainComponentEvent(pressActionModel.getMainComponent()));
}

return launchActivityIntent;
} catch (Exception e) {
Logger.e(
"NotificationPendingIntent",
"Failed to create LaunchActivityIntent for notification " + notificationId,
e);
}

return null;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package app.notifee.core;

/*
* Copyright (c) 2016-present Invertase Limited & Contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this library except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;

public class NotificationReceiverActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
NotificationReceiverHandler.handleNotification(this, getIntent());
finish();
}

@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
NotificationReceiverHandler.handleNotification(this, intent);
finish();
}
}

0 comments on commit ed22c8f

Please sign in to comment.