J'ai lu quelques articles ici sur Stackoverflow, et je n'ai pas trouvé de bonne solution, je me demande s'il est possible de détecter quand l'utilisateur appuie longuement sur le bouton d'alimentation en essayant d'éteindre l'appareil, j'aimerais pour savoir si vous pouvez détecter cet événement, et laisser ou non afficher cette boîte de dialogue où apparaît (Redémarrer, Arrêter, etc ...)
J'ai essayé ça:
@Override
public boolean dispatchKeyEvent(KeyEvent event) {
Toast.makeText(MainActivity.this, event.getKeyCode(), Toast.LENGTH_SHORT).show();
return true;
}
mais il ne s'affiche pas, il devrait également fonctionner en tant que service, je veux dire que l'application peut ou non être ouverte pour afficher ce toast.
Voici comment je mets le onCloseSystemDialog
//home or recent button
public void onCloseSystemDialogs(String reason) {
if ("globalactions".equals(reason)) {
Toast.makeText(PowerButtonService.this, "yaps", Toast.LENGTH_SHORT).show();
Intent i= new Intent(getBaseContext(), Demo.class);
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
getApplication().startActivity(i);
//} else if ("homekey".equals(reason)) {
//home key pressed
//} else if ("recentapss".equals(reason)) {
// recent apps button clicked
}
}
Cela fonctionne bien, mais uniquement lorsque l'appareil est déverrouillé, lorsque l'appareil est verrouillé n'affiche rien.
J'essaie également de comprendre comment supprimer la boîte de dialogue lorsque l'utilisateur clique sur le bouton d'alimentation, j'ai essayé ceci:
getWindow().addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);
Mais si je veux le montrer à nouveau, comment puis-je le faire?
Partager ma méthode pour faire ce que vous souhaitez accomplir.
Fondamentalement, ce qu'il fait est
Demander l'autorisation système pour dessiner la superposition (Ce n'est pas une autorisation normale ou vulnérable). Ce n'est pas une autorisation d'utilisateur, vous devriez donc vraiment savoir ce que vous faites en le demandant.
public class MainActivity extends AppCompatActivity {
public final static int REQUEST_CODE = 10101;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (checkDrawOverlayPermission()) {
startService(new Intent(this, PowerButtonService.class));
}
}
public boolean checkDrawOverlayPermission() {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
return true;
}
if (!Settings.canDrawOverlays(this)) {
/** if not construct intent to request permission */
Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
Uri.parse("package:" + getPackageName()));
/** request permission via start activity for result */
startActivityForResult(intent, REQUEST_CODE);
return false;
} else {
return true;
}
}
@Override
@TargetApi(Build.VERSION_CODES.M)
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_CODE) {
if (Settings.canDrawOverlays(this)) {
startService(new Intent(this, PowerButtonService.class));
}
}
}
}
Démarrage d'un service et ajout d'une vue spéciale à WindowManager
En attente d'une action dans la méthode View
de onCloseSystemDialogs
public class PowerButtonService extends Service {
public PowerButtonService() {
}
@Override
public void onCreate() {
super.onCreate();
LinearLayout mLinear = new LinearLayout(getApplicationContext()) {
//home or recent button
public void onCloseSystemDialogs(String reason) {
if ("globalactions".equals(reason)) {
Log.i("Key", "Long press on power button");
} else if ("homekey".equals(reason)) {
//home key pressed
} else if ("recentapps".equals(reason)) {
// recent apps button clicked
}
}
@Override
public boolean dispatchKeyEvent(KeyEvent event) {
if (event.getKeyCode() == KeyEvent.KEYCODE_BACK
|| event.getKeyCode() == KeyEvent.KEYCODE_VOLUME_UP
|| event.getKeyCode() == KeyEvent.KEYCODE_VOLUME_DOWN
|| event.getKeyCode() == KeyEvent.KEYCODE_CAMERA
|| event.getKeyCode() == KeyEvent.KEYCODE_POWER) {
Log.i("Key", "keycode " + event.getKeyCode());
}
return super.dispatchKeyEvent(event);
}
};
mLinear.setFocusable(true);
View mView = LayoutInflater.from(this).inflate(R.layout.service_layout, mLinear);
WindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE);
//params
WindowManager.LayoutParams params = new WindowManager.LayoutParams(
100,
100,
WindowManager.LayoutParams.TYPE_SYSTEM_ALERT,
WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
| WindowManager.LayoutParams.FLAG_FULLSCREEN
| WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
| WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON,
PixelFormat.TRANSLUCENT);
params.gravity = Gravity.LEFT | Gravity.CENTER_VERTICAL;
wm.addView(mView, params);
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
}
Manifeste:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:Android="http://schemas.Android.com/apk/res/Android"
package="powerbuttonpress">
<uses-permission Android:name="Android.permission.SYSTEM_ALERT_WINDOW"/>
<application
Android:allowBackup="true"
Android:icon="@mipmap/ic_launcher"
Android:label="@string/app_name"
Android:supportsRtl="true"
Android:theme="@style/AppTheme">
<activity Android:name=".MainActivity">
<intent-filter>
<action Android:name="Android.intent.action.MAIN"/>
<category Android:name="Android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<service
Android:name=".PowerButtonService"
Android:enabled="true"
Android:exported="true">
</service>
</application>
</manifest>
service_layout:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:layout_width="match_parent"
Android:layout_height="match_parent"
Android:orientation="vertical">
</LinearLayout>
Je vois de nombreuses réponses essayant de se connecter au bouton d'alimentation. Cependant, ne serait-il pas plus facile d'écouter l'événement d'arrêt? Je ne sais pas si cela correspond à vos besoins, mais cela semble être le cas.
Enregistrez simplement un Broadcastreceiver à ce qui suit action (s) :
<receiver Android:name=".ShutdownReceiver">
<intent-filter>
<action Android:name="Android.intent.action.ACTION_SHUTDOWN" />
<action Android:name="Android.intent.action.QUICKBOOT_POWEROFF" />
</intent-filter>
</receiver>
N'oubliez pas d'ajouter l'autorisation suivante:
<uses-permission Android:name="Android.permission.DEVICE_POWER" />
Cette solution simple fonctionne:
@Override
public boolean dispatchKeyEvent(KeyEvent event) {
int keyPressed = event.getKeyCode();
if(keyPressed==KeyEvent.KEYCODE_POWER){
Log.d("###","Power button long click");
Toast.makeText(MainActivity.this, "Clicked: "+keyPressed, Toast.LENGTH_SHORT).show();
return true;}
else
return super.dispatchKeyEvent(event);
}
Si vous souhaitez arrêter la fenêtre contextuelle du système , utilisez la méthode onWindowFocusChanged
spécifiée dans l'une des réponses ci-dessous.
La sortie montrera le toast avec "Clicked: 26" comme joint ci-dessous .
Allez avec ça
<uses-permission Android:name="Android.permission.PREVENT_POWER_KEY" />
Et quand vous voulez capturer cet événement, faites ceci
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_POWER) {
// this is method which detect press even of button
event.startTracking(); // Needed to track long presses
return true;
}
return super.onKeyDown(keyCode, event);
}
@Override
public boolean onKeyLongPress(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_POWER) {
// Here we can detect long press of power button
return true;
}
return super.onKeyLongPress(keyCode, event);
}
Cela peut être fait avec un récepteur de diffusion. voir cette réponse
Essaye ça :
@Override
public boolean dispatchKeyEvent(KeyEvent event) {
if (event.getKeyCode() == KeyEvent.KEYCODE_POWER) {
Intent i = new Intent(this, ActivitySetupMenu.class);
startActivity(i);
return true;
}
return super.dispatchKeyEvent(event);
}
Pour un appui long .... Veuillez essayer ceci ...
import Android.app.Activity;
import Android.content.Intent;
import Android.os.Bundle;
import Android.view.KeyEvent;
import Android.view.WindowManager;
import Android.widget.Toast;
import Java.util.ArrayList;
import Java.util.Arrays;
import Java.util.List;
public class demo extends Activity {
private final List<Integer> blockedKeys = new ArrayList<>(Arrays.asList(KeyEvent.KEYCODE_VOLUME_DOWN, KeyEvent.KEYCODE_VOLUME_UP, KeyEvent.KEYCODE_POWER));
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);
setContentView(R.layout.demo);
}
@Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
if (!hasFocus) {
// Close every kind of system dialog
Intent closeDialog = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
sendBroadcast(closeDialog);
Toast.makeText(demo.this, "Your LongPress Power Button", Toast.LENGTH_SHORT).show();
}
}
@Override
public void onBackPressed() {
// nothing to do here
// … really
}
@Override
public boolean dispatchKeyEvent(KeyEvent event) {
if (blockedKeys.contains(event.getKeyCode())) {
return true;
} else {
return super.dispatchKeyEvent(event);
}
}
}
Appuyez longuement sur le bouton Toast Power Show pour le test ...
La méthode utilisée ci-dessus par R. Zagórski a très bien fonctionné pour moi pendant longtemps, mais à partir d'une révision de Android 9 la méthode onCloseSystemDialogs a cessé de recevoir "globalactions".
Pour contourner ce problème, mon application utilise déjà l'accessibilité. Depuis l'intérieur du service d'accessibilité, vous pouvez ajouter ce code dans onAccessibilityEvent
@Override
public void onAccessibilityEvent(AccessibilityEvent event) {
Log.i(TAG,"Accessibilityevent");
if (event == null || event.getPackageName()==null||event.getClassName()==null)
return;
if (event.getClassName().toString().contains("globalactions")){
//TRIGGER YOUR CODE HERE
}
....
Notez que si j'ai mis le commentaire "DÉCLENCHEZ VOTRE CODE ICI", j'appelle en fait le même code qui était auparavant dans onCloseSystemDialogs.
Notez que jusqu'à présent, cela n'a été testé que pour fonctionner sur un Pixel 2 fonctionnant sous Android. Je n'ai pas d'autre téléphone exécutant une version suffisamment récente, je ne peux donc pas tester si la solution est suffisamment générique sur tous les téléphones.
De la question Skizo-ozᴉʞS, ce que je comprends, vous voulez réellement empêcher le comportement du bouton d'alimentation et cela ne peut pas être fait. tout comme le bouton d'accueil a appuyé sur certains événements dans Android ne peut pas être empêché pour éviter que les gens aient des applications qu'ils ne peuvent pas quitter.
Vous pouvez intercepter l'événement du bouton d'alimentation en remplaçant la méthode onKeyDown
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (event.getKeyCode() == KeyEvent.KEYCODE_POWER) {
Log.e("key","long");
/*//disable the system dialog
Intent closeDialog = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
sendBroadcast(closeDialog);*/
Toast.makeText(getApplicationContext(),"Power",Toast.LENGTH_SHORT).show();
}
return super.onKeyDown(keyCode, event);
}
Comme je le sais, nous ne pouvons pas faire cette activité extérieure (comme un service d'arrière-plan)
La réponse acceptée fonctionne parfaitement jusqu'à Android Oreo mais pas dans Android P. Pour le faire fonctionner dans Android P you ') ll faut utiliser le service d'accessibilité
Classe de service
import Android.accessibilityservice.AccessibilityService;
import Android.util.Log;
import Android.view.accessibility.AccessibilityEvent;
import com.bm.yucasa.Utils.LocationSetup;
import static com.bm.yucasa.controller.AppController.TAG;
public class PowerServiceTwo extends AccessibilityService {
@Override
public void onAccessibilityEvent(AccessibilityEvent event) {
Log.i(TAG,"Accessibilityevent");
if (event == null || event.getPackageName()==null||event.getClassName()==null)
return;
if (event.getClassName().toString().contains("globalactions")){
LocationSetup locationSetup =
LocationSetup.getInstance(PowerServiceTwo.this);
if (locationSetup.isConnected) {
locationSetup.startOnDemandLocationUpdates(false, "0");
} else {
//Toast.makeText(getApplicationContext(), "please check gps", Toast.LENGTH_SHORT).show();
}
}
}
@Override
public void onInterrupt() {
}
}
Comme vous ne pouvez pas utiliser la méthode startService () pour démarrer un service d'accessibilité,
Voici donc comment vous pouvez l'activer.
Intent openSettings = new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS);
openSettings.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(openSettings);
Essaye ça :
@Override
public boolean onKeyLongPress( int keyCode, KeyEvent event ) {
if( keyCode == KeyEvent.KEYCODE_POWER ) {
//Handle what you want in long press.
return true;
}
return super.onKeyLongPress( keyCode, event );
}
Ajoutez ceci dans le manifeste:
<uses-permission Android:name="Android.permission.DEVICE_POWER" />
<uses-permission Android:name="Android.permission.PREVENT_POWER_KEY" />