Android 在版本 S+ 中创建通知时应用崩溃
Android app crashing while creating notifications in Version S+
我在我的应用程序中使用通知已经有一段时间了,一切正常,直到我最近定位到 android 12。现在,当我在 android 12 上收到通知时,我的应用程序崩溃了。但在 android 12 台设备上一切正常。这是我到目前为止尝试过的方法。
AlarmReceiver.java
public class AlarmReceiver extends BroadcastReceiver {
private static final String CHANNEL_ID = "1";
private static final String CHANNEL_NAME = "Notifications";
@Override
public void onReceive(Context context, Intent intent) {
// For android 8 and above
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
NotificationChannel channel = new NotificationChannel(CHANNEL_ID, CHANNEL_NAME, NotificationManager.IMPORTANCE_HIGH);
channel.setDescription(context.getString(R.string.notifications));
channel.enableLights(true);
channel.enableVibration(true);
channel.setLightColor(Color.RED);
channel.setShowBadge(true);
channel.setLockscreenVisibility(NotificationCompat.VISIBILITY_PUBLIC); //Show notification on lock screen
NotificationManager manager = context.getSystemService(NotificationManager.class);
assert manager != null;
manager.createNotificationChannel(channel);
}
Cursor cursor = new DatabaseHelper(context).generateNotification();
if (cursor.moveToFirst()) {
// Create an Intent for the activity you want to start
Intent newIntent = new Intent(context, MainActivity.class);
newIntent.putExtra(Constants.STRING_EXTRA_INCOMING_ACTIVITY, Constants.ACTIVITY_NOTIFICATION);
newIntent.putExtra(Constants.STRING_EXTRA_QUOTE, cursor.getString(1));
// on back pressed go back to main activity
TaskStackBuilder stackBuilder = TaskStackBuilder.create(context);
stackBuilder.addNextIntentWithParentStack(newIntent);
PendingIntent pendingIntent = stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
// Build Notification
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(context, CHANNEL_ID)
.setSmallIcon(R.drawable.ic_notification)
.setColor(Color.parseColor("#ffa000"))
.setContentTitle(context.getString(R.string.notifications))
.setContentText(Html.fromHtml(cursor.getString(1)))//builds the title from columns of the selected row
.setContentIntent(pendingIntent) // On Notification Click Goto DetailActivity
.setDefaults(NotificationCompat.DEFAULT_ALL)
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
.setAutoCancel(true);
NotificationManagerCompat managerCompat = NotificationManagerCompat.from(context);
managerCompat.notify(1, mBuilder.build());
} else {
Toast.makeText(context, "Unable To Generate Notification", Toast.LENGTH_LONG).show();
}
cursor.close();
}
}
这是在我的 MainActivity 中显示通知的代码
Intent intent = new Intent(this, AlarmReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(this,
0, intent, PendingIntent.FLAG_IMMUTABLE);
AlarmManager alarms = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
Calendar calendar = Calendar.getInstance();
Calendar now = Calendar.getInstance();
calendar.set(Calendar.HOUR_OF_DAY, 8);
calendar.set(Calendar.MINUTE, 10);
if (now.after(calendar)) {
calendar.add(Calendar.DATE, 1);
}
if (alarms != null) {
alarms.setInexactRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(),
AlarmManager.INTERVAL_DAY, pendingIntent);
}
}
这是我在 firebase 上收到的崩溃报告
Fatal Exception: java.lang.RuntimeException: Unable to start receiver com.example.app.receiver.AlarmReceiver: java.lang.IllegalArgumentException: com.example.app: Targeting S+ (version 31 and above) requires that one of FLAG_IMMUTABLE or FLAG_MUTABLE be specified when creating a PendingIntent.
Strongly consider using FLAG_IMMUTABLE, only use FLAG_MUTABLE if some functionality depends on the PendingIntent being mutable, e.g. if it needs to be used with inline replies or bubbles.
at android.app.ActivityThread.handleReceiver(ActivityThread.java:4766)
at android.app.ActivityThread.access00(ActivityThread.java:310)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2288)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loopOnce(Looper.java:226)
at android.os.Looper.loop(Looper.java:313)
at android.app.ActivityThread.main(ActivityThread.java:8611)
at java.lang.reflect.Method.invoke(Method.java)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:563)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1133)
Caused by java.lang.IllegalArgumentException: com.example.app: Targeting S+ (version 31 and above) requires that one of FLAG_IMMUTABLE or FLAG_MUTABLE be specified when creating a PendingIntent.
Strongly consider using FLAG_IMMUTABLE, only use FLAG_MUTABLE if some functionality depends on the PendingIntent being mutable, e.g. if it needs to be used with inline replies or bubbles.
at android.app.PendingIntent.checkFlags(PendingIntent.java:382)
at android.app.PendingIntent.getActivitiesAsUser(PendingIntent.java:616)
at android.app.PendingIntent.getActivities(PendingIntent.java:598)
at androidx.core.app.TaskStackBuilder.getPendingIntent(TaskStackBuilder.java:341)
at androidx.core.app.TaskStackBuilder.getPendingIntent(TaskStackBuilder.java:312)
at com.example.app.receiver.AlarmReceiver.onReceive(AlarmReceiver.java:58)
at android.app.ActivityThread.handleReceiver(ActivityThread.java:4757)
at android.app.ActivityThread.access00(ActivityThread.java:310)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2288)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loopOnce(Looper.java:226)
at android.os.Looper.loop(Looper.java:313)
at android.app.ActivityThread.main(ActivityThread.java:8611)
at java.lang.reflect.Method.invoke(Method.java)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:563)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1133)
根据官方文档“如果您的应用面向 Android 12,您必须指定您的应用创建的每个 PendingIntent 对象的可变性。此附加要求提高了您应用的安全性。"
Intent notificationIntent = new Intent(getApplicationContext(), MainActivity.class);
PendingIntent contentIntent = PendingIntent.getActivity(context,NOTIFICATION_REQUEST_CODE, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);
我们正在构建一个标准类型的 Intent 来打开我们的应用程序,然后简单地将其包装在 PendingIntent 中,然后再将其添加到我们的 notification.In 这种情况下,因为我们有一个确切的动作,我们知道我们想要执行,我们构建一个 PendingIntent,我们通过使用名为 FLAG_IMMUTABLE.
的标志,将其传递给的应用程序无法对其进行修改
我在我的应用程序中使用通知已经有一段时间了,一切正常,直到我最近定位到 android 12。现在,当我在 android 12 上收到通知时,我的应用程序崩溃了。但在 android 12 台设备上一切正常。这是我到目前为止尝试过的方法。
AlarmReceiver.java
public class AlarmReceiver extends BroadcastReceiver {
private static final String CHANNEL_ID = "1";
private static final String CHANNEL_NAME = "Notifications";
@Override
public void onReceive(Context context, Intent intent) {
// For android 8 and above
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
NotificationChannel channel = new NotificationChannel(CHANNEL_ID, CHANNEL_NAME, NotificationManager.IMPORTANCE_HIGH);
channel.setDescription(context.getString(R.string.notifications));
channel.enableLights(true);
channel.enableVibration(true);
channel.setLightColor(Color.RED);
channel.setShowBadge(true);
channel.setLockscreenVisibility(NotificationCompat.VISIBILITY_PUBLIC); //Show notification on lock screen
NotificationManager manager = context.getSystemService(NotificationManager.class);
assert manager != null;
manager.createNotificationChannel(channel);
}
Cursor cursor = new DatabaseHelper(context).generateNotification();
if (cursor.moveToFirst()) {
// Create an Intent for the activity you want to start
Intent newIntent = new Intent(context, MainActivity.class);
newIntent.putExtra(Constants.STRING_EXTRA_INCOMING_ACTIVITY, Constants.ACTIVITY_NOTIFICATION);
newIntent.putExtra(Constants.STRING_EXTRA_QUOTE, cursor.getString(1));
// on back pressed go back to main activity
TaskStackBuilder stackBuilder = TaskStackBuilder.create(context);
stackBuilder.addNextIntentWithParentStack(newIntent);
PendingIntent pendingIntent = stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
// Build Notification
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(context, CHANNEL_ID)
.setSmallIcon(R.drawable.ic_notification)
.setColor(Color.parseColor("#ffa000"))
.setContentTitle(context.getString(R.string.notifications))
.setContentText(Html.fromHtml(cursor.getString(1)))//builds the title from columns of the selected row
.setContentIntent(pendingIntent) // On Notification Click Goto DetailActivity
.setDefaults(NotificationCompat.DEFAULT_ALL)
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
.setAutoCancel(true);
NotificationManagerCompat managerCompat = NotificationManagerCompat.from(context);
managerCompat.notify(1, mBuilder.build());
} else {
Toast.makeText(context, "Unable To Generate Notification", Toast.LENGTH_LONG).show();
}
cursor.close();
}
}
这是在我的 MainActivity 中显示通知的代码
Intent intent = new Intent(this, AlarmReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(this,
0, intent, PendingIntent.FLAG_IMMUTABLE);
AlarmManager alarms = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
Calendar calendar = Calendar.getInstance();
Calendar now = Calendar.getInstance();
calendar.set(Calendar.HOUR_OF_DAY, 8);
calendar.set(Calendar.MINUTE, 10);
if (now.after(calendar)) {
calendar.add(Calendar.DATE, 1);
}
if (alarms != null) {
alarms.setInexactRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(),
AlarmManager.INTERVAL_DAY, pendingIntent);
}
}
这是我在 firebase 上收到的崩溃报告
Fatal Exception: java.lang.RuntimeException: Unable to start receiver com.example.app.receiver.AlarmReceiver: java.lang.IllegalArgumentException: com.example.app: Targeting S+ (version 31 and above) requires that one of FLAG_IMMUTABLE or FLAG_MUTABLE be specified when creating a PendingIntent.
Strongly consider using FLAG_IMMUTABLE, only use FLAG_MUTABLE if some functionality depends on the PendingIntent being mutable, e.g. if it needs to be used with inline replies or bubbles.
at android.app.ActivityThread.handleReceiver(ActivityThread.java:4766)
at android.app.ActivityThread.access00(ActivityThread.java:310)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2288)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loopOnce(Looper.java:226)
at android.os.Looper.loop(Looper.java:313)
at android.app.ActivityThread.main(ActivityThread.java:8611)
at java.lang.reflect.Method.invoke(Method.java)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:563)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1133)
Caused by java.lang.IllegalArgumentException: com.example.app: Targeting S+ (version 31 and above) requires that one of FLAG_IMMUTABLE or FLAG_MUTABLE be specified when creating a PendingIntent.
Strongly consider using FLAG_IMMUTABLE, only use FLAG_MUTABLE if some functionality depends on the PendingIntent being mutable, e.g. if it needs to be used with inline replies or bubbles.
at android.app.PendingIntent.checkFlags(PendingIntent.java:382)
at android.app.PendingIntent.getActivitiesAsUser(PendingIntent.java:616)
at android.app.PendingIntent.getActivities(PendingIntent.java:598)
at androidx.core.app.TaskStackBuilder.getPendingIntent(TaskStackBuilder.java:341)
at androidx.core.app.TaskStackBuilder.getPendingIntent(TaskStackBuilder.java:312)
at com.example.app.receiver.AlarmReceiver.onReceive(AlarmReceiver.java:58)
at android.app.ActivityThread.handleReceiver(ActivityThread.java:4757)
at android.app.ActivityThread.access00(ActivityThread.java:310)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2288)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loopOnce(Looper.java:226)
at android.os.Looper.loop(Looper.java:313)
at android.app.ActivityThread.main(ActivityThread.java:8611)
at java.lang.reflect.Method.invoke(Method.java)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:563)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1133)
根据官方文档“如果您的应用面向 Android 12,您必须指定您的应用创建的每个 PendingIntent 对象的可变性。此附加要求提高了您应用的安全性。"
Intent notificationIntent = new Intent(getApplicationContext(), MainActivity.class);
PendingIntent contentIntent = PendingIntent.getActivity(context,NOTIFICATION_REQUEST_CODE, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);
我们正在构建一个标准类型的 Intent 来打开我们的应用程序,然后简单地将其包装在 PendingIntent 中,然后再将其添加到我们的 notification.In 这种情况下,因为我们有一个确切的动作,我们知道我们想要执行,我们构建一个 PendingIntent,我们通过使用名为 FLAG_IMMUTABLE.
的标志,将其传递给的应用程序无法对其进行修改