Mam SharedPreference: sharedPref.getBoolean("online", false)

Jeśli otrzymam powiadomienie, gdy online jest fałszywe, chcę je zablokować. Zazwyczaj nie będzie powiadomienia, jeśli użytkownik jest w trybie offline, ale bardzo rzadko je otrzymuję i chciałbym, aby to było kopia zapasowa, aby zapobiec powiadomieniu.

Powiadomienie jest wysyłane przez Firebase Cloud Messaging (FCM), a oto jak jest przetwarzane w moja aplikacja:

class CustomApplication : Application() {

    val MATCH_CHANNEL_ID = "MATCH_CHANNEL"

    companion object {
        var database: AppDatabase? = null
    }

    override fun onCreate() {
        super.onCreate()
        val settings: FirebaseFirestoreSettings = FirebaseFirestoreSettings.Builder().setPersistenceEnabled(false).build()
        FirebaseFirestore.getInstance().firestoreSettings = settings
        CustomApplication.database = Room.databaseBuilder(this, AppDatabase::class.java, "AppDatabase").build()
        createNotificationChannel()
    }

    private fun createNotificationChannel(){
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){
            val matchChannel = NotificationChannel(MATCH_CHANNEL_ID, "Nearby matches", NotificationManager.IMPORTANCE_HIGH)
            matchChannel.description = "Nearby matches"
            val manager: NotificationManager = getSystemService(NotificationManager::class.java)
            manager.createNotificationChannel(matchChannel)
        }
    }
}

Czy mogę w jakiś sposób zapobiec otrzymywaniu powiadomień, jeśli online jest fałszywe w SharedPreferences?

EDYTOWAĆ:

Gdy otrzymuję powiadomienie FCM w tle, dzwoni . FirebaseMessagingService.onCreate():

class CustomFirebaseMessagingService : FirebaseMessagingService() {

    val db = FirebaseFirestore.getInstance()

    override fun onCreate() {
        Log.d(TAG, "CustomFirebaseMessagingService onCreate()")
        return
        super.onCreate()
    } 

Nadpisałem onCreate(), aby wrócić przed super.onCreate() - w nadziei anulowania powiadomienia. Jednak powiadomienie nadal się uruchamia.

Czy istnieje inna funkcja w CustomFirebaseMessagingService(), którą mogę zastąpić, aby przechwycić powiadomienie i je anulować?

-4
Zorgan 20 listopad 2019, 11:43
Możesz umieścić swojego menedżera powiadomień wewnątrz instrukcji if
 – 
L2_Paver
20 listopad 2019, 11:53
Jak to? Czy manager.createNotificationChannel(matchChannel) nie tworzy tylko kanału powiadomień, ale nie przetwarza przyszłych powiadomień?
 – 
Zorgan
20 listopad 2019, 11:54
Czy korzystałeś z usługi, która rozszerza FirebaseMessagingService?
 – 
L2_Paver
20 listopad 2019, 12:05
createNotificationChannel tworzy tylko Kanał, który użytkownik może dostosować w ustawieniach powiadomień aplikacji (także System), ale tworzenie powiadomienia to inny proces, możesz go znaleźć zgodnie z sugestiami innych w FirebaseMessagingService
 – 
Ahmed na
20 listopad 2019, 12:08
Ustaw flagę i sprawdź, czy pochodzi z firebase lub wspólnych preferencji.
 – 
Shivam Oberoi
20 listopad 2019, 12:09

3 odpowiedzi

Zobacz swój plik manifestu, będzie taka usługa

<service
    android:name=".java.MyFirebaseMessagingService"
    android:exported="false">
    <intent-filter>
        <action android:name="com.google.firebase.MESSAGING_EVENT" />
    </intent-filter>
</service>

Następnie przejdź do pliku MyFirebaseMessagingService.java, sprawdź wartość wspólnych preferencji i ustaw warunek powiadamiania. Spróbuj tego..

@Override
public void onMessageReceived(RemoteMessage remoteMessage) {

    boolean flag = sharedPref.getBoolean("online", false);

    // Check if message contains a notification payload.
    if (remoteMessage.getNotification() != null) {

          if(flag){
             //TODO write your code here to set notification and notify
          }

    }

} 
0
Koushik Mondal 20 listopad 2019, 11:56
1
OnMessageReceived() jest wywoływany tylko w aplikacji - muszę zablokować powiadomienie w tle.
 – 
Zorgan
5 grudzień 2019, 12:50

Jeśli dobrze zrozumiałem Twoje pytanie, mówisz o sytuacji, w której otrzymujesz wiadomości push, gdy Twoja aplikacja nie jest uruchomiona. Wspomniałeś, że onMessageReceived() jest wywoływana tylko wtedy, gdy Twoja aplikacja jest uruchomiona, ale powiadomienia są wyświetlane nawet bez wywołania tej metody przez system. W związku z tym możemy wnioskować, że powiadomienia te są pobierane przez system automatycznie. To zachowanie jest kontrolowane przez sekcje „powiadomienia” i „dane” w treści wiadomości FCM.

Wiadomości FCM mają skomplikowaną specyfikację, którą można znaleźć tutaj . Ale ponieważ interesują nas tylko sekcje „powiadomienia” i „dane”, możemy polegać na ich zachowaniu:

Pierwszy przypadek – obecne są zarówno sekcje „powiadomienia”, jak i „dane”

Przykład:

{
  "message":{
    "notification": { /*...*/ },
    "data": {/*...*/}
  }
}

W takim przypadku, jeśli Twoja aplikacja działa w tle,

