Giới thiệu
Ví dụ này minh họa cách ẩn nội dung thông báo trên màn hình khóa (Lock Screen) nhưng vẫn cho phép hiển thị đầy đủ trong khu vực thông báo (Notification Shade). Sử dụng VISIBILITY_SECRET và kiểm tra trạng thái khóa màn hình bằng KeyguardManager.
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 Lock Screen" />
</RelativeLayout>
Bước 3: Custom Layout (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">
<ImageView
android:id="@+id/image"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_alignParentStart="true"
android:layout_marginEnd="10dp"
android:contentDescription="@string/app_name"
android:src="@mipmap/ic_launcher" />
<TextView
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toEndOf="@id/image"
android:text="Thông báo bí mật"
android:textColor="#000"
android:textSize="18sp" />
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/title"
android:layout_marginTop="8dp"
android:layout_toEndOf="@id/image"
android:hint="Nội dung nhạy cảm..."
android:inputType="text"
android:textSize="14sp" />
</RelativeLayout>
Bước 4: MainActivity với KeyguardManager (src/MainActivity.java)
package app.tutorialspoint.com.notifyme;
import android.app.KeyguardManager;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.content.Context;
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);
mBuilder.setSmallIcon(R.drawable.ic_launcher_foreground);
mBuilder.setAutoCancel(true);
// QUAN TRỌNG: ẨN NỘI DUNG TRÊN LOCK SCREEN
mBuilder.setVisibility(NotificationCompat.VISIBILITY_SECRET);
// KIỂM TRA MÀN HÌNH KHÓA - GIẢM PRIORITY NẾU ĐANG KHÓA
KeyguardManager keyguardManager = (KeyguardManager) getApplicationContext()
.getSystemService(Context.KEYGUARD_SERVICE);
if (keyguardManager != null && keyguardManager.isKeyguardLocked()) {
mBuilder.setPriority(NotificationCompat.PRIORITY_MIN);
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
int importance = NotificationManager.IMPORTANCE_HIGH;
NotificationChannel notificationChannel = new NotificationChannel(
NOTIFICATION_CHANNEL_ID, "Kênh ẩn Lock Screen", importance);
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 cơ chế
1. Notification Visibility Levels
| Visibility | Lock Screen | Notification Shade |
|---|---|---|
VISIBILITY_PUBLIC |
Hiện đầy đủ | Hiện đầy đủ |
VISIBILITY_PRIVATE |
Chỉ hiện app name, icon | Hiện đầy đủ |
VISIBILITY_SECRET |
Ẩn hoàn toàn (không hiện) | Hiện đầy đủ |
2. KeyguardManager.isKeyguardLocked()
Kiểm tra thiết bị có đang khóa màn hình không. Nếu đang khóa → giảm priority xuống MIN để không hiện heads-up trên lock screen.
3. Public Version (tùy chọn)
Có thể cung cấp phiên bản công khai cho lock screen:
Notification publicVersion = new NotificationCompat.Builder(context, channelId)
.setContentTitle("Có thông báo mới")
.setContentText("Nhấn để xem chi tiết")
.setSmallIcon(R.drawable.ic_launcher)
.build();
mBuilder.setPublicVersion(publicVersion);
mBuilder.setVisibility(NotificationCompat.VISIBILITY_PRIVATE);
Lưu ý quan trọng
- User có thể override trong Settings: Apps → Your App → Notifications → "On lock screen"
- Android 11+ có "Conversation notifications" ưu tiên hiển thị trên lock screen
- VISIBILITY_SECRET hoàn toàn ẩn trên lock screen, kể cả heads-up
- Custom layout (RemoteViews) vẫn tuân thủ visibility rules
Chạy thử nghiệm
- Chạy app, tạo thông báo
- Khóa màn hình (Power button)
- Quan sát lock screen: KHÔNG thấy thông báo
- Mở khóa → Kéo notification shade: THẤY thông báo đầy đủ
