Android 12(API 31)下Notification Builder操作按钮无响应求助
Android 12(API 31)通知操作按钮无响应问题
我开发了一款聊天应用,在API 31以下的Android系统中,通知的接听电话操作按钮可正常工作,但在Android 12(API 31)上,仅无操作的通知能正常显示,带操作按钮的通知点击无响应。相关代码如下,求解决:
FirebaseService.java
@Override public void onMessageReceived(@NonNull RemoteMessage remoteMessage) { super.onMessageReceived(remoteMessage); boolean cancelNotification = false; Intent intent = new Intent(this, MainActivity.class); intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); Map<String, String> params = remoteMessage.getData(); JSONObject data = new JSONObject(params); PendingIntent pendingIntent; if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.S) { pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_MUTABLE); } else { pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_ONE_SHOT); } String channel_id = getNotificationData(data, "channel"); NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this, channel_id) .setSmallIcon(R.mipmap.ic_launcher) .setContentTitle(getNotificationData(data, "title")) .setContentText(getNotificationData(data, "body")) .setAutoCancel(true) .setContentIntent(pendingIntent); if(channel_id.equals("cll2") && getNotificationData(data, "call_action").equals("open")){ playCallSound(this); if(WindowUtil.isAppOnBackground(this) || isScreenOff()){ ArrayList<String> par = new ArrayList<>(); par.add("call_channel"); par.add("call_type"); par.add("call_token"); par.add("call_peer"); String callType = getNotificationData(data, "call_type"); if(callType.equals("3") || callType.equals("4")){ par.add("call_group_name"); par.add("call_group_caller"); } Intent receiveCallAction = new Intent(this, CallReceiver.class); receiveCallAction.putExtra("action", "ANSWER"); Intent cancelCallAction = new Intent(this, CallReceiver.class); cancelCallAction.putExtra("action", "DECLINE"); for (String s : par) { receiveCallAction.putExtra(s, getNotificationData(data, s)); cancelCallAction.putExtra(s, getNotificationData(data, s)); } notificationBuilder.setOngoing(true); receiveCallAction.setAction("RECEIVE_CALL"); cancelCallAction.setAction("CANCEL_CALL"); PendingIntent receiveCallPendingIntent = PendingIntent.getBroadcast(this, 1200, receiveCallAction, PendingIntent.FLAG_UPDATE_CURRENT); PendingIntent cancelCallPendingIntent = PendingIntent.getBroadcast(this, 1201, cancelCallAction, PendingIntent.FLAG_UPDATE_CURRENT); notificationBuilder .addAction(R.drawable.ic_baseline_call_24_green, "Answer", receiveCallPendingIntent) .addAction(R.drawable.ic_baseline_call_red_24, "Decline", cancelCallPendingIntent); }else{ cancelNotification = true; } }if(channel_id.equals("cll2") && getNotificationData(data, "call_action").equals("end_timeout")){ stopRinging(); }else if(channel_id.equals("ntf1")){ if(UserUtil.IS_CHAT_ACTIVITY){ cancelNotification = true; } if(!cancelNotification){ playNotificationSound(this); } } if(!cancelNotification){ NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) { notificationBuilder.setDefaults(Notification.DEFAULT_VIBRATE); NotificationChannel channel = new NotificationChannel(channel_id, getString(R.string.app_name), NotificationManager.IMPORTANCE_HIGH); channel.enableLights(true); channel.enableVibration(true); mNotificationManager.createNotificationChannel(channel); } mNotificationManager.notify(1000, notificationBuilder.build()); } }
CallReceiver.java(Broadcast Receiver)
@Override public void onReceive(Context context, Intent intent) { if (intent != null && intent.getExtras() != null) { String action = intent.getStringExtra("action"); // Perform the action performClickAction(context, action, intent.getExtras()); // Close the notification after the click action is performed. NotificationManager mNotificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); mNotificationManager.cancel(1000); // Stop the ringtone stopRinging(); } }
AndroidManifest.xml
<service android:name=".services.FirebaseService" android:exported="true"> <intent-filter> <action android:name="com.google.firebase.MESSAGING_EVENT" /> </intent-filter> </service> <receiver android:name=".receiver.CallReceiver" android:exported="false" android:enabled="true"> <intent-filter> <action android:name="CALL_RECEIVER" /> </intent-filter> </receiver>
问题解决办法
1. 适配Android 12的PendingIntent标记
Android 12(API 31)及以上版本要求创建PendingIntent时必须指定FLAG_MUTABLE或FLAG_IMMUTABLE,你当前创建广播PendingIntent时未添加该标记,导致点击无响应。修改FirebaseService中创建广播PendingIntent的代码:
PendingIntent receiveCallPendingIntent; PendingIntent cancelCallPendingIntent; if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.S) { receiveCallPendingIntent = PendingIntent.getBroadcast(this, 1200, receiveCallAction, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_MUTABLE); cancelCallPendingIntent = PendingIntent.getBroadcast(this, 1201, cancelCallAction, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_MUTABLE); } else { receiveCallPendingIntent = PendingIntent.getBroadcast(this, 1200, receiveCallAction, PendingIntent.FLAG_UPDATE_CURRENT); cancelCallPendingIntent = PendingIntent.getBroadcast(this, 1201, cancelCallAction, PendingIntent.FLAG_UPDATE_CURRENT); }
2. 修正广播Action不匹配问题
代码中给广播Intent设置的Action是RECEIVE_CALL和CANCEL_CALL,但Manifest里注册的是CALL_RECEIVER,两者不匹配导致广播无法被接收,任选一种方式修改:
方式一:修改代码中的Action
receiveCallAction.setAction("CALL_RECEIVER"); cancelCallAction.setAction("CALL_RECEIVER");
方式二:修改Manifest中的Intent Filter
<receiver android:name=".receiver.CallReceiver" android:exported="false" android:enabled="true"> <intent-filter> <action android:name="RECEIVE_CALL" /> <action android:name="CANCEL_CALL" /> </intent-filter> </receiver>
3. 优化通知渠道创建逻辑(可选)
当前每次发送通知都重复创建通知渠道,建议将渠道创建逻辑移到Application的onCreate方法中,避免重复操作。
内容的提问来源于stack exchange,提问作者Aditya Rizqi
相关产品推荐
相关产品推荐

