Подтвердить что ты не робот

Длительное нажатие кнопки питания

Я читал некоторые посты здесь, на Stackoverflow, и я не нашел хорошего решения, мне интересно, можно ли определить, когда пользователь долго нажимает кнопку питания при попытке выключить устройство, я хотел бы чтобы узнать, можете ли вы обнаружить это событие и разрешить или запретить показ этого диалогового окна, в котором он появляется (перезагрузка, завершение работы и т.д.)

Я пробовал это:

@Override
public boolean dispatchKeyEvent(KeyEvent event) {
        Toast.makeText(MainActivity.this, event.getKeyCode(), Toast.LENGTH_SHORT).show();
    return true;
}

но он не отображается, также он должен работать как служба, я имею в виду, что приложение может или не может быть открыто, чтобы показать этот тост.

EDIT

Вот как я поставил 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
    }
}

Он работает нормально, но только когда устройство разблокировано, когда устройство заблокировано, ничего не отображается.

Также я пытаюсь выяснить, как удалить диалоговое окно, когда пользователь нажимает кнопку питания. Я попытался это сделать:

getWindow().addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);

Но если я хочу показать это снова, как я могу это сделать?

4b9b3361

Ответ 1

Поделиться своим методом, чтобы сделать то, что вы хотели бы достичь.

По сути, это

  1. Запрос системного разрешения на рисовать оверлей (это не обычное или уязвимое разрешение). Это не разрешение пользователя, поэтому вы должны действительно знать, что вы делаете, запрашивая его.

    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));
                }
            }
        }
    }
    
  2. Запуск службы и добавление специального представления в WindowManager

  3. Ожидание действия внутри метода View 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;
        }
    }
    

Manifest:

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

Ответ 2

Я вижу много ответов, пытающихся зацепить кнопку питания. Тем не менее, не было бы легче слушать событие выключения? Я не уверен, что это соответствует вашим потребностям, но похоже, что так.

Просто зарегистрируйте Broadcastreceiver для следующих действий (й):

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

Не забудьте добавить следующее разрешение:

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

Ответ 3

Это простое решение работает:

    @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);
}

Если вы хотите остановить всплывающее окно системы, используйте метод onWindowFocusChanged, указанный в одном из ответов ниже.

На выходе будет показан тост с "Clicked: 26", как прикреплено ниже.enter image description here

Ответ 4

Пойдите с этим

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

И когда вы хотите захватить это событие, сделайте это

@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);
}

Это можно сделать с помощью широковещательного приемника. см. этот ответ

Ответ 5

Попробуйте следующее:

@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);
}

Ответ 6

For Long Press.... Please Try this...

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);
        }
    }
}

Длительное нажатие кнопки тоста Power Show для теста...

enter image description here

Ответ 7

Метод, использованный выше Р. Загорским, долгое время работал для меня очень хорошо, но с некоторой ревизии Android 9 метод onCloseSystemDialogs перестал получать "глобальные действия".

В качестве обходного пути мое приложение уже использует Accessibility. Изнутри AccessibilityService вы можете добавить этот код в 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

    }
        ....

Обратите внимание, что если бы я поместил комментарий "TRIGGER YOUR CODE HERE", я фактически просто вызываю тот же код, который был ранее в onCloseSystemDialogs.

Обратите внимание, что до сих пор это тестировалось только на работу с Pixel 2 под управлением последней версии Android. У меня нет других телефонов с достаточно свежей версией, поэтому я не могу проверить, является ли решение достаточно общим для всех телефонов.

Ответ 8

Из вопроса Skizo-ozᴉʞS, что я понимаю, вы действительно хотите предотвратить поведение кнопки питания, и это невозможно. так же, как кнопка дома нажата, некоторые события в андроиде не могут быть предотвращены, чтобы избежать людей, у которых приложения не могут выйти.

Ответ 9

Вы можете поймать событие кнопки питания, переопределив методKeyDown

@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);
    }

Насколько я знаю, мы не можем делать это за пределами деятельности (например, фоновая служба)

Ответ 10

Принятый ответ работает без сбоев до Android Oreo, но не до Android P. Чтобы он работал в Android P, вам нужно использовать Accessibility 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() {

    }
}

Поскольку вы не можете использовать метод startService() для запуска службы специальных возможностей,

Итак, вот как вы можете включить его.

Intent openSettings = new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS);
openSettings.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(openSettings);

Ответ 11

Попробуйте следующее:

 @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 );
   }

Добавьте это в манифест:

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