Skip to content
This repository has been archived by the owner on Dec 1, 2022. It is now read-only.

GcmListenerService.onMessageReceived not called #63

Open
void99 opened this issue Jun 12, 2015 · 25 comments
Open

GcmListenerService.onMessageReceived not called #63

void99 opened this issue Jun 12, 2015 · 25 comments
Assignees

Comments

@void99
Copy link

void99 commented Jun 12, 2015

Maybe not a proper place to post (not a demo issue), but could not find answer elsewhere: when sending both "data" and "notification" keys as payload notification is displayed but onMessageReceived method is not called. The method is properly called when "notification" key is removed from payload. What could be the cause?

@void99 void99 changed the title GcmListenerService.onMessageReceived not called when notification in payload is set GcmListenerService.onMessageReceived not called Jun 12, 2015
@alibitek
Copy link

Indeed, this seems to be the case. I've tested with a payload as follows:

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

The notification is displayed by the system, but the onMessageReceived(String from, Bundle data) method of the GcmListenerService implemention doesn't get called

In AndroidManifest.xml MyGcmListenerService is defined as follows:

 <!-- [START gcm_listener] -->
        <service
            android:name="com.company.myapp.service.MyGcmListenerService"
            android:exported="false" >
            <intent-filter>
                <action android:name="com.google.android.c2dm.intent.RECEIVE" />
            </intent-filter>
        </service>
        <!-- [END gcm_listener] -->

The server reference payload docs (https://developers.google.com/cloud-messaging/server#payload) says:
The app server can send a message including both notifications and data payloads. In such cases, GCM handles displaying the notification payload and the client app handles the data payload.

The "the client app handles the data payload" part doesn't work.
If I remove the notification key from the payload the method on the receiver is called.

@alibitek
Copy link

@void99

I think I found what's "the problem"

From https://developers.google.com/cloud-messaging/server#notifications_and_data_messages
"GCM will display the notification part on the client app’s behalf. When optional data is provided, it is sent to the client app once user clicks on the notification and opens the client app.
[...] On Android, data payload can be retrieved in the Intent used to launch your activity.
"

So, the data is passed in the intent used to launch the activity, once the user clicks on the notification.
This means you need to do the following:

  • Add a click_action to the notification key you send from the server:
    e.g.
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" } })

See the reference for notification payload at: https://developers.google.com/cloud-messaging/server-ref#notification-payload-support

  • In AndroidManifest.xml add an intent filter on the activity you want to be opened once the user clicks on the notification, with the same action name you used on the "click_action" key on the server side
    e.g.
         <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>
  • Get the data from the intent on your onCreate() method or on onNewIntent() if you've set the launchMode to singleTop for the activity you want to launch when the notification is clicked.
    e.g.
@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);
        }
}

I've tested this and can confirm that it works. (using XMPP connection)

@void99
Copy link
Author

void99 commented Jun 14, 2015

Thanks for Your explanation. But imo the implementation is kind of awkward. If the user dismisses the notification, the data will never be passed to application. Or am i missing something?

@alibitek
Copy link

Yes, that's the downside of letting the system handle the notification.

@void99 void99 closed this as completed Jun 14, 2015
@ZakTaccardi
Copy link

So what if I want the iOS app to use the notification payload, and the android app to use the data payload for displaying the notification? Seems like I am SoL.

