2015-07-02 12 views
14

Obecnie pracuję nad wprowadzeniem powiadomień GCM do mojej aplikacji.GcmListenerService.onMessageReceived() nie nazywane

Problem, który mam, polega na tym, że metoda onMessageReceived() z mojej implementacji GcmListenerService nie jest wywoływana. Otrzymuję dane z serwerów GCM w porządku, ponieważ automatycznie generują powiadomienie (chcę zastąpić to moim własnym powiadomieniem przy użyciu metody onMessageReceived()), ale po tym czasie żadne z moich zgłoszeń dziennika nie są drukowane w dzienniku.

JSON, który jest wysyłany z serwera na serwer GCM

{ 
    "notification" : { 
     "title" : "Title", 
     "text" : "Message", 
     "icon" : "@drawable\/ic_notification", 
     "click_action" : "OPEN_MAIN_ACTIVITY" 
    }, 
    "registration_ids":[ 
     "xxxx", "xxxx", "xxxx", "etc" 
    ] 
} 

AndroidManifest.xml (tylko część GCM)

<!-- GCM START --> 
    <receiver 
     android:name="com.google.android.gms.gcm.GcmReceiver" 
     android:exported="true" 
     android:permission="com.google.android.c2dm.permission.SEND" > 
     <intent-filter> 
      <action android:name="com.google.android.c2dm.intent.RECEIVE" /> 
      <category android:name="com.my.package" /> 
     </intent-filter> 
    </receiver> 

    <service 
     android:name=".Services.ListenerService" 
     android:exported="false" > 
     <intent-filter> 
      <action android:name="com.google.android.c2dm.intent.RECEIVE" /> 
     </intent-filter> 
    </service> 

    <service 
     android:name=".Services.IDListenerService" 
     android:exported="false"> 
     <intent-filter> 
      <action android:name="com.google.android.gms.iid.InstanceID"/> 
     </intent-filter> 
    </service> 
    <!-- GCM END --> 

GcmListenerService (tylko szybkie druku, aby zobaczyć, czy jego w ogóle wywoływana)

public class ListenerService extends GcmListenerService { 

    private static final String TAG = "MyGcmListenerService"; 

    @Override 
    public void onMessageReceived(String from, Bundle data) { 
     String message = data.getString("title"); 
     Log.d(TAG, "From: " + from); 
     Log.d(TAG, "Message: " + message); 
    } 
} 

Nie wiem, czy metoda wnioskowania o tokeny jest istotna, ale mogę ją opublikować w razie potrzeby.

Jeśli jakaś część pytania jest niejasna, daj mi znać, nie jestem najlepszy w wyjaśnianiu.

+0

Czy zarejestrowałeś swojego klienta? – Gordak

+0

Otrzymuję token, a nawet powiadomienia (myślę, że auto GCM je generuje lub coś takiego), jeśli to masz na myśli? – Dan

+0

Jeśli skonfigurowałeś klienta zgodnie z https://developers.google.com/cloud-messaging/android/client, wszystko powinno być w porządku. Nie zapomnij wysłać tokena gcm do swojej aplikacji na serwerze (nie widzę tu kodu rejestracyjnego). – Gordak

Odpowiedz

12

Jak wyjaśniono w this GitHub kwestii, która jest dokładnie twój problem:

Od https://developers.google.com/cloud-messaging/server#notifications_and_data_messages „GCM wyświetli część powiadomienia w imieniu aplikacji klienckiej Po dostarczeniu danych opcjonalnych jest ona wysyłana do aplikacji klienckiej, gdy użytkownik kliknie powiadomienie i otworzy aplikację kliencką [...] Na Androidzie, ładunek danych może zostać odzyskane w intencji użytej do uruchomienia twojej aktywności. . "

Tak, dane są przekazywane w intencji używany do uruchomienia działalności, gdy użytkownik kliknie powiadomienia Oznacza to, że trzeba wykonać następujące czynności:

  • Dodaj click_action do klucza powiadomienia wysyłanego z serwera: np.

    send_queue.append({'to': REGISTRATION_ID, 
           'message_id': random_id(), 
           "notification" : { 
            "body" : "Hello from Server! What is going on? Seems to work!!!", 
            "title" : "Hello from Server!", 
            "icon" : "@drawable/ic_school_white_48dp", 
            "sound": "default", 
            "color": "#03A9F4", 
            "click_action": "OPEN_MAIN_ACTIVITY" 
           }, 
           'data': { 'message': "Hello" }}) 
    

