NotificationCompat.Builder jest przestarzała w systemie Android O

161

Po uaktualnieniu mojego projektu do Androida O

buildToolsVersion "26.0.1"

Lint w Android Studio wyświetla przestarzałe ostrzeżenie dla następującej metody konstruktora powiadomień:

new NotificationCompat.Builder(context)

Problem polega na tym, że programiści Androida aktualizują swoją dokumentację opisującą NotificationChannel, aby obsługiwać powiadomienia w systemie Android O i dostarczają nam fragment kodu, ale z tym samym przestarzałym ostrzeżeniem:

Notification notification = new Notification.Builder(MainActivity.this)
        .setContentTitle("New Message")
        .setContentText("You've received new messages.")
        .setSmallIcon(R.drawable.ic_notify_status)
        .setChannelId(CHANNEL_ID)
        .build();  

Omówienie powiadomień

Moje pytanie: czy jest jakieś inne rozwiązanie do tworzenia powiadomień i nadal obsługuje Androida O?

Rozwiązaniem, które znalazłem, jest przekazanie identyfikatora kanału jako parametru w konstruktorze Notification.Builder. Ale to rozwiązanie nie nadaje się do ponownego użycia.

new Notification.Builder(MainActivity.this, "channel_id")
GuilhermeFGL
źródło
4
Ale to rozwiązanie nie nadaje się do ponownego użycia. jak to?
Tim
5
NotificationCompat.Builder jest przestarzała, a nie Notification.Builder. Zwróć uwagę, że część Compat zniknęła. Powiadomienie to ich nowa klasa, w której wszystko usprawniają
Kapil G
1
@kapsym to właściwie na odwrót. Notification.Builder jest starszy
Tim
Poza tym nie widzę tego tutaj jako przestarzałego developer.android.com/reference/android/support/v4/app/… . Może błąd w Lint
Kapil G
Identyfikator kanału jest przekazywany w konstruktorze lub można go umieścić za pomocą notificationBuild.setChannelId("channel_id"). W moim przypadku to ostatnie rozwiązanie jest bardziej przydatne, ponieważ moje NotificationCompat.Builderjest ponownie używane w kilku metodach, zapisując parametry ikon, dźwięków i wibracji.
GuilhermeFGL

Odpowiedzi:

167

W dokumentacji wspomniano, że metoda konstruktora NotificationCompat.Builder(Context context)jest przestarzała. I musimy użyć konstruktora, który ma channelIdparametr:

NotificationCompat.Builder(Context context, String channelId)

NotificationCompat.Builder Dokumentacja:

Ten konstruktor został wycofany na poziomie API 26.0.0-beta1. zamiast tego użyj NotificationCompat.Builder (Context, String). Wszystkie opublikowane powiadomienia muszą określać identyfikator NotificationChannel.

Notification.Builder Dokumentacja:

Ten konstruktor był przestarzały na poziomie API 26. Zamiast tego użyj Notification.Builder (Context, String). Wszystkie opublikowane powiadomienia muszą określać identyfikator NotificationChannel.

Jeśli chcesz ponownie użyć seterów konstruktora, możesz utworzyć konstruktora za pomocą channelIdi przekazać go do metody pomocniczej i ustawić preferowane ustawienia w tej metodzie.

Pion
źródło
3
Wydaje się, że zaprzeczają sobie podczas publikowania Notification.Builder(context)rozwiązania w sesji NotificationChannel. Ale cóż, przynajmniej znalazłeś post powiadamiający o tym, że wycofanie =)
GuilhermeFGL
23
Co to jest kanał? Czy możesz wyjaśnić?
Santanu Sur,
15
co to jest channelId?
RoundTwo
3
Możesz także nadal używać NotificationCompat.Builder(Context context), a następnie przypisać kanał w następujący sposób:builder.setChannelId(String channelId)
deyanm
36
Identyfikator kanału może być dowolnym ciągiem znaków, jest zbyt duży, aby omawiać go w komentarzach, ale służy do rozdzielania powiadomień na kategorie, aby użytkownik mógł wyłączyć to, co według niego nie jest dla niego ważne, zamiast blokować wszystkie powiadomienia z Twojej aplikacji.
yehyatt
110