Also, the notification icon is very limiting. On Lollipop, you cannot use a complex icon because it is automatically forced into a single color (makes the icon all white in my case. This doesn't seem right.

@joelSimpson
Copy link

I'm currently experiencing a consistent InternalServerError when trying to push a payload with the notification tag. I need this for my iOS app to display a banner notification when the app is in the background.

@StephenStrickland
Copy link

+1 having similar issues as well.

@afjackman
Copy link

@void99 Why is this closed? This problem pretty much makes it impossible to route iOS and Android traffic together through GCM if you want any processing to occur.

@joelSimpson and @StephenStrickland Make sure both body & title are set in the notification field. iOS doesn't use the title tag but it's required in order to send and may be the reason for this issue you're both having.

EDIT: Unfortunately, I'm now seeing the InternalServerError again. The above suggestion doesn't fix the problem.

@wildseansy
Copy link

Having the same problem as @ZakTaccardi trying to use Lollipop and support the same iOS notification body. This seems like it was overlooked.

@pato89xd
Copy link

hi, i have problems with the Constants.KEY_MESSAGE_TXT variable, it doesnt import

@alibitek
Copy link

@pato89xd You have to define that constant yourself. The above code is just an example, you have to adapt it for your own needs.

@pato89xd
Copy link

@mnemonicflow so there is no Constants class?

@alibitek
Copy link

@pato89xd You have to create it yourself.

@pato89xd
Copy link

@mnemonicflow sorry about that i'm new on android, I'm implementing this, thanks

@macecchi
Copy link

macecchi commented Feb 6, 2016

Is this being fixed? This bug makes it impossible to use GCM to both iOS and Android users.

@apognu
Copy link

apognu commented Feb 12, 2016

We are having the exact same issue.

It would suck to have to manage two different sets of GCM registration files to manage Android and iOS.

Any news on the matter?

@ogeidix
Copy link
Contributor

ogeidix commented Feb 12, 2016

The current implementation doesn't allow to send a message that is simultaneously a display notification for ios and a silent notification for android.

I understand the issue and I appreciate your feedback.
We might be able to cover it in a future update, but I cannot promise an ETA on this.

@jackdevco
Copy link

Hi I am new to android ,I have added custom additional data so that when the user clicks the notification, it opens the data I entered. However, it does not open. Anyone have a solution or an idea of the error I'm receiving?

@afarber
Copy link

afarber commented Feb 18, 2016

I have "an idea": show your source code.

On Thu, Feb 18, 2016 at 10:45 AM, jackdevco [email protected]
wrote:

Hi I am new to android ,I have added custom additional data so that when
the user clicks the notification, it opens the data I entered. However, it
does not open. Anyone have a solution or an idea of the error I'm receiving?


Reply to this email directly or view it on GitHub
#63 (comment).

@jackdevco
Copy link

Hi

Thank you for the feedback. Please see code below.

Appreciate the assistance.


MainActivity.java

package com.app.bradv_000.pushk;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.widget.ArrayAdapter;
import android.widget.ListView;

import com.pushwoosh.BasePushMessageReceiver;
import com.pushwoosh.BaseRegistrationReceiver;
import com.pushwoosh.PushManager;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.util.ArrayList;

public class MainActivity extends AppCompatActivity
{
private static final String bTAG = "example";

boolean broadcastPush = true;

JSONAdapter jsonAdapter;

private ListView list;

@Override
protected void onCreate(Bundle savedInstanceState)
{
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    //here we register receivers for push notifications
    registerReceivers();

    final PushManager pushManager = PushManager.getInstance(this);

    //Now we start the push manager, this will count app open for

Pushwoosh stats as well
try
{
pushManager.onStartup(this);
}
catch (Exception e)
{
e.printStackTrace();
}

    //now we register for push notification
    pushManager.registerForPushNotifications();

    //then check launch notification
    String launchNotification = pushManager.getLaunchNotification();
    if(launchNotification != null)
    {
        Log.d(bTAG, "Launch notification received" + launchNotification);
    }
    else
    {
        Log.d(bTAG, "No notification received");
    }

    //Clear application icon badge number
    pushManager.setBadgeNumber(0);
}

/**
 * Called when the activity receives a new intent.
 */
public void onNewIntent(Intent intent)
{
    super.onNewIntent(intent);
    //have to check if we've got new intent as a part of push notification
    try
    {
        checkMessage(intent);
    } catch (JSONException e)
    {
        e.printStackTrace();
    }

}

//Registration receiver
BroadcastReceiver mBroadcastReceiver = new BaseRegistrationReceiver()
{
    @Override
    public void onRegisterActionReceive(Context context, Intent intent)
    {
        try
        {
            checkMessage(intent);
        } catch (JSONException e)
        {
            e.printStackTrace();
        }
    }
};

//Push message receiver
private BroadcastReceiver mReceiver = new BasePushMessageReceiver()
{
    @Override
    protected void onMessageReceive(Intent intent)
    {
        //JSON_DATA_KEY contains JSON payload of push notification.
        try
        {
            doOnMessageReceive(intent.getExtras().getString(JSON_DATA_KEY));
        } catch (JSONException e)
        {
            e.printStackTrace();
        }
    }
};

//Registration of the receivers
public void registerReceivers()
{
    IntentFilter intentFilter = new IntentFilter(getPackageName()
  • ".action.PUSH_MESSAGE_RECEIVE");

    if (broadcastPush)
        registerReceiver(mReceiver, intentFilter, getPackageName()
    

    +".permission.C2D_MESSAGE", null);

    registerReceiver(mBroadcastReceiver, new
    

    IntentFilter(getPackageName() + "." +
    PushManager.REGISTER_BROAD_CAST_ACTION));

    }

    public void unregisterReceivers()
    {
    //Unregister receivers on pause
    try
    {
    unregisterReceiver(mReceiver);
    }
    catch (Exception e)
    {
    // pass.
    }

    try
    {
        unregisterReceiver(mBroadcastReceiver);
    }
    catch (Exception e)
    {
        //pass through
    }
    

    }

    @OverRide
    public void onPause()
    {
    super.onPause();

    //Unregister receivers on pause
    unregisterReceivers();
    

    }

    @OverRide
    public void onResume()
    {
    super.onResume();

    //Re-register receivers on resume
    registerReceivers();
    

    }

    /**

    • Will check PushWoosh extras in this intent, and fire actual method
      *
    • @param intent activity intent
      */
      private void checkMessage(Intent intent) throws JSONException
      {
      if (null != intent)
      {
      if (intent.hasExtra(PushManager.PUSH_RECEIVE_EVENT))
      {

doOnMessageReceive(intent.getExtras().getString(PushManager.PUSH_RECEIVE_EVENT));
}
else if (intent.hasExtra(PushManager.REGISTER_EVENT))
{

doOnRegistered(intent.getExtras().getString(PushManager.REGISTER_EVENT));
}
else if (intent.hasExtra(PushManager.UNREGISTER_EVENT))
{

doOnUnregistered(intent.getExtras().getString(PushManager.UNREGISTER_EVENT));
}
else if (intent.hasExtra(PushManager.REGISTER_ERROR_EVENT))
{

doOnRegisteredError(intent.getExtras().getString(PushManager.REGISTER_ERROR_EVENT));
}
else if (intent.hasExtra(PushManager.UNREGISTER_ERROR_EVENT))
{

doOnUnregisteredError(intent.getExtras().getString(PushManager.UNREGISTER_ERROR_EVENT));
}

        resetIntentValues();
    }
}

public void doOnRegistered(String registrationId)
{
    Log.d(bTAG, "registered: " + registrationId);
}

public void doOnRegisteredError(String errorId)
{
    Log.d(bTAG, "registration error: " + errorId);
}

public void doOnUnregistered(String registrationId)
{
    Log.d(bTAG, "unregistered: " + registrationId);
}

public void doOnUnregisteredError(String errorId)
{
    Log.d(bTAG, "deregistration error: " + errorId);
}

public void doOnMessageReceive(String message) throws JSONException
{
    ArrayList<String> user = new ArrayList<String>();

    Log.d(bTAG, "received push: " + message);
    JSONObject json  = new JSONObject("message");

    JSONArray array = json.getJSONArray("employees");

    for (int i=0; i<array.length(); i++)
    {
        JSONObject o = array.getJSONObject(i);
        String firstName = json.getString("firstName");
        user.add(firstName);
        System.out.println(o);
    }

    ArrayAdapter<String> arrayAdapter = new

ArrayAdapter(this, android.R.layout.simple_list_item_1, user);

    //Set the adapter as the adapter of choice for our list
    list.setAdapter(arrayAdapter);


    try
    {
        json = new JSONObject(message);
    }
    catch (JSONException e)
    {
        e.printStackTrace();
    }

    try
    {
        JSONObject userdataObject = json.getJSONObject("userdata");

        array = userdataObject.getJSONArray("employees");
    }
    catch (JSONException e)
    {
        e.printStackTrace();
    }


    for (int i=0; i<array.length();i++)
    {
        JSONObject o = null;
        try
        {
            o = array.getJSONObject(i);
        }
        catch (JSONException e)
        {
            e.printStackTrace();
        }
        try
        {
            Log.i("Testing this ...", o.getString("firstName"));
        }
        catch (JSONException e)
        {
            e.printStackTrace();
        }
        try
        {
            Log.i("Testing this ...", o.getString("lastName"));
        }
        catch (JSONException e)
        {
            e.printStackTrace();
        }
    }

}

/**
 * Will check main Activity intent and if it contains any

PushWoosh data, will clear it
*/
private void resetIntentValues()
{
Intent mainAppIntent = getIntent();

    if (mainAppIntent.hasExtra(PushManager.PUSH_RECEIVE_EVENT))
    {
        mainAppIntent.removeExtra(PushManager.PUSH_RECEIVE_EVENT);
    }
    else if (mainAppIntent.hasExtra(PushManager.REGISTER_EVENT))
    {
        mainAppIntent.removeExtra(PushManager.REGISTER_EVENT);
    }
    else if (mainAppIntent.hasExtra(PushManager.UNREGISTER_EVENT))
    {
        mainAppIntent.removeExtra(PushManager.UNREGISTER_EVENT);
    }
    else if (mainAppIntent.hasExtra(PushManager.REGISTER_ERROR_EVENT))
    {
        mainAppIntent.removeExtra(PushManager.REGISTER_ERROR_EVENT);
    }
    else if (mainAppIntent.hasExtra(PushManager.UNREGISTER_ERROR_EVENT))
    {
        mainAppIntent.removeExtra(PushManager.UNREGISTER_ERROR_EVENT);
    }

    setIntent(mainAppIntent);
}

}


UserNameAdapter.java (My custom Adapter)

package com.app.bradv_000.pushk;

import android.app.Activity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

/**

  • Created by bradv_000 on 2016/02/16.
    */
    class JSONAdapter extends BaseAdapter
    {
    private final Activity activity;
    private final JSONArray jsonArray;

    public JSONAdapter (Activity activity, JSONArray jsonArray)
    {
    assert activity != null;
    assert jsonArray != null;

    this.jsonArray = jsonArray;
    this.activity = activity;
    

    }

    @OverRide public int getCount() {
    if(null==jsonArray)
    return 0;
    else
    return jsonArray.length();
    }

    @OverRide public JSONObject getItem(int position) {
    if(null==jsonArray) return null;
    else
    return jsonArray.optJSONObject(position);
    }

    @OverRide public long getItemId(int position) {
    JSONObject jsonObject = getItem(position);

    return jsonObject.optLong("id");
    

    }

    @OverRide public View getView(int position, View convertView,
    ViewGroup parent)
    {

    if (convertView == null)
        convertView =
    

    activity.getLayoutInflater().inflate(R.layout.user_name_list, null);

    TextView text_list = (TextView)convertView.findViewById(R.id.text_list);
    
    JSONObject json_data = getItem(position);
    
    if(null!=json_data )
    {
        try
        {
            text_list.setText(json_data.getString("firstName"));
        }
        catch (JSONException e) {
            e.printStackTrace();
        }
    }
    
    return convertView;
    

    }

}


activity_main.xml

<ListView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:id="@+id/list"/>

username_list.xml

<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:id="@+id/text_list">

</TextView>

On Thu, Feb 18, 2016 at 1:46 PM, Alexander Farber [email protected]
wrote:

I have "an idea": show your source code.

On Thu, Feb 18, 2016 at 10:45 AM, jackdevco [email protected]
wrote:

Hi I am new to android ,I have added custom additional data so that when
the user clicks the notification, it opens the data I entered. However,
it
does not open. Anyone have a solution or an idea of the error I'm
receiving?


Reply to this email directly or view it on GitHub
#63 (comment).


Reply to this email directly or view it on GitHub
#63 (comment).

@KirillMakarov
Copy link

In additional, when I have only data field (without notification) and "content_available": true, then GcmListenerService.onMessageReceived is not called. "content_available": true is needed for iOS, but it breaks data payload on Android. I removed "content_available": true on App Server for messages, which go to Android, and it is worked for me.

@ogeidix
Copy link
Contributor

ogeidix commented Apr 6, 2016

@KirillMakarov the issue you mentioned is being investigated in #178

@jimmyFlash
Copy link

i'm only using the data payload in my android app , because i want the application to handle creating notifications , not GCM , problem is that when app. is in background the "onMessageReceived " method is never triggered , i don't want to use both notification and data payloads and pass data when the user clicks the notification to my activity this seems too awkward , appreciate any suggestions

@KirillMakarov
Copy link

Can you post json which your app server post to gcm server for data notification?

@yayah
Copy link

yayah commented Jun 14, 2016

Yes
On 14 Jun 2016 09:32, "Kirill Makarov" [email protected] wrote:

Can you post json which your app server post to gcm server for data
notification?


You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
#63 (comment), or mute
the thread
https://github.com/notifications/unsubscribe/AGZ2dJjJhedl4rnBvv9VzN4rqYto_Prcks5qLnUYgaJpZM4FBGQU
.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests