web-dev-qa-db-fra.com

Remplacer le bouton d'alimentation comme le bouton Accueil

Eh bien, je fais quelque chose dans lequel je veux désactiver tous les boutons durs de l'appareil.

Boutons en dur comme Power, Home, Volume up, Volume down, Search, Back.

J'ai réussi à remplacer presque tous les boutons ici sauf Power.

Je veux donc que vous puissiez voir et partager quelques idées pour que je puisse m'en tirer.

J'obtiens le appui long Keyevent de puissance dans onDispatchKeyEvent(), de la même manière je veux attraper le clic court du même. De plus, en appuyant sur l'alimentation, j'ai également essayé d'arrêter Écran éteint en obtenant le Broadcast de SCREEN_OFF et j'ai réussi à le recevoir mais je n'ai pas pu le gérer.

Merci.

Ensuite, j'avais créé un ReceiverScreen qui reçoit la diffusion de l'écran on/off

ReceiverScreen.Java

public class ReceiverScreen extends BroadcastReceiver {

    public static boolean wasScreenOn = true;

    @Override
    public void onReceive(Context context, Intent intent) {
        if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
            // do whatever you need to do here
            wasScreenOn = false;
        } else if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) {
            // and do whatever you need to do here
            wasScreenOn = true;
        }
    }
}

DisableHardButton.Java

public class DisableHardButton extends Activity {

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    setContentView(R.layout.main);
    IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_ON);
    filter.addAction(Intent.ACTION_SCREEN_OFF);
    BroadcastReceiver mReceiver = new ReceiverScreen();
    registerReceiver(mReceiver, filter);
    }

@Override
    protected void onPause() {
        // when the screen is about to turn off
        if (ScreenReceiver.wasScreenOn) {
            // this is the case when onPause() is called by the system due to a screen state change
            System.out.println("SCREEN TURNED OFF");

    } else {
        // this is when onPause() is called when the screen state has not changed
    }
    super.onPause();
}

@Override
protected void onResume() {
    // only when screen turns on
    if (!ScreenReceiver.wasScreenOn) {
        // this is when onResume() is called due to a screen state change
        System.out.println("SCREEN TURNED ON");
    } else {
        // this is when onResume() is called when the screen state has not changed
    }
    super.onResume();
}
}
34
Azhar Shaikh

Phew. C'est une question assez controversée, avec beaucoup de commentaires derrière elle.

Permettez-moi de commencer par reformuler un peu votre question. Si je comprends bien, vous souhaitez désactiver tous les boutons physiques de l'appareil pendant la durée de votre activité. Cela comprend le bouton d'alimentation, que vous détectez en manipulant le ACTION_SCREEN_OFF intention. Votre solution de contournement actuelle (réussie) pour ce scénario consiste à diffuser un ACTION_SCREEN_ON, donnant vie à l'écran lorsqu'il est éteint, à condition que l'hôte l'implémente correctement.

Vous voudriez maintenant aller plus loin, en rendant cette action inutile, si (et seulement si) vous êtes capable d'attraper et de gérer ACTION_SCREEN_OFF avant qu'il ne soit envoyé au système. Est-ce possible, et si oui comment?

Cela mérite discussion. Cependant, la version courte est simple: ce n'est pas possible, sans modification personnalisée de votre firmware ou du noyau du système d'exploitation Android Android, pour une durée limitée). nombre d'appareils.

Le système Android, pour autant que cela soit documenté, définit cela comme --- action de diffusion . Suivant le modèle de publication-abonnement de propagation du message, ce message informera toutes les parties concernées de cette action. Parce que ce message est envoyé par le système, parce que la pile de messages est gérée par le système, et parce que le message est également reçu par le système, votre code n'est tout simplement pas injecté au bon endroit pour bloquer la réception de ce message.

De plus, pour certains appareils, ce sera un commutateur physique qui n'a aucune interruption programmatique. Au mieux, le système Android Android peut espérer gérer l'événement quand il se produit, c'est précisément pourquoi ce message diffusé est quelque chose d'un cas particulier dans la pile de services. À ma connaissance et sur la base de la documentation clairsemée sur ce scénario, c'est pourquoi ce n'est pas une fonctionnalité prise en charge prête à l'emploi, avant d'envisager l'un des vecteurs possibles d'abus.

