11

I would like my application to show a notification when the phone has been set to do-not-disturb modes (alarms-only, priority-only or total-silence). This works pretty well by listening to android.media.RINGER_MODE_CHANGED when checking this mode in quick settings and choosing the mode in the already selected tab. But when selecting another tab it isn't fired again. So my application has the wrong mode information and displays a wrong notification.

I gave another try to android.app.action.INTERRUPTION_FILTER_CHANGED but it wasn't fired at all in the cases above.

As I want to be informed at once I don't want to use a polling observer. In my case I'd expect massive battery drain from that.

There's a similar question but no listener solution for it:

Android: Detect Do Not Disturb status?

In the hope there might be a solution in the meantime I wanted to ask this again: Has anybody a good idea or a hint what to listen for?

UPDATE:

This is the broadcast receiver definition in AndroidManifest.xml ... to be clear about this: the receiver is called on ring mode changes, flight mode and off hook are detected as well, but it is not called on all ring mode changes, especially switches between do-not-disturb mode changes by tabbing in quick settings or by volume keys:

    <receiver android:name="UpdateStatusNotification" android:process=":remote">
        <intent-filter>
            <action android:name="android.app.action.INTERRUPTION_FILTER_CHANGED"/>
            <action android:name="android.intent.action.AIRPLANE_MODE"/>
            <action android:name="android.intent.action.PHONE_STATE"/>
            <action android:name="android.media.RINGER_MODE_CHANGED"/>
        </intent-filter>
    </receiver>

UPDATE 2:

Please read my last comment to the accepted answer.

yasd
  • 916
  • 7
  • 21
  • Use your activity to check for mode change and propagate it to your tab fragments? Also try this with a broadcast receiver if you want to save battery as you mention, it seems you are already doing this with a broadcast? – Skynet Jun 03 '16 at 18:15
  • Yes, I have a broadcast receiver that updates the notification by checking the stream volume. It does update the notification correctly, *if* called. But it isn't called in all cases, especially not, when tabbing through the different modes in quick settings. The app is mostly sleeping in the background only getting active by alarm manager to ring a tone regularly. Therefore most of the times I have no active activity. – yasd Jun 03 '16 at 18:28
  • You dont require an Alarm Manager in this case, the change in profile should trigger all the necessary broadcast receivers, please post the code of how you achieve it. As it seems strange that if everything is proper, why you dont get the notification – Skynet Jun 03 '16 at 18:32
  • You are right, the Alarm Manager has nothing to do with detecting the mode changes. I only mentioned it to explain why my app is mostly in background. I've added the broadcast receiver definition to the question. – yasd Jun 03 '16 at 19:09

1 Answers1

6

The broadcast receiver action is :

NotificationManager.ACTION_INTERRUPTION_FILTER_CHANGED

IntentFilter intent = new IntentFilter();
intent.addAction(NotificationManager.ACTION_INTERRUPTION_FILTER_CHANGED);

The below code should be in receiver.

if(intetn.getAction().equals(NotificationManager.ACTION_INTERRUPTION_FILTER_CHANGED) {
    NotificationManager mNotificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); 
    if(mNotificationManager.getCurrentInterruptionFilter() == NotificationManager.INTERRUPTION_FILTER_ALARMS) {
        //do your stuff
    } else if (mNotificationManager.getCurrentInterruptionFilter() == NotificationManager.INTERRUPTION_FILTER_NONE) {
        //....
    } else if (mNotificationManager.getCurrentInterruptionFilter() == NotificationManager.INTERRUPTION_FILTER_ALL) {
        //....
    } else if (mNotificationManager.getCurrentInterruptionFilter() == NotificationManager.INTERRUPTION_FILTER_PRIORITY) {
        //....
    } else if (mNotificationManager.getCurrentInterruptionFilter() == NotificationManager.INTERRUPTION_FILTER_UNKNOWN) {
        //....
    }
}
Goutham
  • 156
  • 13
Navas pk
  • 331
  • 3
  • 17
  • But what do you mean should I add as android:name in the tag of the tag of my receiver in the AndroidManifest.xml? I don't understand what you want to tell me with your first code block - to my understanding it does nothing. The receiver side alreay works well. – yasd Nov 22 '16 at 18:15
  • You created static receiver, so you have to add `` in your manifest, as per my understandability, do not disturb will work with this action, but in receiver you will get below actions. What ever I have created is dynamic receiver. So I need to add code for register and unregister the receiver. – Navas pk Nov 23 '16 at 04:55
  • with this action, system will fire the broadcast for 1. Alarm only 2.Total silence – Navas pk Nov 23 '16 at 05:10
  • `NotificationManager.ACTION_INTERRUPTION_FILTER‌​_CHANGED` resolves to `"android.app.action.INTERRUPTION_FILTER_CHANGED"` which does not work as stated in my question. However, I tried `` and as expected doesn't solve my problem. Broadcast receiver is not called when you change tabs in do-not-disturb quick settings. – yasd Nov 23 '16 at 06:52
  • Following your answer I've found out that `android.app.action.INTERRUPTION_FILTER_CHANGED` *is* being fired if and only if registered dynamically (with registerReceiver). This requires my app to be active which is not what I want. If registered statically (via AndroidManifest.xml) it is *not* fired. So I've created an [issue](https://code.google.com/p/android/issues/detail?id=228507). I'm going to add the action to my `AndroidManifest.xml` in case it get fixed, accept your answer and update my question. – yasd Nov 26 '16 at 12:24