1

I have chat system using firebase for notification/push message on android (using restfull api for send message to firebase with rails & fcm gems). I'm using free account firebase. The chat system is fine without blast some messages to one receiver (e.g 5 or more messages in seconds). The Fcm callbacks are all successfully sent to firebase in backend log (using rails). e.g log :

{
  "multicast_id":7122767959146612142,
  "success":1,
  "failure":0,
  "canonical_ids":0,
  "results":[
    {
        "message_id":"0:1493177420664636%a2c0fa75b971369c"
    }
  ]
}

code in rails :

def send_message(message, registration_ids, collapse_key)
 fcm = FCM.new(FCM_API_KEY)
 options = { data: message, collapse_key: collapse_key }
 response = fcm.send(registration_ids, options)
end

on android :

public void onMessageReceived(RemoteMessage message) {
        Log.d("FCM", "onMessageReceived: " + App.getInstance().getGson().toJson(message.getData()));
       // other stuff here
}

but The device not receiving any notification from firebase after blast some messages (without output logger of firebase notification in device). I don't know how I can trace the mistake of code,I think backend (rails apps) and front end (android apps) are fine (normal message successfully), I can't check full log on firebase console. is there a limit to how much message I can use in one time?

example message :

{  
   "data": "{
     \"firstname\":\"Ani\",
     \"lastname\":\"Emly\",
     \"image_url\":\"\",
     \"sub_intent_question_id\":\"\",
     \"created_at\":\"2017-04-26T05:29:02.866Z\",
     \"updated_at\":\"2017-04-26T05:29:02.866Z\",
     \"total_unread_count\":0,
     \"unread_counts\": [{\"unread_count\":0,\"id\":\"58c9f7719443790c480003e2\"}],
     \"is_multiple_answer\":false,
     \"content\":\"ggh\",
     \"is_choice\":false,
     \"is_answerable\":true,
     \"user_picture\":\"\",
     \"payload\":null,
     \"user_id\":\"5786ff28150cd4233f003f1d\",
     \"driver_id\":\"582d4b2eedaba85243009d4a\",
     \"options\":[],
     \"id\":\"58c9f7719443790c480003e2\",
     \"username\":\"username\"
   }",
   "category":"reply_object"
}
itx
  • 1,327
  • 1
  • 15
  • 38
  • put your code here – Bhupat Bheda Apr 26 '17 at 05:15
  • There is no message limit that you could send with FCM. It's kinda hard to picture what's on your payload. Could you post a sample payload structure? – AL. Apr 26 '17 at 05:45
  • @AL. I have add a sample of message. FYI if I turn off and turn on again of internet on receiver and The message was received. – itx Apr 26 '17 at 09:45
  • Thanks itx. The payload looks okay. It's possible that this is an issue with connectivity, but I can't say for sure. Have you tried setting the `priority` to `high`? – AL. Apr 26 '17 at 09:50
  • @AL.I have try set priority to high, but didn't change. – itx May 19 '17 at 06:57
  • @AL. how about this https://firebase.google.com/docs/cloud-messaging/android/upstream, I have try again for check pattern and stuck in 20 messages. – itx May 22 '17 at 01:32
  • Hey itx. Sorry I wasn't able to get back to you here.. I'm having a hard time figuring out what's wrong here. It might be possible that it is related to the *message blast* you're doing. Are you positive that there is no error like [rate exceeded](http://stackoverflow.com/a/40241595/4625829) is being returned? – AL. May 22 '17 at 04:04
  • @AL.Thanks bro, Finally I found the solution.. – itx May 22 '17 at 05:05
  • How to check whether the response is success or not? – Thananjaya S Sep 03 '19 at 15:39

3 Answers3

0

try this :

MyFirebaseInstanceIDService

public class MyFirebaseInstanceIDService extends FirebaseInstanceIdService  {

    private static final String TAG = "MyFirebaseIIDService";


    @Override
    public void onTokenRefresh() {

        //Getting registration token
        String refreshedToken = FirebaseInstanceId.getInstance().getToken();

        //Displaying token on logcat
        Log.d(TAG, "Refreshed token: " + refreshedToken);
        sendRegistrationToServer(refreshedToken);



    }


    }




}