Votre meilleur recours est en fait beaucoup plus simple, si vous avez la possibilité de modifier le matériel physique de l'appareil en question: restreindre l'accès, modifier ou autrement désactiver le bouton d'alimentation physique. Dans de nombreux scénarios, cela n'est pas souhaitable, mais cela fonctionne dans les situations où votre appareil Android est utilisé, par exemple, comme point de vente ou machine de service public. Si cela ne fonctionne pas, placer des restrictions physiques sur l'accès au bouton d'alimentation peut être tout ce qui est nécessaire, gérer le reste des cas (par exemple, repérer les tentatives de basculement de l'écran) en envoyant ACTION_SCREEN_ON.

N'oubliez pas que cette stratégie n'est pas infaillible. Faites-le avec compétence et documentez bien la procédure, de peur de devenir du fourrage pour le prochain 2600 exposé .

Bonne chance avec votre candidature.

51
MrGomez

Au contraire de toutes les réponses .. Vérifiez ceci:


@Override
public boolean dispatchKeyEvent(KeyEvent event) {
        if (event.getKeyCode() == KeyEvent.KEYCODE_POWER) {
                Log.i("", "Dispath event power");
                Intent closeDialog = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
                sendBroadcast(closeDialog);
                return true;
        }

        return super.dispatchKeyEvent(event);
}

Ce qu'il fait:

Chaque fois que l'utilisateur appuie sur le bouton d'alimentation. Nous annulons la boîte de dialogue avant même qu'elle ne soit vue !! :). Cela fonctionne pour moi .. (Testé sur note2)

8
amalBit

Voici ce que j'ai fait:

(1) Créez une classe de récepteur:

public class ScreenReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();
        switch (action) {
            case Intent.ACTION_SCREEN_OFF:
                BaseActivity.unlockScreen();
                break;

            case Intent.ACTION_SCREEN_ON:
                // and do whatever you need to do here
                BaseActivity.clearScreen();
        }
    }
}

(2) Les deux méthodes appelées ci-dessus ressemblaient à ceci:

public static void unlockScreen () {
    if (current == null) return;

    Log.i( Constants.TAG, "Turning on screen ... " );

    Window window = current.getWindow();
    window.addFlags( WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD );
    window.addFlags( WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED );
    window.addFlags( WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON   );
}

public static void clearScreen () {
    if (current == null) return;

    Log.i( Constants.TAG, "Clearing screen flag when on ... " );

    Window window = current.getWindow();
    window.clearFlags( WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD );
    window.clearFlags( WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED );
    window.clearFlags( WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON   );
}

private static BaseActivity current;

@Override
protected void onResume () {
    current = this;
}

(3) Dans la méthode onCreate () de la classe d'activité principale, enregistrez le récepteur:

    IntentFilter filter = new IntentFilter( Intent.ACTION_SCREEN_ON );
    filter.addAction( Intent.ACTION_SCREEN_OFF );
    registerReceiver(new ScreenReceiver(), filter);
5
Sileria

Vous pouvez vous renseigner sur la pression du bouton d'alimentation, mais je ne pense pas que vous pourrez la remplacer et vous pourrez fermer la boîte de dialogue de mise hors tension et afficher autre chose.

Voici ce que j'ai essayé,

package com.easylogs.app;

import Android.content.BroadcastReceiver;
import Android.content.Context;
import Android.content.Intent;
import Android.util.Log;
import Android.widget.Toast;

public class CloseSystemDialogsIntentReceiver extends BroadcastReceiver {
    public void onReceive(final Context context, final Intent intent) {
        Log.i("HERE", "------------------------------------HERE");
        Toast.makeText(context, "OFFFFFFFFFFFFFFFF",Toast.LENGTH_LONG).show();
    }
}

et déclaration dans le manifeste comme,

    <receiver Android:name="CloseSystemDialogsIntentReceiver">
    <intent-filter>
            <action Android:name="Android.intent.action.CLOSE_SYSTEM_DIALOGS" />
            <category Android:name="Android.intent.category.DEFAULT" />
        </intent-filter>
    </receiver>
2
MKJParekh
@Override
public boolean dispatchKeyEvent(KeyEvent event) {
    if (event.getKeyCode() == KeyEvent.KEYCODE_POWER) {

        return true;
    }

    return super.dispatchKeyEvent(event);
}

avez-vous essayé le code ci-dessus où nous pouvons gérer l'événement de touche d'alimentation. Jetez également un oeil à ce LIEN qui a géré l'événement appuyé sur le bouton d'alimentation.

2
Shankar Agarwal

Je sais que c'est trop tard, mais cela pourrait être utile pour d'autres développeurs à l'avenir. Testé sur Android N . Référence de https://stackoverflow.com/a/15828592/1065357

 @Override
    public void onWindowFocusChanged(boolean hasFocus) {
        super.onWindowFocusChanged(hasFocus);
        if(!hasFocus) {
           Intent closeDialog = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
            sendBroadcast(closeDialog);
        }
    }
1
Radhey

Si quelqu'un cherche une solution pour développer votre application en mode kiosque/COSU (application à usage unique détenue par l'entreprise) où vous devez désactiver divers boutons matériels, puis veuillez suivre le lien ci-dessous -

https://www.andreasschrade.com/2015/02/16/Android-tutorial-how-to-create-a-kiosk-mode-in-Android/

0
B.shruti