web-dev-qa-db-fra.com

Désactiver le panneau de notification

Je travaille sur une application lockscreen et je dois désactiver la possibilité d'afficher la barre de notification/statut en haut de l'écran. Il existe une application appelée Holo Locker. Cette application permet à l'utilisateur de tirer vers le bas depuis le haut de l'écran. Elle remet simplement la barre en haut de l'écran et empêche de tirer le tiroir. 

Je n'ai aucune idée par où commencer. Toute aide serait formidable! Merci!

12
DDukesterman

Ceci est possible en utilisant la réflexion. Il y a beaucoup de problèmes cependant.

Il n'y a aucun moyen de vérifier si le panneau de notification est ouvert ou en cours d'ouverture. Nous devrons donc nous fier à Activity#onWindowFocusChanged(boolean). Et c'est là que les problèmes commencent. 

Que fait la méthode:

public void onWindowFocusChanged (boolean aFocus)

Appelée lorsque la fenêtre en cours de l’activité gagne ou perd la mise au point . C’est le meilleur indicateur de la visibilité de cette activité pour le utilisateur.

Nous devrons donc trouver un moyen de distinguer entre la perte de concentration due à l'affichage du panneau de notification et la perte de concentration due à d'autres événements.

Certains événements qui déclencheront onWindowFocusChanged(boolean):

  • La fenêtre est perdue quand une activité est envoyée en arrière-plan (changement d’application par un utilisateur ou appui sur le bouton home).

  • Puisque les boîtes de dialogue et les fenêtres contextuelles s'ouvrent dans leurs propres fenêtres, le focus de la fenêtre de l'activité sera perdu lorsque celles-ci seront affichées. 

  • Un autre exemple de perte de focus de la fenêtre de l'activité est le clic sur une visionneuse qui affiche une fenêtre contextuelle.

Votre activité n’aura peut-être pas à traiter de toutes ces questions. L'exemple suivant en gère un sous-ensemble:

Tout d'abord, vous avez besoin de l'autorisation EXPAND_STATUS_BAR:

<uses-permission Android:name="Android.permission.EXPAND_STATUS_BAR" />

Ensuite, déclarez ces variables de classe-scope dans votre activité:

// To keep track of activity's window focus
boolean currentFocus;

// To keep track of activity's foreground/background status
boolean isPaused;

Handler collapseNotificationHandler;

Remplacer onWindowFocusChanged(boolean):

@Override
public void onWindowFocusChanged(boolean hasFocus) {

    currentFocus = hasFocus;

    if (!hasFocus) {

        // Method that handles loss of window focus
        collapseNow();
    }
}

Définir collapseNow():

public void collapseNow() {

    // Initialize 'collapseNotificationHandler'
    if (collapseNotificationHandler == null) {
        collapseNotificationHandler = new Handler();
    }

    // If window focus has been lost && activity is not in a paused state
    // Its a valid check because showing of notification panel
    // steals the focus from current activity's window, but does not 
    // 'pause' the activity
    if (!currentFocus && !isPaused) {

        // Post a Runnable with some delay - currently set to 300 ms
        collapseNotificationHandler.postDelayed(new Runnable() {

            @Override
            public void run() {

                // Use reflection to trigger a method from 'StatusBarManager'                

                Object statusBarService = getSystemService("statusbar");
                Class<?> statusBarManager = null;

                try {
                    statusBarManager = Class.forName("Android.app.StatusBarManager");
                } catch (ClassNotFoundException e) {
                    e.printStackTrace();
                }

                Method collapseStatusBar = null;

                try {

                    // Prior to API 17, the method to call is 'collapse()'
                    // API 17 onwards, the method to call is `collapsePanels()`

                    if (Build.VERSION.SDK_INT > 16) {
                        collapseStatusBar = statusBarManager .getMethod("collapsePanels");
                    } else {
                        collapseStatusBar = statusBarManager .getMethod("collapse");
                    }
                } catch (NoSuchMethodException e) {
                    e.printStackTrace();
                }

                collapseStatusBar.setAccessible(true);

                try {
                    collapseStatusBar.invoke(statusBarService);
                } catch (IllegalArgumentException e) {
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                } catch (InvocationTargetException e) {
                    e.printStackTrace();
                }

                // Check if the window focus has been returned
                // If it hasn't been returned, post this Runnable again
                // Currently, the delay is 100 ms. You can change this
                // value to suit your needs.
                if (!currentFocus && !isPaused) {
                    collapseNotificationHandler.postDelayed(this, 100L);
                }

            }
        }, 300L);
    }   
}