MyFirebaseMessagingService

 public class MyFirebaseMessagingService extends FirebaseMessagingService {

        private static final String TAG = "MyFirebaseMsgService";

        /**
         * Called when message is received.
         *
         * @param remoteMessage Object representing the message received from Firebase Cloud Messaging.
         */
        // [START receive_message]
        @Override
        public void onMessageReceived(RemoteMessage remoteMessage) {

            Log.d(TAG, "From: " + remoteMessage.getFrom());

            // Check if message contains a data payload.
            if (remoteMessage != null && remoteMessage.getData().size() > 0) {
                Log.d(TAG, "Message data payload: " + remoteMessage.getData());
                try {
                    JSONObject json = new JSONObject(remoteMessage.getData().toString());
                    sendPushNotification(json);
                } catch (Exception e) {
                    Log.e(TAG, "Exception: " + e.getMessage());
                }
            }

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


        }
        // [END receive_message]

        /**
         * Create and show a simple notification containing the received FCM message.
         *
         * @param messageBody FCM message body received.
         */
        private void sendNotification(String messageBody) {
            Intent intent = new Intent(this, MainActivity.class);
            intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
            PendingIntent pendingIntent = PendingIntent.getActivity(this, 0 /* Request code */, intent,
                    PendingIntent.FLAG_ONE_SHOT);

            Uri defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
            NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
                    .setSmallIcon(R.drawable.ic_app_icon)
                    .setContentTitle("Chetan ram say to you:")
                    .setContentText(messageBody)
                    .setAutoCancel(true)
                    .setSound(defaultSoundUri)
                    .setContentIntent(pendingIntent);

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

            notificationManager.notify(0 /* _ID of notification */, notificationBuilder.build());
        }

        //this method will display the notification
        //We are passing the JSONObject that is received from
        //firebase cloud messaging
        private void sendPushNotification(JSONObject json) {
            //optionally we can display the json into log
            Log.e(TAG, "Notification JSON " + json.toString());
            try {
                //getting the json data
                JSONObject data = json.getJSONObject("data");

                //parsing json data
                String title = data.getString("title");
                String message = data.getString("message");
                String imageUrl = data.getString("image");

                //creating MyNotificationManager object
                MyNotificationManager mNotificationManager = new MyNotificationManager(getApplicationContext());

                //creating an intent for the notification
                Intent intent = new Intent(getApplicationContext(), MainActivity.class);

                try {
                    if (data.has("details") && data.getJSONObject("details") != null) {
                        Log.e("enter", "enter");
                        intent.putExtra(Constants.AC_LOTTERY_DETAILS, data.getJSONObject("details").toString());
                        intent.putExtra(Constants.FROM_PUSHNOTIFICATION,true);
                    }
                }catch (Exception e)
                {

                }

                //if there is no image
                if (imageUrl.equals("null")) {
                    //displaying small notification
                    mNotificationManager.showSmallNotification(title, message, intent);
                } else {
                    //if there is an image
                    //displaying a big notification
                    mNotificationManager.showBigNotification(title, message, imageUrl, intent);
                }
            } catch (JSONException e) {
                Log.e(TAG, "Json Exception: " + e.getMessage());
            } catch (Exception e) {
                Log.e(TAG, "Exception: " + e.getMessage());
            }
        }
    }                    intent.putExtra(Constants.FROM_PUSHNOTIFICATION,true);
                    }
                }catch (Exception e)
                {

                }

                //if there is no image
                if (imageUrl.equals("null")) {
                    //displaying small notification
                    mNotificationManager.showSmallNotification(title, message, intent);
                } else {
                    //if there is an image
                    //displaying a big notification
                    mNotificationManager.showBigNotification(title, message, imageUrl, intent);
                }
            } catch (JSONException e) {
                Log.e(TAG, "Json Exception: " + e.getMessage());
            } catch (Exception e) {
                Log.e(TAG, "Exception: " + e.getMessage());
            }
        }
    }

MyNotificationManager

public class MyNotificationManager {

    public int ID_BIG_NOTIFICATION = 234;
    public int ID_SMALL_NOTIFICATION = 235;

    private Context mCtx;

    public MyNotificationManager(Context mCtx) {
        this.mCtx = mCtx;
        ID_BIG_NOTIFICATION = getRandom();
        ID_SMALL_NOTIFICATION = getRandom();
    }

    private int getRandom() {
        Random random = new Random();

        return random.nextInt(99999) + 1;
    }