wprowadź opis obrazu tutaj

Oto działający kod dla wszystkich wersji Androida od poziomu API 26+ z kompatybilnością wsteczną.

 NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(getContext(), "M_CH_ID");

        notificationBuilder.setAutoCancel(true)
                .setDefaults(Notification.DEFAULT_ALL)
                .setWhen(System.currentTimeMillis())
                .setSmallIcon(R.drawable.ic_launcher)
                .setTicker("Hearty365")
                .setPriority(Notification.PRIORITY_MAX) // this is deprecated in API 26 but you can still use for below 26. check below update for 26 API
                .setContentTitle("Default notification")
                .setContentText("Lorem ipsum dolor sit amet, consectetur adipiscing elit.")
                .setContentInfo("Info");

NotificationManager notificationManager = (NotificationManager) getContext().getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(1, notificationBuilder.build());

UPDATE dla API 26, aby ustawić maksymalny priorytet

    NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
    String NOTIFICATION_CHANNEL_ID = "my_channel_id_01";

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        NotificationChannel notificationChannel = new NotificationChannel(NOTIFICATION_CHANNEL_ID, "My Notifications", NotificationManager.IMPORTANCE_MAX);

        // Configure the notification channel.
        notificationChannel.setDescription("Channel description");
        notificationChannel.enableLights(true);
        notificationChannel.setLightColor(Color.RED);
        notificationChannel.setVibrationPattern(new long[]{0, 1000, 500, 1000});
        notificationChannel.enableVibration(true);
        notificationManager.createNotificationChannel(notificationChannel);
    }


    NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this, NOTIFICATION_CHANNEL_ID);

    notificationBuilder.setAutoCancel(true)
            .setDefaults(Notification.DEFAULT_ALL)
            .setWhen(System.currentTimeMillis())
            .setSmallIcon(R.drawable.ic_launcher)
            .setTicker("Hearty365")
       //     .setPriority(Notification.PRIORITY_MAX)
            .setContentTitle("Default notification")
            .setContentText("Lorem ipsum dolor sit amet, consectetur adipiscing elit.")
            .setContentInfo("Info");

    notificationManager.notify(/*notification id*/1, notificationBuilder.build());
