Introduction
[Description des exigences personnalisées] : après avoir inséré la carte SD, dans l'état de l'écran de verrouillage, supprimez l'invite "La carte SD peut être utilisée pour transférer des photos et des fichiers multimédias"
Démontage des exigences : il doit être normalement affiché dans la barre d'état déroulante de SystemUI, et seules les notifications dans l'état de l'écran de verrouillage doivent être bloquées.
2. Envoyer une notification
Cherchez d'abord la chaîne "peut être utilisé pour transférer des photos et des fichiers multimédias"
est dans /frameworks/base/core/res/res/values-zh-rCN.xml
Recherchez le fichier faisant référence à la chaîne dans le code source : StorageNotification.java Le chemin est :
frameworks/base/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java
Le code logique après insertion de SD est :
private void onVolumeStateChangedInternal(VolumeInfo vol) {
switch (vol.getType()) {
case VolumeInfo.TYPE_PRIVATE:
onPrivateVolumeStateChangedInternal(vol);
break;
//SD卡
case VolumeInfo.TYPE_PUBLIC:
onPublicVolumeStateChangedInternal(vol);
break;
}
}
Ensuite, une fois la carte SD montée avec succès, la méthode onVolumeMounted(vol) sera utilisée
private Notification onVolumeMounted(VolumeInfo vol) {
....
Notification.Builder builder = buildNotificationBuilder(vol, title, text)
....
}
Dans la méthode, l'objet générateur de notification sera créé
private Notification.Builder buildNotificationBuilder(VolumeInfo vol, CharSequence title,
CharSequence text) {
Notification.Builder builder =
new Notification.Builder(mContext, NotificationChannels.STORAGE)
.setSmallIcon(getSmallIcon(vol.getDisk(), vol.getState()))
.setColor(mContext.getColor(R.color.system_notification_accent_color))
.setContentTitle(title)
.setContentText(text)
.setStyle(new Notification.BigTextStyle().bigText(text))
.setVisibility(Notification.VISIBILITY_PUBLIC)
.setLocalOnly(true)
.extend(new Notification.TvExtender());
overrideNotificationAppName(mContext, builder, false);
return builder;
}
Ensuite, revenez à onPublicVolumeStateChangedInternal. Lorsque le générateur est créé avec succès, l'étape suivante consiste à envoyer une notification
private void onPublicVolumeStateChangedInternal(VolumeInfo vol) {
....
mNotificationManager.notifyAsUser(vol.getId(), SystemMessage.NOTE_STORAGE_PUBLIC,
notif, UserHandle.of(vol.getMountUserId()));
....
}
3. Afficher la notification
Les développeurs qui connaissent le module SystemUI peuvent visualiser directement le fichier qui gère l'affichage des notifications dans l'état de l'écran verrouillé :
frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManager.java est un fichier d'interface avec ces deux méthodes :
L'une consiste à filtrer par userId, et l'autre à filtrer les communications cachées par String key
boolean shouldHideNotifications(int userId);
boolean shouldHideNotifications(String key);
Le fichier d'implémentation spécifique est le fichier NotificationLockscreenUserManagerImpl.java
Je filtre en utilisant la méthode clé
public boolean shouldHideNotifications(String key) {
if (getEntryManager() == null) {
Log.wtf(TAG, "mEntryManager was null!", new Throwable());
return true;
}
return isLockscreenPublicMode(mCurrentUserId)
&& getEntryManager().getNotificationData().getVisibilityOverride(key) ==
Notification.VISIBILITY_SECRET;
}
Rechercher globalement où cette méthode est appelée
Dans la méthode shouldFilterOut du fichier NotificationFilter.java
/**
* @return true if the provided notification should NOT be shown right now.
*/
public boolean shouldFilterOut(NotificationEntry entry) {
final StatusBarNotification sbn = entry.notification;
if (!(getEnvironment().isDeviceProvisioned()
|| showNotificationEvenIfUnprovisioned(sbn))) {
return true;
}
if (!getEnvironment().isNotificationForCurrentProfiles(sbn)) {
return true;
}
if (getUserManager().isLockscreenPublicMode(sbn.getUserId())
&& (sbn.getNotification().visibility == Notification.VISIBILITY_SECRET
|| getUserManager().shouldHideNotifications(sbn.getUserId())
|| getUserManager().shouldHideNotifications(sbn.getKey()))) {
return true;
}
....
}
La signification de cette méthode est de filtrer les notifications dans des conditions spécifiques, il existe donc une solution à cela. Dans cette méthode, nous renvoyons vrai selon des conditions de jugement spécifiques, indiquant que cette notification doit être filtrée sur l'écran de verrouillage.
4. Solutions
Étant donné que la clé est utilisée comme condition de jugement, ajoutez une méthode liée à la clé à l'endroit où la notification est envoyée
private Notification.Builder buildNotificationBuilder(VolumeInfo vol, CharSequence title,
CharSequence text) {
Notification.Builder builder =
new Notification.Builder(mContext, NotificationChannels.STORAGE)
.setSmallIcon(getSmallIcon(vol.getDisk(), vol.getState()))
.setColor(mContext.getColor(R.color.system_notification_accent_color))
.setContentTitle(title)
.setContentText(text)
.setStyle(new Notification.BigTextStyle().bigText(text))
.setVisibility(Notification.VISIBILITY_PUBLIC)
.setLocalOnly(true)
//加上这个自定义的key 不需要显示在锁屏界面
.setGroup("not_show_on_lockscreen")
.extend(new Notification.TvExtender());
overrideNotificationAppName(mContext, builder, false);
return builder;
}
Ensuite, dans la méthode de filtrage pour afficher les notifications, ajoutez une condition de jugement et renvoyez true
public boolean shouldFilterOut(NotificationEntry entry) {
final StatusBarNotification sbn = entry.notification;
if (!(getEnvironment().isDeviceProvisioned()
|| showNotificationEvenIfUnprovisioned(sbn))) {
return true;
}
//在锁屏界面不显示SD卡的通知
if ("not_show_on_lockscreen".equals(sbn.getGroupKey())) {
return true;
}
//
....
}