    //the method will show a big notification with an image
    //parameters are title for message title, message for message text, url of the big image and an intent that will open
    //when you will tap on the notification
    public void showBigNotification(String title, String message, String url, Intent intent) {
        PendingIntent resultPendingIntent =
                PendingIntent.getActivity(
                        mCtx,
                        ID_BIG_NOTIFICATION,
                        intent,
                        PendingIntent.FLAG_UPDATE_CURRENT
                );
        NotificationCompat.BigPictureStyle bigPictureStyle = new NotificationCompat.BigPictureStyle();
        bigPictureStyle.setBigContentTitle(title);
        bigPictureStyle.setSummaryText(Html.fromHtml(message).toString());
        bigPictureStyle.bigPicture(getBitmapFromURL(url));
        NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(mCtx);
        Notification notification;
        notification = mBuilder.setSmallIcon(R.mipmap.ic_launcher).setTicker(title).setWhen(0)
                .setAutoCancel(true)
                .setContentIntent(resultPendingIntent)
                .setContentTitle(title)
                .setStyle(bigPictureStyle)
                .setDefaults(Notification.DEFAULT_VIBRATE|Notification.DEFAULT_SOUND|Notification.DEFAULT_LIGHTS)
                .setSmallIcon(R.drawable.ic_app_icon)
                .setLargeIcon(BitmapFactory.decodeResource(mCtx.getResources(), R.drawable.ic_app_icon))
                .setContentText(message)
                .build();

        notification.flags |= Notification.FLAG_AUTO_CANCEL;

        NotificationManager notificationManager = (NotificationManager) mCtx.getSystemService(Context.NOTIFICATION_SERVICE);
        notificationManager.notify(ID_BIG_NOTIFICATION, notification);
    }

    //the method will show a small notification
    //parameters are title for message title, message for message text and an intent that will open
    //when you will tap on the notification
    public void showSmallNotification(String title, String message, Intent intent) {
        PendingIntent resultPendingIntent =
                PendingIntent.getActivity(
                        mCtx,
                        ID_SMALL_NOTIFICATION,
                        intent,
                        PendingIntent.FLAG_UPDATE_CURRENT
                );


        NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(mCtx);
        Notification notification;
        notification = mBuilder.setSmallIcon(R.mipmap.ic_launcher).setTicker(title).setWhen(0)
                .setAutoCancel(true)
                .setContentIntent(resultPendingIntent)
                .setContentTitle(title)
                .setSmallIcon(R.drawable.ic_app_icon)
                .setLargeIcon(BitmapFactory.decodeResource(mCtx.getResources(), R.drawable.ic_app_icon))
                .setContentText(message)
                .build();

        notification.flags |= Notification.FLAG_AUTO_CANCEL;

        NotificationManager notificationManager = (NotificationManager) mCtx.getSystemService(Context.NOTIFICATION_SERVICE);
        notificationManager.notify(ID_SMALL_NOTIFICATION, notification);
    }

    //The method will return Bitmap from an image URL
    private Bitmap getBitmapFromURL(String strURL) {
        try {
            URL url = new URL(strURL);
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            connection.setDoInput(true);
            connection.connect();
            InputStream input = connection.getInputStream();
            Bitmap myBitmap = BitmapFactory.decodeStream(input);
            return myBitmap;
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }
}

AndroidManifest file

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

        <service
            android:name=".Listeners.MyFirebaseInstanceIDService">
            <intent-filter>
                <action android:name="com.google.firebase.INSTANCE_ID_EVENT"/>
            </intent-filter>
        </service>

make sure google-services.json file put in your app directory

Bhupat Bheda
  • 1,968
  • 1
  • 8
  • 13
0

It's not about blast some message, but The problem is because I'm using device group messages :

def send_message(message, registration_ids, collapse_key)
 fcm = FCM.new(FCM_API_KEY)
 options = { data: message, collapse_key: collapse_key }
 response = fcm.send(registration_ids, options)
end

I'm use send/send_notification method, that method means, send message to multiple registration id (registration_ids). I didn't find any documentation about limit on device group messages, but I found this doc https://firebase.google.com/docs/cloud-messaging/android/upstream, on that doc say's

With FirebaseMessaging, you can implement the callbacks onMessageSent and onSendError to check the status of upstream messages. In error cases, onSendError returns a SendException with an error code. For example, if the client attempts to send more messages after the 20-message limit is reached, it returns SendException#ERROR_TOO_MANY_MESSAGES.

I don't now relation about my problem with that documentation but I get 20 message limit on last tested.

And now, The solution is using paremeter to instead of registration_ids. Here about Data Message.

For the solution on rails I'm use send_with_notification_key method :

fcm = FCM.new(FCM_API_KEY)
options = { data: message }
response = fcm.send_with_notification_key(send_to, options)
itx
  • 1,327
  • 1
  • 15
  • 38
0

Actually the issue seems to be because of collapse_key.

Scenario: I send 20 pushes in a small time frame (1 minute), using some collapse_key. All these messages are received by the device (as it is online). When I try to send new pushes, only the last one will be received, and this happens exactly after 3 minutes (after the 20 push limit is exceeded). So then the device is able to receive 1 push every 3 minutes.

This issue happens only when I use a collapse_key. If I don't use a collapse_key, then there seems to be no limit. The count resets in some cases, for example when the device restarts or there is a network change.

Kaido
  • 1
  • 1