38 votes

Remplacer le bouton d'alimentation comme le bouton d'accueil

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

Boutons durs comme Alimentation, Accueil, Volume haut, Volume bas, Recherche, Retour.

J'ai réussi à remplacer presque tous les boutons aquí sauf le pouvoir.

Je veux juste que vous voyiez et que vous partagiez vos idées pour que je puisse m'en sortir.

Je reçois le pression longue L'événement clé du pouvoir dans onDispatchKeyEvent() De la même façon, je veux attraper le petit clic de la même chose. De plus, en appuyant sur le bouton d'alimentation, j'ai aussi 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 manipuler.

Gracias.

Ensuite, j'ai créé un ReceiverScreen qui reçoit la diffusion de Screen on/off.

Écran de réception.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();
}
}

0 votes

Quel est le but..., peut-être qu'il y a une autre solution de contournement

2 votes

Vous ne pouvez pas faire ça avec le stock Android. Il y a aussi beaucoup de questions à ce sujet sur Stackoverflow.com Que pensez-vous trouver sur le vôtre maintenant ?

0 votes

La question semble similaire, vérifiez ceci stackoverflow.com/questions/8036701/how-to-disable-power-button

57voto

MrGomez Points 20526

Ouf. C'est une question très controversée, avec beaucoup de commentaires à l'appui.

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é. Ceci inclut le bouton d'alimentation, que vous détectez en manipulant le bouton de l'appareil. ACTION_SCREEN_OFF intention. Votre solution actuelle (réussie) pour ce scénario est de diffuser un ACTION_SCREEN_ON Il s'agit de redonner vie à l'écran lorsqu'il est éteint, à condition que l'hôte l'implémente correctement.

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

Cela mérite une discussion. La version courte, cependant, est simple : cela n'est pas possible, sans modification personnalisée de votre micrologiciel ou du cœur du système d'exploitation Android, pour un nombre limité d'appareils.

Le système Android, pour autant qu'il soit documenté, définit cela comme une action de diffusion . Suite à la modèle de publication et d'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.

En outre, pour certains appareils, il s'agira d'une physique qui n'a aucune interruption programmée. Au mieux, le système Android peut espérer gérer l'événement quand il se produit, ce qui est précisément la raison pour laquelle ce message de diffusion est un cas spécial dans la pile de services. À ma connaissance, et sur la base de la documentation éparse sur ce scénario, c'est la raison pour laquelle il ne s'agit pas d'une fonctionnalité prise en charge dès le départ, avant de considérer tous les 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 au bouton d'alimentation physique, le mutiler ou le désactiver d'une autre manière. 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 un point de vente ou une machine de service public. Si cela n'est pas possible, il peut suffire d'imposer des restrictions physiques à l'accès au bouton d'alimentation. Pour les autres cas (par exemple, les tentatives ponctuelles de basculer l'écran), envoyez 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, sinon vous deviendrez la proie du prochain 2600 exposé .

Bonne chance pour votre candidature.

0 votes

Crédit supplémentaire pour améliorer cette réponse : quelqu'un a-t-il une bonne liste d'appareils fonctionnant sous Android et utilisant des interrupteurs physiques pour leur écran et leur état d'alimentation ? Compte tenu de la nature open-source d'Android, il est clair que pourquoi Il s'agit d'une décision de conception, mais je ne trouve pas de bonne liste d'exemples actuels à citer ici.

1 votes

Je ne connais pas d'appareil qui n'a pas utiliser un interrupteur physique pour l'alimentation au moins.

0 votes

Moi aussi je suis d'accord que ce n'est pas possible sans modification du firmware. @MrGomez Tout d'abord laissez-moi vous dire que ce que j'ai appris plus tôt est vous ne pouvez pas passer outre le bouton HOME mais j'avais quand même fait quelque chose avec (lien collé ci-dessus), donc la même chose que je veux avec Puissance bouton. Je m'attendais à une idée de nuisance. Je n'attendais pas de réponse mais un +1 pour vous.

11voto

amalBit Points 3406

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)

0 votes

Je peux confirmer que cela fonctionne sur mon Moto G fonctionnant sous Android 4.4.4.

0 votes

Salut Venkat... Est-ce que le code ci-dessus fonctionne pour vous... Je l'ai essayé dans le Moto X mais l'écran s'éteint.

0 votes

@amalBit J'ai utilisé ce code dans l'activité. Mais lorsque j'appuie sur le bouton d'alimentation, je suis toujours capable de voir la boîte de dialogue.

5voto

Mobistry Points 2902

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 qui sont appelées ci-dessus ressemblent à 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);

2voto

MKJParekh Points 18108

Vous pouvez être informé de l'appui sur le bouton d'alimentation, mais je ne pense pas que vous pourrez l'ignorer et vous serez en mesure d'ignorer le dialogue de mise hors tension et d'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 la déclaration dans le manifeste en tant que ,

    <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>

1 votes

Je suis en mesure d'obtenir l'événement "Power long click" en onDispatchKey() mais je veux attraper les pressions courtes sur les touches et je dois passer outre d'une manière ou d'une autre, ce qui peut être une sorte d'illusion.

2voto

Agarwal Shankar Points 14558
@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 la touche d'alimentation. Jetez également un coup d'oeil à ceci LIEN qui a géré l'événement "bouton d'alimentation enfoncé".

5 votes

Avez-vous essayé par vous-même ? Si c'était si simple, on ne vous le demanderait pas ici.

1 votes

Je reçois aussi l'événement SCREEN_OFF mais je ne veux pas que l'écran s'éteigne. +1 toujours

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X