0

I am working on an app based on device to device push notifications. My notifications are working fine when the app is in foreground. But it doesn't work as per requirement, when the app is in background or killed state. onMessageReceived() doesn't get called in that case. I have a custom notification which has two buttons (Accept and Reject). When the app is in background or in killed state, I am able to get the notification, but the action buttons don't appear. But when the app is in foreground, it works perfectly. Can you guys please help me this? I am stuck in this for long now.

Note: I am using FCM to generate push notifications. And the payload is in index.js file. Payload contains both 'data' and 'notification', because notifications need to get generated in both Android and iOS. I read somewhere that removing 'notification' from payload will make it work perfectly in foreground, background and killed state, and it does too, but that doesn't match my requirement as I need both 'data' and 'notifications'.

Please help me out!!

public class FirebaseNotifications extends FirebaseMessagingService {
    @Override
    public void onMessageReceived(RemoteMessage remoteMessage) {
        Map<String, String> remoteMessageData = remoteMessage.getData();

        String remoteMessageType = remoteMessageData.get(REMOTE_TYPE);

        /*E-Intercom Notification requires Users Action*/
        if (remoteMessageType.equals(getString(R.string.e_intercom))) {
            String message = remoteMessageData.get(REMOTE_MESSAGE);
            String profilePhoto = remoteMessageData.get(REMOTE_PROFILE_PHOTO);
            String notificationUID = remoteMessageData.get(REMOTE_NOTIFICATION_UID);
            String userUID = remoteMessageData.get(REMOTE_USER_UID);
            String visitorType = remoteMessageData.get(REMOTE_VISITOR_TYPE);
            String visitorMobileNumber = remoteMessageData.get(REMOTE_VISITOR_MOBILE_NUMBER);

            RemoteViews remoteViews = new RemoteViews(getPackageName(), R.layout.layout_custom_notification);

            remoteViews.setTextViewText(R.id.textNotificationMessage, message);

            /*We don't want to show Profile image if cabs and packages enter into society*/
            if (visitorType.equals(FIREBASE_CHILD_CABS) || visitorType.equals(FIREBASE_CHILD_PACKAGES)) {
                remoteViews.setViewVisibility(R.id.eIntercomProfilePic, View.GONE);
            } else {
                remoteViews.setImageViewBitmap(R.id.eIntercomProfilePic, getBitmapFromURL(profilePhoto));
            }

            NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
            String channelId;

            /*To support Android Oreo Devices and higher*/
            if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
                NotificationChannel mChannel = new NotificationChannel(
                        getString(R.string.default_notification_channel_id), getString(R.string.namma_apartments_channel), NotificationManager.IMPORTANCE_HIGH);
                Objects.requireNonNull(notificationManager).createNotificationChannel(mChannel);
                channelId = mChannel.getId();
                IntentFilter actionIntents = new IntentFilter();
                actionIntents.addAction(ACCEPT_BUTTON_CLICKED);
                actionIntents.addAction(REJECT_BUTTON_CLICKED);
                getApplicationContext().registerReceiver(new ActionButtonListener(), actionIntents);
            } else {
                channelId = getString(R.string.default_notification_channel_id);
            }

            Notification notification = new NotificationCompat.Builder(this, channelId)
                    .setSmallIcon(R.drawable.namma_apartment_notification)
                    .setContentTitle(NOTIFICATION_EXPAND_TITLE)
                    .setContentText(NOTIFICATION_EXPAND_MSG)
                    .setAutoCancel(true)
                    .setCustomBigContentView(remoteViews)
                    .setSound(RingtoneManager.getDefaultUri(Notification.DEFAULT_SOUND))
                    .setPriority(PRIORITY_DEFAULT)
                    .build();

            int mNotificationID = (int) System.currentTimeMillis();

            Intent acceptButtonIntent = new Intent(ACCEPT_BUTTON_CLICKED);
            acceptButtonIntent.putExtra(NOTIFICATION_ID, mNotificationID);
            acceptButtonIntent.putExtra(NOTIFICATION_UID, notificationUID);
            acceptButtonIntent.putExtra(USER_UID, userUID);
            acceptButtonIntent.putExtra(MESSAGE, message);
            acceptButtonIntent.putExtra(VISITOR_TYPE, visitorType);
            acceptButtonIntent.putExtra(VISITOR_PROFILE_PHOTO, profilePhoto);
            acceptButtonIntent.putExtra(VISITOR_MOBILE_NUMBER, visitorMobileNumber);
            PendingIntent acceptPendingIntent = PendingIntent.getBroadcast(this, 123, acceptButtonIntent, PendingIntent.FLAG_UPDATE_CURRENT);
            remoteViews.setOnClickPendingIntent(R.id.buttonAccept, acceptPendingIntent);

            Intent rejectButtonIntent = new Intent(REJECT_BUTTON_CLICKED);
            rejectButtonIntent.putExtra(NOTIFICATION_ID, mNotificationID);
            rejectButtonIntent.putExtra(NOTIFICATION_UID, notificationUID);
            rejectButtonIntent.putExtra(USER_UID, userUID);
            rejectButtonIntent.putExtra(VISITOR_TYPE, visitorType);
            PendingIntent rejectPendingIntent = PendingIntent.getBroadcast(this, 123, rejectButtonIntent, PendingIntent.FLAG_UPDATE_CURRENT);
            remoteViews.setOnClickPendingIntent(R.id.buttonReject, rejectPendingIntent);

            Objects.requireNonNull(notificationManager).notify(mNotificationID, notification);
        } else {

            /*General Notification - These do not require any user actions*/
            String message = remoteMessageData.get(REMOTE_MESSAGE);

            NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);

