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.

的标志,将其传递给的应用程序无法对其进行修改