I want to hide all notifications of other apps whe

2019-04-21 05:56发布

问题:

I am creating an educational app where school students can appear for 5 mins quick exams. Most of the time they are using their parent's mobile phone.

Now what I want is that when a student is giving the exam, no notification should come from any other app such as WhatsApp, FB or Gmail.

Is this possible? How?

回答1:

One possible solution would be to set the phone in DND (Do Not Disturb) mode. I haven't tested this but according to the documentation you should be able to do:

NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
int currentFilter = notificationManager.getCurrentInterruptionFilter();
notificationManager.setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_NONE);
// Run the exam...
// Restore the filter
notificationManager.setInterruptionFilter(currentFilter);

This requires a special DND access permission though, and it requires Android M:

<uses-permission android:name="android.permission.ACCESS_NOTIFICATION_POLICY" />

That permission needs to be accepted by the user via Settings. See this question for more background and how you can launch the activity that leads to this setting.

A second option is to use Screen Pinning, which was introduced in Android L.



回答2:

You can close all notification from other app by using NotificationListenerService:

public class NotificationListener extends NotificationListenerService {

    @Override
    public void onNotificationPosted(StatusBarNotification statusBarNotification) {
      cancelNotification(statusBarNotification.getKey());
    }
}

You must declare the service in your manifest file with the Manifest.permission.BIND_NOTIFICATION_LISTENER_SERVICE permission and include an intent filter with the SERVICE_INTERFACE action. For example:

 <service android:name=".NotificationListener"
          android:label="@string/service_name"
          android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE">
     <intent-filter>
         <action android:name="android.service.notification.NotificationListenerService" />
     </intent-filter>
 </service>

https://developer.android.com/reference/android/service/notification/NotificationListenerService.html



回答3:

This seems like an interesting question.

Personally, I like the DND idea. It is simple, less messy and effective.

But say we need to reach out to lower APIs, You can use one approach to be like this.

You can have your own Notification Listener.

import android.annotation.SuppressLint;
import android.service.notification.NotificationListenerService;
import android.service.notification.StatusBarNotification;
import android.util.Log;

@SuppressLint("OverrideAbstract")
public class NotificationListener  extends NotificationListenerService {

    public static String TAG = NotificationListener.class.getSimpleName();

    @Override
    public void onNotificationPosted(StatusBarNotification sbm) {

        /**
         * This condition will define how you will identify your test is running
         * You can have an in memory variable regarding it, or persistant variable,
         * Or you can use Settings to store current state.
         * You can have your own approach
         */
        boolean condition = true; // say your test is running

        if(condition)
            cancelAllNotifications(); //Cancel all the notifications . No Disturbance 

        //else
            // nothing.
    }
}

Add this to Manifest

 <service android:name=".NotificationListener"
        android:label="@string/app_name"
        android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE">
        <intent-filter>
            <action android:name="android.service.notification.NotificationListenerService" />
        </intent-filter>
    </service>

Now, you will need Notification Access Permission for this. In your application, entry points(or before test as per your logic) you can check this

if (!NotificationManagerCompat.getEnabledListenerPackages(getApplicationContext())
            .contains(getApplicationContext().getPackageName())) {
        //We dont have access
        Intent intent= new Intent("android.settings.ACTION_NOTIFICATION_LISTENER_SETTINGS");
         //For API level 22+ you can directly use Settings.ACTION_NOTIFICATION_LISTENER_SETTINGS

        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        startActivityForResult(intent,NOTIFICATION_REQUEST_CODE);
    } else {
        //Your own logic
        Log.d(TAG, "You have Notification Access");

    }

This intent will open a page like below, which user will have to enable for giving you Access.

Hope this helps.



回答4:

If it is an exam you would likely be using your own device and not be running on students devices.

In this case your application can be a "device owner". See Device owner documentation

This will let you use Lock Task mode. See Lock task mode documentation This link also has lock task vs pinning comparison. You can use screen pinning if your application cannot be a "device owner"

I would highly recommend using Lock Task mode for any exam application to block access to the rest of the device (and not just notifications)

Note in your layout add "android:fitsSystemWindows="true" to block access to topline completely.



回答5:

Please try this to activate DND:

NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
        mNotificationManager.setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_NONE);

It will require:

<uses-permission android:name="android.permission.ACCESS_NOTIFICATION_POLICY" />

or for manually asking to enable DND:

NotificationManager mNotificationManager = (NotificationManager) getActivity().getSystemService(Context.NOTIFICATION_SERVICE);

 if (!mNotificationManager.isNotificationPolicyAccessGranted()) {
     Intent intent = new Intent(android.provider.Settings.ACTION_NOTIFICATION_POLICY_ACCESS_SETTINGS);
     startActivity(intent);
 }

or you can also turn on pin mode which keeps the app always at foreground and all notifications (even notification bar is disabled) is available from Lollipop onwards: to access pinning mode: Settings->Security->Screen Pinning->turn it on now when you press recent apps button you can see a pin in whim, click on it, the app which is first in the stack will be pinned, for more detail: https://www.cnet.com/how-to/ho-to-pin-apps-in-android-5-lollipop/

Hope this helps Happy coding... :)