适配Android S+(API 31+)时PendingIntent未指定FLAG问题求助
解决Android通知应用的PendingIntent FLAG错误
开发通知应用时遇到如下错误:
java.lang.IllegalArgumentException: com.tonyapp.rabbitfarm: 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:375) at android.app.PendingIntent.getBroadcastAsUser(PendingIntent.java:645) at android.app.PendingIntent.getBroadcast(PendingIntent.java:632) at com.allyants.notifyme.NotifyMe.scheduleNotification(NotifyMe.java:159) at com.allyants.notifyme.NotifyMe.<init>(NotifyMe.java:89) at com.allyants.notifyme.NotifyMe$Builder.build(NotifyMe.java:327) at com.tonyapp.rabbitfarm.NotesTakerActivity.onTimeSet(NotesTakerActivity.java:291) at com.wdullaer.materialdatetimepicker.time.TimePickerDialog.notifyOnDateListener(TimePickerDialog.java:1893) at com.wdullaer.materialdatetimepicker.time.TimePickerDialog.lambda$onCreateView$3$com-wdullaer-materialdatetimepicker-time-TimePickerDialog(TimePickerDialog.java:761) at com.wdullaer.materialdatetimepicker.time.TimePickerDialog$$ExternalSyntheticLambda3.onClick(Unknown Source:2) at android.view.View.performClick(View.java:7441) at com.google.android.material.button.MaterialButton.performClick(MaterialButton.java:1202) at android.view.View.performClickInternal(View.java:7418) at android.view.View.access$3700(View.java:835) at android.view.View$PerformClick.run(View.java:28676) at android.os.Handler.handleCallback(Handler.java:938) at android.os.Handler.dispatchMessage(Handler.java:99) at android.os.Looper.loopOnce(Looper.java:201) at android.os.Looper.loop(Looper.java:288) at android.app.ActivityThread.main(ActivityThread.java:7839) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1003)
我的MainActivity.java相关代码:
btnCancel.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { NotifyMe.cancel(getApplicationContext(),"test"); } }); btnNotify.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { dpd.show(getSupportFragmentManager(),"DatePickerDialog"); } }); } @Override public void onDateSet(DatePickerDialog view, int year, int monthOfYear, int dayOfMonth) { now.set(Calendar.YEAR,year); now.set(Calendar.MONTH,monthOfYear); now.set(Calendar.DAY_OF_MONTH,dayOfMonth); tpd.show(getSupportFragmentManager(),"timepicker"); } @Override public void onTimeSet(TimePickerDialog view, int hourOfDay, int minute, int second) { now.set(Calendar.HOUR_OF_DAY,hourOfDay); now.set(Calendar.MINUTE,minute); now.set(Calendar.SECOND,second); NotifyMe notifyMe = new NotifyMe.Builder(getApplicationContext()) .title(edt1.getText().toString()) .content(edt2.getText().toString()) .color(255,0,0,255) .led_color(255,255,255,255) .time(now) .addAction(new Intent(),"Snooze",false) .addAction(new Intent(),"Dismiss",true) .addAction(new Intent(),"Done") .large_icon(R.mipmap.ic_launcher_round) .build(); }
解决方案
错误根源是Target SDK >=31(Android 12+)要求创建PendingIntent时必须指定FLAG_IMMUTABLE或FLAG_MUTABLE,而你使用的NotifyMe库内部创建PendingIntent时没有添加这些flag。
方案1:升级NotifyMe库到兼容Android 12+的版本
检查该库的最新版本,确认是否已修复此问题。若有更新,直接在build.gradle中升级依赖版本即可。方案2:修改NotifyMe库源码(无法升级时)
找到库中scheduleNotification方法(对应错误栈的com.allyants.notifyme.NotifyMe.scheduleNotification(NotifyMe.java:159)),修改PendingIntent创建代码:int flags; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { // 除非需要可变PendingIntent(如内回复、气泡功能),否则优先用FLAG_IMMUTABLE flags = PendingIntent.FLAG_IMMUTABLE; // 需可变时用:flags = PendingIntent.FLAG_MUTABLE; } else { flags = 0; } PendingIntent.getBroadcast(context, 0, intent, flags);方案3:替换为系统原生通知API(最可靠)
若NotifyMe库长期未维护,建议直接用Android原生NotificationManager和PendingIntentAPI创建通知,完全控制flag设置:// 创建通知广播意图 Intent notifyIntent = new Intent(this, YourNotificationReceiver.class); PendingIntent pendingIntent = PendingIntent.getBroadcast( this, 0, notifyIntent, Build.VERSION.SDK_INT >= Build.VERSION_CODES.S ? PendingIntent.FLAG_IMMUTABLE : 0 ); // 构建通知 NotificationCompat.Builder builder = new NotificationCompat.Builder(this, "YOUR_CHANNEL_ID") .setSmallIcon(R.drawable.ic_notification) .setContentTitle(edt1.getText().toString()) .setContentText(edt2.getText().toString()) .setPriority(NotificationCompat.PRIORITY_DEFAULT) .setContentIntent(pendingIntent); // 调度通知 AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE); alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, now.getTimeInMillis(), pendingIntent);
内容的提问来源于stack exchange,提问作者jackie Maik
相关产品推荐
相关产品推荐

