Giới thiệu
Khi thêm Action button vào thông báo (qua addAction()), panel thông báo (notification shade) mặc định **không tự đóng** sau khi bấm nút. Bài này hướng dẫn cách buộc đóng panel bằng cách gửi broadcastIntent với Intent.ACTION_CLOSE_SYSTEM_DIALOGS.
Yêu cầu
- Android 5.0+ (API 21) cho Action button
- Quyền
android.permission.BROADCAST_CLOSE_SYSTEM_DIALOGS(chỉ system apps được cấp, ứng dụng thường **không thể** dùng action này từ API 23+)
⚠️ Lưu ý quan trọng: Từ Android 6.0 (Marshmallow), Google hạn chế quyềnBROADCAST_CLOSE_SYSTEM_DIALOGSchỉ cho system apps. Ứng dụng thông thường **không thể** ép đóng notification shade bằng cách này. Giải pháp thay thế: dùngsetAutoCancel(true)trên action's PendingIntent (chỉ đóng thông báo đó, không đóng toàn bộ panel).
Cách làm (chỉ dành cho system apps / rooted devices)
1. Tạo BroadcastReceiver để đóng panel
public class ClosePanelReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
// Chỉ system apps mới có hiệu lực
Intent closeDialogs = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
context.sendBroadcast(closeDialogs);
}
}
2. Đăng ký trong Manifest
<receiver android:name=".ClosePanelReceiver"
android:exported="false">
<intent-filter>
<action android:name="com.example.CLOSE_NOTIFICATION_PANEL" />
</intent-filter>
</receiver>
<uses-permission android:name="android.permission.BROADCAST_CLOSE_SYSTEM_DIALOGS" />
3. Gán vào Action button
Intent closeIntent = new Intent("com.example.CLOSE_NOTIFICATION_PANEL");
PendingIntent closePendingIntent = PendingIntent.getBroadcast(
this, 0, closeIntent, PendingIntent.FLAG_IMMUTABLE);
NotificationCompat.Builder builder = new NotificationCompat.Builder(this, CHANNEL_ID)
.setSmallIcon(R.drawable.ic_launcher)
.setContentTitle("Có nút bấm")
.setContentText("Bấm nút sẽ cố gắng đóng panel")
.addAction(R.drawable.ic_close, "Đóng panel", closePendingIntent)
.setAutoCancel(true);
Giải pháp thực tế cho ứng dụng thông thường
Vì không thể ép đóng toàn bộ panel, hãy thiết kế UX phù hợp:
- Dùng setAutoCancel(true): Thông báo biến mất sau khi bấm action → panel gọn nhẹ hơn.
- Mở Activity với FLAG_ACTIVITY_NEW_TASK: Chuyển người dùng sang app, panel tự thu gọn.
- Foreground Service với ongoing notification: Dành cho media player, download manager.
Ví dụ thực tế: Nút "Đọc sau" / "Xóa"
// Nút "Đọc sau" - mở app, đánh dấu đã đọc
Intent readLaterIntent = new Intent(this, ArticleActivity.class);
readLaterIntent.putExtra("action", "read_later");
readLaterIntent.putExtra("article_id", articleId);
PendingIntent readLaterPI = PendingIntent.getActivity(this, 1, readLaterIntent,
PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_UPDATE_CURRENT);
// Nút "Xóa" - chỉ xóa thông báo, không mở app
Intent dismissIntent = new Intent(this, NotificationActionReceiver.class);
dismissIntent.setAction("DISMISS");
dismissIntent.putExtra("notification_id", notificationId);
PendingIntent dismissPI = PendingIntent.getBroadcast(this, 2, dismissIntent,
PendingIntent.FLAG_IMMUTABLE);
builder.addAction(R.drawable.ic_bookmark, "Đọc sau", readLaterPI)
.addAction(R.drawable.ic_delete, "Xóa", dismissPI)
.setAutoCancel(false); // Giữ thông báo nếu bấm "Đọc sau"
Kết luận
Không thể đóng hoàn toàn notification shade từ app thường do chính sách bảo mật Android. Hãy tập trung vào trải nghiệm người dùng: tự xóa thông báo sau hành động, hoặc chuyển sang app để panel tự thu.