Aks4125
źródło
Jak sprawić, by powiadomienie faktycznie wyświetlało się na ekranie w aplikacji lub w innej aplikacji?
BlueBoy
@BlueBoy Nie otrzymuję twojego pytania. czy mógłbyś wyjaśnić, czego dokładnie potrzebujesz?
Aks4125
@ Aks4125 Powiadomienie nie przesuwa się w dół i nie jest wyświetlane u góry ekranu. Usłyszysz dźwięk, a na pasku stanu pojawi się niewielka ikona powiadomienia - ale nic nie zsuwa się w dół i nie pokazuje, jak masz wiadomość tekstową.
BlueBoy
@BlueBoy musisz ustawić priorytet na WYSOKI dla tego zachowania. daj mi znać, jeśli mam zaktualizować ten kod. jeśli zakradniesz się do powiadomienia o wysokim priorytecie, otrzymasz odpowiedź.
Aks4125
2
@BlueBoy sprawdź zaktualizowaną odpowiedź. Jeśli nie kierujesz się na 26 API, po prostu użyj tego samego kodu z .setPriority(Notification.PRIORITY_MAX)else użyj zaktualizowanego kodu dla 26 API. `
Aks4125
31

Wywołaj konstruktor 2-arg: Aby uzyskać zgodność z systemem Android O, wywołaj support-v4 NotificationCompat.Builder(Context context, String channelId). W przypadku korzystania z systemu Android N lub starszego channelIdzostanie zignorowany. W przypadku korzystania z systemu Android O utwórz również plik NotificationChannelz tym samym plikiem channelId.

Nieaktualny przykładowy kod: przykładowy kod na kilku stronach JavaDoc, takich jak wywołanie Notification.Builder,new Notification.Builder(mContext) jest nieaktualny.

Przestarzałe konstruktory: Notification.Builder(Context context) i v4 NotificationCompat.Builder(Context context) są przestarzałe na rzecz Notification[Compat].Builder(Context context, String channelId). (Zobacz Notification.Builder (android.content.Context) i v4 NotificationCompat.Builder (kontekst kontekstowy) .)

Przestarzała klasa: cała klasa v7 NotificationCompat.Builder jest przestarzała. (Widzieć NotificationCompat.Builder w wersji 7 ). Wcześniej NotificationCompat.Builderdo obsługi potrzebna była wersja 7 NotificationCompat.MediaStyle. W Android O, tam jest v4 NotificationCompat.MediaStylew Media-compat biblioteki „s android.support.v4.mediapakietu. Użyj tego, jeśli potrzebujesz MediaStyle.

API 14+: W Support Library od 26.0.0 i nowszych, pakiety support-v4 i support-v7 obsługują minimalny poziom API 14. Nazwy v # są historyczne.

Widzieć Najnowsze wersje biblioteki pomocy technicznej .

Jerry101
źródło
22

Zamiast sprawdzać Build.VERSION.SDK_INT >= Build.VERSION_CODES.O tyle odpowiedzi, ile sugeruje, istnieje nieco prostszy sposób -

Dodaj następujący wiersz do applicationsekcji pliku AndroidManifest.xml , jak wyjaśniono w dokumencie Konfigurowanie aplikacji klienckiej Firebase Cloud Messaging na Androida :

    <meta-data
        android:name="com.google.firebase.messaging.default_notification_channel_id" 
        android:value="@string/default_notification_channel_id" />

Następnie dodaj wiersz z nazwą kanału do pliku values ​​/ strings.xml :

<string name="default_notification_channel_id">default</string>

Po tym będziesz mógł korzystać z nowej wersji konstruktora NotificationCompat.Builder z 2 parametrami (ponieważ stary konstruktor z 1 parametrem został wycofany w systemie Android Oreo):

private void sendNotification(String title, String body) {
    Intent i = new Intent(this, MainActivity.class);
    i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
    PendingIntent pi = PendingIntent.getActivity(this,
            0 /* Request code */,
            i,
            PendingIntent.FLAG_ONE_SHOT);

    Uri sound = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);

    NotificationCompat.Builder builder = new NotificationCompat.Builder(this, 
        getString(R.string.default_notification_channel_id))
            .setSmallIcon(R.mipmap.ic_launcher)
            .setContentTitle(title)
            .setContentText(body)
            .setAutoCancel(true)
            .setSound(sound)
            .setContentIntent(pi);

    NotificationManager manager = 
        (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);

    manager.notify(0, builder.build());
}
Alexander Farber
źródło
1
jak to jest prostsze? : S
Nactus,
17

Oto przykładowy kod, który działa w systemie Android Oreo i mniej niż Oreo.

  NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
            NotificationCompat.Builder builder = null;
            if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
                int importance = NotificationManager.IMPORTANCE_DEFAULT;
                NotificationChannel notificationChannel = new NotificationChannel("ID", "Name", importance);
                notificationManager.createNotificationChannel(notificationChannel);
                builder = new NotificationCompat.Builder(getApplicationContext(), notificationChannel.getId());
            } else {
                builder = new NotificationCompat.Builder(getApplicationContext());
            }

            builder = builder
                    .setSmallIcon(R.drawable.ic_notification_icon)
                    .setColor(ContextCompat.getColor(context, R.color.color))
                    .setContentTitle(context.getString(R.string.getTitel))
                    .setTicker(context.getString(R.string.text))
                    .setContentText(message)
                    .setDefaults(Notification.DEFAULT_ALL)
                    .setAutoCancel(true);
            notificationManager.notify(requestCode, builder.build());
Arpit
źródło
8

Prosta próbka

    public void showNotification (String from, String notification, Intent intent) {
        PendingIntent pendingIntent = PendingIntent.getActivity(
                context,
                Notification_ID,
                intent,
                PendingIntent.FLAG_UPDATE_CURRENT
        );


        String NOTIFICATION_CHANNEL_ID = "my_channel_id_01";
        NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);


        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            NotificationChannel notificationChannel = new NotificationChannel(NOTIFICATION_CHANNEL_ID, "My Notifications", NotificationManager.IMPORTANCE_DEFAULT);

            // Configure the notification channel.
            notificationChannel.setDescription("Channel description");
            notificationChannel.enableLights(true);
            notificationChannel.setLightColor(Color.RED);
            notificationChannel.setVibrationPattern(new long[]{0, 1000, 500, 1000});
            notificationChannel.enableVibration(true);
            notificationManager.createNotificationChannel(notificationChannel);
        }


        NotificationCompat.Builder builder = new NotificationCompat.Builder(context, NOTIFICATION_CHANNEL_ID);
        Notification mNotification = builder
                .setContentTitle(from)
                .setContentText(notification)

//                .setTicker("Hearty365")
//                .setContentInfo("Info")
                //     .setPriority(Notification.PRIORITY_MAX)

                .setContentIntent(pendingIntent)

                .setAutoCancel(true)
//                .setDefaults(Notification.DEFAULT_ALL)
//                .setWhen(System.currentTimeMillis())
                .setSmallIcon(R.mipmap.ic_launcher)
                .setLargeIcon(BitmapFactory.decodeResource(context.getResources(), R.mipmap.ic_launcher))
                .build();

        notificationManager.notify(/*notification id*/Notification_ID, mNotification);

    }
Mehul
źródło
4
Notification notification = new Notification.Builder(MainActivity.this)
        .setContentTitle("New Message")
        .setContentText("You've received new messages.")
        .setSmallIcon(R.drawable.ic_notify_status)
        .setChannelId(CHANNEL_ID)
        .build();  

Prawidłowy kod to:

Notification.Builder notification=new Notification.Builder(this)

z zależnościami 26.0.1 i nowymi zaktualizowanymi zależnościami, takimi jak 28.0.0.

Niektórzy użytkownicy używają tego kodu w następujący sposób:

Notification notification=new NotificationCompat.Builder(this)//this is also wrong code.

Tak więc logika to metoda, którą zadeklarujesz lub zainicjujesz, a następnie ta sama metoda po prawej stronie zostanie użyta do alokacji. jeśli w Leftside of = użyjesz jakiejś metody, to ta sama metoda zostanie użyta po prawej stronie = do alokacji z new.

Wypróbuj ten kod ... Na pewno zadziała

Pradeep Sheoran
źródło
1

Ten konstruktor był przestarzały na poziomie interfejsu API 26.1.0. zamiast tego użyj NotificationCompat.Builder (Context, String). Wszystkie opublikowane powiadomienia muszą określać identyfikator NotificationChannel.

Sandeep Singh
źródło
Może raczej dodaj komentarz z linkiem do dokumentacji zamiast kopiować kota i pisać jako odpowiedź.
JacksOnF1re
0
  1. Musisz zadeklarować kanał powiadomień z Notification_Channel_ID
  2. Utwórz powiadomienie z tym identyfikatorem kanału. Na przykład,

...
 public static final String NOTIFICATION_CHANNEL_ID = MyLocationService.class.getSimpleName();
...
...
NotificationChannel channel = new NotificationChannel(NOTIFICATION_CHANNEL_ID,
                NOTIFICATION_CHANNEL_ID+"_name",
                NotificationManager.IMPORTANCE_HIGH);

NotificationManager notifManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);

notifManager.createNotificationChannel(channel);


NotificationCompat.Builder builder = new NotificationCompat.Builder(this, NOTIFICATION_CHANNEL_ID)
                .setContentTitle(getString(R.string.app_name))
                .setContentText(getString(R.string.notification_text))
                .setOngoing(true)
                .setContentIntent(broadcastIntent)
                .setSmallIcon(R.drawable.ic_tracker)
                .setPriority(PRIORITY_HIGH)
                .setCategory(Notification.CATEGORY_SERVICE);

        startForeground(1, builder.build());
...
Zaman
źródło