1
votes

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"
}
3
put your code hereBhupat Bheda
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.
@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
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.
@AL.I have try set priority to high, but didn't change.itx

3 Answers

0
votes

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

0
votes

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)
0
votes

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.