在版本 S 中创建通知时 Android 应用程序崩溃

发布于 2025-01-12 11:08:14 字数 6408 浏览 0 评论 0原文

我已经在我的应用程序中使用通知有一段时间了,一切都工作正常,直到我最近瞄准了 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.access$1800(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.access$1800(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)

I have been using notifications in my app for a while now and everything was working fine until i recently targeted android 12. Now my app is crashing when i get notifications on android 12. But everything is working fine on below android 12 devices. Here is what i have tried so far.

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();
}
}

And here is the code to show notifications in my 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);
    }

}

And here are the crash reports I'm getting on 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.access$1800(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.access$1800(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)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

彻夜缠绵 2025-01-19 11:08:14

根据官方文档“如果您的应用面向 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 中,然后将其添加到我们的通知中。在这种情况下,由于我们知道我们想要执行一个确切的操作,因此我们构造了一个不能执行的 PendingIntent由我们通过使用名为 FLAG_IMMUTABLE 的标志传递给它的应用程序进行修改。

As per the official doc "If your app targets Android 12, you must specify the mutability of each PendingIntent object that your app creates. This additional requirement improves your app's security."

Intent notificationIntent = new Intent(getApplicationContext(), MainActivity.class);


PendingIntent contentIntent = PendingIntent.getActivity(context,NOTIFICATION_REQUEST_CODE, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);

we’re constructing a standard type of Intent that will open our app, and then simply wrapping that in a PendingIntent before adding it to our notification.In this case, since we have an exact action we know we want to perform, we construct a PendingIntent that cannot be modified by the app we pass it to by utilizing a flag called FLAG_IMMUTABLE.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文