Traiter les onPause() et onResume() de l'activité:

@Override
protected void onPause() {
    super.onPause();

    // Activity's been paused      
    isPaused = true;
}

@Override
protected void onResume() {
    super.onResume();

    // Activity's been resumed
    isPaused = false;
}

J'espère que c'est proche de ce que vous recherchez.

Remarque: le scintillement qui se produit lorsque vous faites glisser la barre de notification et que vous le maintenez est malheureusement inévitable. Son apparence peut cependant être contrôlée/améliorée en utilisant de «meilleures» valeurs pour les délais de traitement. Ce problème est également présent dans l'application Holo Locker.

29
Vikram
        private void disablePullNotificationTouch() {
                WindowManager manager = ((WindowManager) getApplicationContext()
                        .getSystemService(Context.WINDOW_SERVICE));
                WindowManager.LayoutParams localLayoutParams = new WindowManager.LayoutParams();
                localLayoutParams.type = WindowManager.LayoutParams.TYPE_SYSTEM_ERROR;
                localLayoutParams.gravity = Gravity.TOP;
                localLayoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE |

                        // this is to enable the notification to recieve touch events
                        WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL |

                        // Draws over status bar
                        WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;

                localLayoutParams.width = WindowManager.LayoutParams.MATCH_PARENT;
                localLayoutParams.height = (int) (25 * getResources()
                        .getDisplayMetrics().scaledDensity);
                localLayoutParams.format = PixelFormat.RGBX_8888;
                customViewGroup view = new customViewGroup(this);
                manager.addView(view, localLayoutParams);
            }

    //Add this class in your project
    public class customViewGroup extends ViewGroup {

        public customViewGroup(Context context) {
            super(context);
        }

        @Override
        protected void onLayout(boolean changed, int l, int t, int r, int b) {
        }

        @Override
        public boolean onInterceptTouchEvent(MotionEvent ev) {

            Log.v("customViewGroup", "**********Intercepted");
            return true;
        }
7
NitinM

Si vous voulez juste empêcher l'utilisateur d'ouvrir le statut, essayez ceci:

getWindow().addFlags(WindowManager.LayoutParams.[TYPE_SYSTEM_OVERLAY][1]);

Utilisation:

super.onCreate(savedInstanceState);
getWindow().addFlags(WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY);
setContentView(R.layout.your_layout);

Ajoutez avant En fonction de vos besoins spécifiques, vous pouvez choisir un WindowManager.LayoutParams .

J'espère que cela t'aides.

6
ZZeyaNN

J'ai essayé la réponse acceptée, mais j'étais toujours capable de retirer et de modifier rapidement certains paramètres.

Il existe une solution différente qui empêche l’utilisateur de descendre complètement le menu, ce que j’ai préféré à la réponse acceptée ici.

2
Stefan Bogaard
WindowManager manager = ((WindowManager) getApplicationContext().getSystemService(Context.WINDOW_SERVICE));

WindowManager.LayoutParams localLayoutParams = new WindowManager.LayoutParams();
localLayoutParams.type = WindowManager.LayoutParams.TYPE_SYSTEM_ERROR;
localLayoutParams.gravity = Gravity.TOP;
localLayoutParams.flags = 
    WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE |

    // this is to enable the notification to receive touch events
    WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL |

    // Draws over status bar
    WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;

localLayoutParams.width = WindowManager.LayoutParams.MATCH_PARENT;
localLayoutParams.height = (int) (40 * getResources().getDisplayMetrics().scaledDensity);
localLayoutParams.format = PixelFormat.TRANSPARENT;

blockingView = new CustomViewGroup(this);
manager.addView(blockingView, localLayoutParams);

Allez-y et référez-vous au link Pour la classe customViewGroup 

0
Chandsi Gupta