Giới thiệu
Ví dụ này minh họa cách tạo thông báo không hiển thị icon trên status bar (thanh trạng thái trên cùng) nhưng vẫn xuất hiện trong khu vực kéo xuống (notification shade). Sử dụng NotificationCompat.VISIBILITY_SECRET và custom layout.
Các bước thực hiện
Bước 1: Tạo dự án mới
Tạo project Android Studio mới.
Bước 2: Layout chính (res/layout/activity_main.xml)
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="https://schemas.android.com/apk/res/android"
xmlns:tools="https://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<Button
android:onClick="createNotification"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:layout_margin="16dp"
android:text="Tạo thông báo ẩn icon status bar" />
</RelativeLayout>
Bước 3: Custom Layout không có ImageView (res/layout/custom_notification_layout.xml)
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="https://schemas.android.com/apk/res/android"
android:id="@+id/layout"
android:layout_width="match_parent"
android:layout_height="96dp"
android:padding="10dp">
<TextView
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Thông báo ẩn icon"
android:textColor="#000"
android:textSize="18sp" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/title"
android:layout_marginTop="8dp"
android:hint="Chúng ta test không có icon"
android:inputType="text"
android:textSize="14sp" />
</RelativeLayout>
Bước 4: MainActivity (src/MainActivity.java)
package app.tutorialspoint.com.notifyme;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.os.Build;
import android.os.Bundle;
import android.support.v4.app.NotificationCompat;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.RemoteViews;
public class MainActivity extends AppCompatActivity {
public static final String NOTIFICATION_CHANNEL_ID = "10001";
private final static String default_notification_channel_id = "default";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void createNotification(View view) {
RemoteViews contentView = new RemoteViews(getPackageName(), R.layout.custom_notification_layout);
NotificationManager mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(
MainActivity.this, default_notification_channel_id);
mBuilder.setContent(contentView);
// VẪN BẮT BUỘC PHẢI CÓ SMALL ICON (dù không hiển thị)
mBuilder.setSmallIcon(R.drawable.ic_launcher_foreground);
mBuilder.setAutoCancel(true);
// QUAN TRỌNG: ẨN TỪ STATUS BAR
mBuilder.setVisibility(NotificationCompat.VISIBILITY_SECRET);
// Priority thấp để không hiện heads-up
mBuilder.setPriority(NotificationCompat.PRIORITY_MIN);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
int importance = NotificationManager.IMPORTANCE_LOW; // Low importance
NotificationChannel notificationChannel = new NotificationChannel(
NOTIFICATION_CHANNEL_ID, "Kênh ẩn icon", importance);
// Không set light/vibration
mBuilder.setChannelId(NOTIFICATION_CHANNEL_ID);
assert mNotificationManager != null;
mNotificationManager.createNotificationChannel(notificationChannel);
}
assert mNotificationManager != null;
mNotificationManager.notify((int) System.currentTimeMillis(), mBuilder.build());
}
}
Bước 5: AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="https://schemas.android.com/apk/res/android"
package="app.tutorialspoint.com.notifyme">
<uses-permission android:name="android.permission.VIBRATE" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
Giải thích kỹ thuật
1. VISIBILITY_SECRET
mBuilder.setVisibility(NotificationCompat.VISIBILITY_SECRET);
- Ẩn nội dung trên lock screen
- Giảm khả năng hiển thị trên status bar
- Vẫn hiển thị đầy đủ trong notification shade
2. PRIORITY_MIN + IMPORTANCE_LOW
mBuilder.setPriority(NotificationCompat.PRIORITY_MIN); // Channel importance notificationChannel.setImportance(NotificationManager.IMPORTANCE_LOW);
- Không hiện heads-up (popup)
- Không phát âm thanh/rung
- Icon status bar có thể ẩn (tùy OEM)
3. Custom Layout không ImageView
Layout tùy chỉnh không chứa ImageView → không hiển thị large icon → trông như "không icon".
Lưu ý quan trọng
⚠️ Không thể ẩn hoàn toàn icon status bar
- Android yêu cầu
setSmallIcon()bắt buộc (crash nếu thiếu) - Hệ thống quyết định hiển thị status bar icon dựa trên importance/priority
- Một số OEM (Samsung, Xiaomi) vẫn hiện icon dù PRIORITY_MIN
- Cách duy nhất "ẩn hẳn": không post notification, dùng overlay/window manager (cần quyền đặc biệt)
Use case thực tế
- Thông báo nền (background sync, backup hoàn tất)
- Thông báo không quan trọng, không muốn làm phiền
- App tracker, analytics ping
Chạy thử nghiệm
Chạy app → Tạo thông báo → Quan sát status bar (có thể không có icon) → Kéo thanh thông báo xuống → Thấy thông báo đầy đủ trong shade.