Zobacz odniesienie do powiadomienia o ładowności w: https://developers.google.com/cloud-messaging/server-ref#notification-payload-support

  • W AndroidManifest.xml dodać filtr intencyjny w sprawie aktywności chcesz być otwarte po użytkownik kliknie na zgłoszenia, z tę samą nazwę akcji, która była używana w kluczu "click_action" po stronie serwera, na przykład:

    <activity 
        android:name=".ui.MainActivity" 
        android:label="@string/title_activity_main" > 
        <intent-filter> 
         <action android:name="OPEN_MAIN_ACTIVITY" /> 
         <category android:name="android.intent.category.DEFAULT" /> 
        </intent-filter> 
    </activity> 
    
  • uzyskać dane z zamiarem na onCreate() metody lub na onNewIntent() jeśli już ustawić launchMode do singleTop za działalność, którą chcesz uruchomić, gdy zgłoszenie zostanie kliknięty, np:

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
        super.onCreate(savedInstanceState); 
    
        Intent intent = getIntent(); 
    
        if (intent.hasExtra(Constants.KEY_MESSAGE_TXT)) { 
         String message = intent.getStringExtra(Constants.KEY_MESSAGE_TXT); 
         Log.d(TAG, message); 
        } 
    } 
    

Przetestowałem to i może potwierdzić, że to działa. (przy użyciu połączenia XMPP)

+0

Naprawiłem problem, natknąłem się na ten problem z Githubem wcześniej, ale nie przeczytałem go prawidłowo, dzięki za wyjaśnienie. Czy istnieje sposób aktualizacji powiadomień po stronie klienta? Jak nie dostać spammed przez 4 identyczne powiadomienia, ale tylko jeden? Sortof w ten sposób: http://imgur.com/a/DlJV0 – Dan

+2

@Dan Jeśli używasz klawisza powiadomień, możesz ustawić klucz "tag" dla każdego powiadomienia, które jest takie samo jak poprzedni, i nowe powiadomienie z ten sam tag zastąpi poprzedni w centrum powiadomień. Zobacz opis klucza "tag" [tutaj] (https://developers.google.com/cloud-messaging/server-ref#notification-payload-support). Zobacz także ["collapse_key"] (https://developers.google.com/cloud-messaging/server-ref#table1) i delay_while_idle, które są przydatne do poinformowania GCM o tym, co dzieje się w scenariuszach, gdy powiadomienie nie może być dostarczony od razu, a ty możesz spróbować ponownie. – bitek

+1

Jeśli nie używasz klawisza powiadomień, ale klucz "dane", musisz samemu dokonać wykluczenia, śledząc wyświetlane wcześniej powiadomienia. – bitek

3

Aby odebrać wiadomość w trybie "Czytaj dalej", należy zdefiniować pole "data" najwyższego poziomu w obiekcie wiadomości. Pole powiadomień jest obsługiwane automatycznie i generuje powiadomienie. W usłudze "Moja wiadomość" nie przekazuje się żadnych danych w polu powiadomień.

Aktualizacja obiekt wiadomość zawierać pole danych i onMessageReceived powinna nazywać się:

 
{ 
    "notification" : { 
     "title" : "Title", 
     "text" : "Message", 
     "icon" : "@drawable\/ic_notification", 
     "click_action" : "OPEN_MAIN_ACTIVITY" 
    }, 
    "data": { 
     "some_key": "some_value" 
    }, 
    "registration_ids":[ 
     "xxxx", "xxxx", "xxxx", "etc" 
    ] 
} 
+2

Spróbuję, kiedy wrócę dziś do domu. Czy istnieje sposób, aby pole powiadomień nie generowało automatycznie powiadomienia na Androida, aby móc korzystać z własnej implementacji? Najlepiej bez usuwania całego pola powiadomień, ponieważ używam go w systemie iOS. – Dan

+0

Nie mogę wymyślić dobrego sposobu robienia tego. Możesz spróbować pominąć pole ikon, ponieważ jest wymagane na Androidzie, ale nie na iOS. Zakładam więc, że zostanie on zignorowany na Androidzie, ale nadal otrzymasz część danych onMessageReceived. –

+1

Usunięcie bloku "powiadomień" całkowicie załatwiło sprawę i zadzwoniło doMessageReceived. Nie jest dokładnie taki, jak tego chcę, ale znajdę sposób, żeby sobie z tym poradzić. Czy wiesz, czy możliwe jest zwijanie wielu powiadomień w jeden, aby użytkownik nie został zasypany powiadomieniami? Zobacz http://imgur.com/a/DlJV0 dla przykładowego obrazu (sortof) – Dan

4

Funkcja GcmListenerService.onMessageReceived() nie zostanie wywołana, jeśli wiadomość niższego rzędu (json) zawiera powiadomienie.

+2

Aby opracować punkt @ Zephyr, istnieją [dwa rodzaje ładunków w wiadomości GCM] (https://developers.google.com/cloud-messaging/concept-options): Powiadomienia i komunikaty danych. Powiadomienia nie wywołują metody 'onMessageReceived', jeśli aplikacja nie jest aktywna. Powodują tylko wyświetlanie powiadomienia w zasobniku powiadomień. Wiadomości danych spowodują, że komenda 'onMessageReceived' będzie wywoływana przez cały czas, niezależnie od stanu aplikacji. Zobacz szczegóły [tutaj] (http://stackoverflow.com/a/35368530/936761) – Shiprack

0

onMessageReceived wywoływana tylko w przypadku masaży typu "tylko do przesyłania danych".

Powiązane problemy