  • System automatycznie wyświetli powiadomienie;
  • Kliknięcie tego powiadomienia spowoduje uruchomienie działania;
  • Intencja działania będzie zawierać treść „dane” i pewne informacje techniczne dotyczące komunikatu FCM.

Drugi przypadek – obecna jest tylko sekcja „powiadomienie”

Przykład:

{
  "message":{
    "notification": { /*...*/ },
  }
}

W takim przypadku, jeśli Twoja aplikacja działa w tle,

  • System automatycznie wyświetli powiadomienie;
  • Kliknięcie tego powiadomienia spowoduje uruchomienie działania;
  • Intencja działania będzie zawierać tylko informacje techniczne dotyczące komunikatu FCM.

Trzeci przypadek – obecna jest tylko sekcja „dane”

Przykład:

{
  "message":{
    "data": {/*...*/}
  }
}

W takim przypadku, jeśli Twoja aplikacja działa w tle,

  • System nie automatycznie wyświetli powiadomienie;
  • onMessageReceived() zostanie wywołany.

Tak więc, po przejrzeniu tych informacji, możesz spróbować zmienić treść wiadomości FCM (tj. Wyrzucić sekcję „powiadomienia”), aby uniemożliwić systemowi samodzielną obsługę powiadomień o rysowaniu.

Mając wiadomości obsługiwane przez onMessageReceived() za każdym razem, możesz umieścić tam swoją logikę z tą flagą.

5
Stanislav Shamilov 5 grudzień 2019, 13:44
Dzięki temu dobrze to wyjaśnia. Jednak zamierzam wyłączyć powiadomienia na podstawie danych lokalnych (dane SharedPreferences), a nie na ciele FCM.
 – 
Zorgan
5 grudzień 2019, 14:01
W ten sposób otrzymasz wszystkie wiadomości push w swoim Service i tam będziesz mógł zastosować swoją logikę. Chodzi o to, że modyfikacja struktury wiadomości da ci możliwość samodzielnego kontrolowania wszystkiego, zamiast pozwalać systemowi na zrobienie czegoś automatycznie. Teraz twój problem istnieje, ponieważ system sam wyświetla te powiadomienia, gdy aplikacja jest offline. Wyrzucając część „powiadomienia” w wiadomości powiesz systemowi, że chcesz samodzielnie obsługiwać wiadomości push (czyli wyświetlać powiadomienia)
 – 
Stanislav Shamilov
5 grudzień 2019, 16:19
    <service
        android:name=".fcm.FCMService"
        android:enabled="true"
        android:exported="false"
        android:stopWithTask="false"> 
        <intent-filter>
            <action android:name="com.google.firebase.MESSAGING_EVENT" />
        </intent-filter>
    </service>

Niezbyt dobrze udokumentowane, ale ustawienie go na false utrzyma usługę przy życiu, nawet jeśli aplikacja działa w tle lub jest zatrzymana https://developer.android.com/reference/android/R. attr.html#stopWithTask

W ten sposób możesz obsłużyć blokowanie w metodzie otrzymanej na msg, jak sugerował poprzedni plakat

 NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this, Constants.NOTIFICATION_CHANNEL_QA_ID)
            .setSmallIcon(R.drawable.icon_notif)
            .setColor(getResources().getColor(R.color.primary))
            .setContentTitle(title)
            .setContentText(text)
            .setAutoCancel(true)
            .setStyle(new NotificationCompat.BigTextStyle()
               .bigText(text)
            );

    Intent intent = new Intent(getApplicationContext(), LauncherActivty.class);
    intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);

    //use the bundled url if it is there and we have more then 1 notification for this type
    if(amount > 1 && !bundledURL.equals("")){
        intent.putExtra("url", bundledURL);
    }else{
        intent.putExtra("url", url);
    }

    intent.putExtra("notification_group", notificationGroup);
    intent.putExtra("notification_group_id", notificationGroupID);
    intent.putExtra("notification_id", notificationID);
    intent.putExtra("is_group", isGroup);

    PendingIntent pendingIntent = PendingIntent.getActivity(getApplicationContext(), 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);

    notificationBuilder.setContentIntent(pendingIntent);
    NotificationManager notificationManager =  (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
    notificationManager.notify(notificationGroup, Constants.NOTIFICATION_ID, notificationBuilder.build());
0
Finn Marquardt 5 grudzień 2019, 14:14
Właśnie dodałem android:stopWithTask="false" i nadal nie dzwonił onMessagedReceived() w tle
 – 
Zorgan
5 grudzień 2019, 13:42
Hm ok, to dziwne, ponieważ w moim projekcie działa, wszystkie powiadomienia tworzę ręcznie w FCMService i działa to zarówno wtedy, gdy aplikacja jest w tle, jak i całkowicie zamknięta. czy usunąłeś oświadczenie return z kreacji przed testowaniem?
 – 
Finn Marquardt
5 grudzień 2019, 13:47
Tak, usunąłem oświadczenie return. Co masz na myśli, że utworzyłeś powiadomienia ręcznie? Stworzyłem swoją za pomocą Cloud Functions
 – 
Zorgan
5 grudzień 2019, 13:58
Wszystkie powiadomienia, które tworzę, są wykonywane w otrzymanych wiadomościach, w zasadzie otrzymuję tylko powiadomienia „wypychania” danych z fcm, a następnie tworzę powiadomienie za pomocą konstruktora: umieść faktyczne utworzenie powiadomienia w głównej odpowiedzi dla czytelności ;)
 – 
Finn Marquardt
5 grudzień 2019, 14:12