javaandroidpush-notificationmiui

Push notifications with no sound on MIUI


My app's main functionality is push-notification messages sent from remote server. I am using FCM as a message delivery service. My problem is that notifications come without any sound on Xiaomi Mi 9 Lite (Android 9/MIUI 11). However, on Xiaomi Redmi Note 5 (Android 9/MIUI 10) sound works fine and on Samsung Galaxy S7 Edge (Android 8) as well. I created MessagingService which extends FirebaseMessagingService and notification channel as written in documentation.

Here is my code:

public class MessagingService extends FirebaseMessagingService {

    private static String channelId;
    private NotificationManager notificationManager;
    private NotificationChannel notificationChannel;
    private NotificationCompat.Builder notificationBuilder;

    private MessagesViewModel viewModel;

    public MessagingService() { }

    @Override
    public void onCreate() {
        super.onCreate();
        channelId = getResources().getString(R.string.default_notification_channel_id);
        notificationManager = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);

        final Uri soundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);

        notificationBuilder = new NotificationCompat.Builder(this, channelId);
        notificationBuilder.setSmallIcon(R.raw.metrial_message_icon);
        notificationBuilder.setAutoCancel(false);
        notificationBuilder.setSound(soundUri);

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            final AudioAttributes audioAttributes = new AudioAttributes.Builder()
                    .setUsage(AudioAttributes.USAGE_NOTIFICATION)
                    .build();

            String name = getString(R.string.channel_name);
            String description = getString(R.string.channel_description);
            int importance = NotificationManager.IMPORTANCE_HIGH;
            notificationChannel = new NotificationChannel(channelId, name, importance);
            notificationChannel.setDescription(description);
            notificationChannel.enableLights(true);
            notificationChannel.setShowBadge(true);
            notificationChannel.setSound(soundUri, audioAttributes);
            notificationManager.createNotificationChannel(notificationChannel);
            notificationBuilder.setChannelId(channelId);
        }
        else {
            notificationBuilder.setPriority(NotificationCompat.PRIORITY_HIGH);
            notificationBuilder.setBadgeIconType(NotificationCompat.BADGE_ICON_SMALL);
            notificationBuilder.setLights(Color.WHITE, 500, 5000);
        }

        viewModel = new MessagesViewModel(getApplication());
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
    }

    @Override
    public void onNewToken(@NonNull String s) {
        super.onNewToken(s);
        logger.info("onNewToken()");
        ConnectionParameters.getInstance().setToken(s);
        MyPrefs.getInstance(getApplicationContext()).putString(Constants.TOKEN, s);
    }

    @Override
    public void onMessageReceived(@NonNull RemoteMessage remoteMessage) {
        super.onMessageReceived(remoteMessage);

        final String messageId = remoteMessage.getData().get("message_id");
        final String title = remoteMessage.getData().get("title");
        final String body = remoteMessage.getData().get("body");

        if (messageId != null && title != null && body != null) {

            final Message message = new Message();
            message.setMessageId(messageId);
            message.setTitle(title);
            message.setContent(body);
            message.setTimestamp(new Date());

            try {
                message.setNotificationId((int)viewModel.insert(message));
            } catch (ExecutionException | InterruptedException e) {
                e.printStackTrace();
            }

            logger.info("onMessageReceived(): notificationId=" + message);

            if (MyPrefs.getInstance(getApplicationContext()).getBoolean(Constants.ENABLE_PUSH)) {
                notificationBuilder.setContentTitle(title);
                notificationBuilder.setContentText(body);

                final Intent notifyIntent = new Intent(this, MessageInfoActivity.class);
                notifyIntent.putExtra(Constants.ARG_MESSAGE_OBJECT, message);
                TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
                stackBuilder.addNextIntentWithParentStack(notifyIntent);
                PendingIntent pendingActivityIntent =
                        stackBuilder.getPendingIntent(message.getNotificationId(), PendingIntent.FLAG_UPDATE_CURRENT);
                notificationBuilder.setContentIntent(pendingActivityIntent);

                final Notification notification = notificationBuilder.build();
                notification.defaults = Notification.DEFAULT_SOUND|Notification.DEFAULT_LIGHTS;
                notificationManager.notify(message.getNotificationId(), notification);
            }
        }
    }

    private final Logger logger = LoggerFactory.getLogger(getClass());
}

And in Settings->Notifications I got the following parameters: enter image description here

And inside my push-notifications-channel sound is enabled but whenever a message comes, it seems like app notification settings override parameters in notification channel. enter image description here

There should be some solution because in popular apps such WhatsApp, Telegram, etc., these switches are enabled after installation (by default). Hope, someone helps!


Solution

  • As nobody provided better solution, I guess there is no way to allow sound/badge counter/floating notifications programmatically on MIUI (and mostly on other Chinese OEMs). It is a user's privilege to turn these settings on manually. Therefore, to enhance UX, it is important to decrease the quantity of "clicks" as much as possible. So, we could provide a dialog describing how to enable the features above with button leading to App's settings. Namely, to open a notification settings page through Intent, do the following:

    final Intent notificationSettingsIntent = new Intent();
    notificationSettingsIntent
            .setAction("android.settings.APP_NOTIFICATION_SETTINGS");
    notificationSettingsIntent
            .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        notificationSettingsIntent.putExtra(
                "android.provider.extra.APP_PACKAGE",
                activity.getPackageName());
    }
    else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            notificationSettingsIntent.putExtra(
                    "app_package",
                    activity.getPackageName());
            notificationSettingsIntent.putExtra(
                    "app_uid", 
                    activity.getApplicationInfo().uid);
    }
    activity.startActivityForResult(
            notificationSettingsIntent, 
            NOTIFICATIONS_SETTINGS_REQUEST_CODE);
    

    and you could open a dialog with button "Open notification settings" clicking on which triggers the code snippet above.