            int mNotificationID = (int) System.currentTimeMillis();

            /*To support Android Oreo Devices and higher*/
            if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
                NotificationChannel mChannel = new NotificationChannel(
                        getString(R.string.default_notification_channel_id), getString(R.string.namma_apartments_channel), NotificationManager.IMPORTANCE_HIGH);
                Objects.requireNonNull(notificationManager).createNotificationChannel(mChannel);
            }
            /*After the Admin adds a notice and user receives notification, making sure user is navigated
             * to 'Notice Board' screen on press of notification in notification panel*/
            if (remoteMessageType.equals(getString(R.string.notice_board_notification))) {
                Intent noticeBoardIntent = new Intent(this, NoticeBoard.class);

                PendingIntent pendingIntent = PendingIntent.getActivity(this, Constants.NEW_NOTICE_CODE,
                        noticeBoardIntent, PendingIntent.FLAG_UPDATE_CURRENT);

                Notification noticeBoardNotification = new NotificationCompat.Builder(this, getString(R.string.default_notification_channel_id))
                        .setSmallIcon(R.drawable.namma_apartment_notification)
                        .setAutoCancel(true)
                        .setContentTitle(getString(R.string.app_name))
                        .setContentText(message)
                        .setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION))
                        .setPriority(PRIORITY_DEFAULT)
                        .setContentIntent(pendingIntent)
                        .build();

                Objects.requireNonNull(notificationManager).notify(mNotificationID, noticeBoardNotification);
            } else {
                Notification notificationDefault = new NotificationCompat.Builder(this, getString(R.string.default_notification_channel_id))
                        .setSmallIcon(R.drawable.namma_apartment_notification)
                        .setAutoCancel(true)
                        .setContentTitle(getString(R.string.app_name))
                        .setContentText(message)
                        .setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION))
                        .setPriority(PRIORITY_DEFAULT)
                        .build();

                Objects.requireNonNull(notificationManager).notify(mNotificationID, notificationDefault);

            }
        }
    }

    public 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 getCircleBitmap(myBitmap);
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }

    private Bitmap getCircleBitmap(Bitmap bitmap) {
        final Bitmap output = Bitmap.createBitmap(bitmap.getWidth(),
                bitmap.getHeight(), Bitmap.Config.ARGB_8888);
        final Canvas canvas = new Canvas(output);

        final int color = Color.RED;
        final Paint paint = new Paint();
        final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
        final RectF rectF = new RectF(rect);

        paint.setAntiAlias(true);
        canvas.drawARGB(0, 0, 0, 0);
        paint.setColor(color);
        canvas.drawOval(rectF, paint);

        paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
        canvas.drawBitmap(bitmap, rect, rect, paint);

        bitmap.recycle();

        return output;
    }
}
Saurabh
  • 434
  • 1
  • 4
  • 12
Ashish Jha
  • 173
  • 1
  • 3
  • 18
  • You can get answer from here https://stackoverflow.com/questions/37711082/how-to-handle-notification-when-app-in-background-in-firebase – Tayyab Amin Sep 10 '18 at 04:50
  • What about your android manifest file where you added this receiver – Shaon Sep 10 '18 at 06:37

1 Answers1

0

For this purpose you can try this technique. When you store FCM Token in DB add a bit or variable (device_type) in db that is used to store the device type like if FCM Token is come from IOS then add IOS in device_type and if it from android do this same for android device, then at the time of sending notification u can check if FCM Token is android type send just Data payload and if it is IOS type sent both Notification and Data Payload.

A. Wahab
  • 120
  • 1
  • 8
  • How do I get the device type? Like I know how to get the device version, but how will I know whether its Android or iOS? – Ashish Jha Sep 10 '18 at 06:46
  • Save Constants in App Like (ANDROID or IOS ) when you call api for FCM TOKEN from android device send the param ANDROID and when you call api from ios device send the param IOS Like this (i will show code of android side) `Map params = new HashMap(); params.put(ApiConfig.DEVICE_TYPE, "android"); // This field is use to send token on basis of device type params.put(ApiConfig.DEVICE_PUSH_TOKEN, token); new NetworkUtils(this).postForm(ApiConfig.FCM_TOKEN_REG, this, params, false, ApiConfig.FCM_TOKEN_FLAG, null);` – A. Wahab Sep 10 '18 at 07:14
  • you got the logic? – A. Wahab Sep 10 '18 at 10:46