Отключить экран программно, когда лицо закрывает экран на Android

Мое приложение является номеронабирателем, и когда пользователь держит телефон рядом с головой, мне нужно выключить экран и предотвратить нажатие на элементы управления - как в обычном режиме набора номера Android. Какой уровень API мне нужен и как это сделать правильно?


person Solkin    schedule 19.02.2014    source источник
comment
Возможный дубликат android: выключать экран при приближении к лицу   -  person kotucz    schedule 16.02.2016


Ответы (4)


Я нашел решение, разобрав одно очень известное приложение VoIP. Это действие после нажатия кнопки 1 отключит экранные и аппаратные клавиши, когда вы закроете датчики. После нажатия кнопки 2 эта функция будет отключена.

Также для этой функции требовалось разрешение:

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

Мероприятия. Попробуй.

public class MainActivity extends Activity {

    private Button button1;
    private Button button2;
    private PowerManager powerManager;
    private PowerManager.WakeLock wakeLock;
    private int field = 0x00000020;

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

        try {
            // Yeah, this is hidden field.
            field = PowerManager.class.getClass().getField("PROXIMITY_SCREEN_OFF_WAKE_LOCK").getInt(null);
        } catch (Throwable ignored) {
        }

        powerManager = (PowerManager) getSystemService(POWER_SERVICE);
        wakeLock = powerManager.newWakeLock(field, getLocalClassName());

        setContentView(R.layout.main);
        button1 = (Button) findViewById(R.id.button1);
        button2 = (Button) findViewById(R.id.button2);

        button1.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                if(!wakeLock.isHeld()) {
                    wakeLock.acquire();
                }
            }
        });

        button2.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                if(wakeLock.isHeld()) {
                    wakeLock.release();
                }
            }
        });
    }
}
person Solkin    schedule 20.02.2014
comment
Одно небольшое исправление: вместо PowerManager.class.getClass() следует использовать PowerManager.class - person Muzikant; 03.03.2014
comment
не работает на samsung duos, moto e, moto g 3rd gen - person Pararth; 05.10.2015
comment
Это действительно работает!!! Я потратил много часов, чтобы найти решение! Большое спасибо!!! - person Vasia Dunaev; 23.08.2016
comment
У меня работало на LGE Nexus 4 -- Android v.4.3 (API:18), хотя в официальных документах говорится, что флаг PROXIMITY_SCREEN_OFF_WAKE_LOCK был добавлен в API 21 (developer.android.com/reference/android/os/PowerManager)! - person Astrogator; 13.12.2018
comment
не работает, когда телефон заблокирован - person Alireza aslami; 15.02.2021
comment
А что за приложение было?? - person james04; 08.03.2021
comment
@james04 это был Скайп - person Solkin; 09.03.2021
comment
@Solkin Могу ли я где-нибудь найти код? Я заинтересован - person james04; 10.03.2021
comment
@ james04 Исходный код Skype? Кажется, что нет. Можно только попробовать разобрать. - person Solkin; 12.03.2021

Следующий код показывает, как использовать датчик приближения:

public class SensorActivity extends Activity implements SensorEventListener {
private SensorManager mSensorManager;
private Sensor mProximity;

 @Override
 public final void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);

// Get an instance of the sensor service, and use that to get an instance of
// a particular sensor.
mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
mProximity = mSensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY);
 }

 @Override
 public final void onAccuracyChanged(Sensor sensor, int accuracy) {
// Do something here if sensor accuracy changes.
 }

 @Override
  public final void onSensorChanged(SensorEvent event) {
   float distance = event.values[0];
// Do something with this sensor data.
   }

 @Override
 protected void onResume() {
// Register a listener for the sensor.
super.onResume();
mSensorManager.registerListener(this, mProximity, SensorManager.SENSOR_DELAY_NORMAL);
 }

 @Override
  protected void onPause() {
// Be sure to unregister the sensor when the activity pauses.
super.onPause();
mSensorManager.unregisterListener(this);
 }}

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

Надеюсь, это поможет вам.

person i.n.e.f    schedule 19.02.2014
comment
Да, это отправит мне много событий, но я понятия не имею, как выключить экран... В ответе по ссылке используется только частный Android API. - person Solkin; 19.02.2014
comment
Я не понимаю, для чего ОП нужен акселерометр. Его, скорее всего, будут интересовать события от датчика приближения. . - person Michael; 19.02.2014
comment
Спасибо, но... Это всего лишь датчики прослушивания. Но мне нужно отключить экран. - person Solkin; 20.02.2014
comment
проверьте эту ссылку stackoverflow.com/questions/9561320/ в этом контрольном ответе, опубликованном @hackbod, и попробуйте этот код params.flags |= LayoutParams.FLAG_KEEP_SCREEN_OFF; params.screenBrightness = 0; getWindow().setAttributes(params), надеюсь, это поможет. - person i.n.e.f; 20.02.2014
comment
@i.n.e.f, нет FLAG_KEEP_SCREEN_OFF - person suitianshi; 23.12.2015

Есть много устройств, где загрузка ЦП становится высокой, если вы попробуете метод, опубликованный Солкиным (с использованием wakelock). Это ошибка Android-устройств.

Вы должны использовать событие onSensorChanged и просто отображать черный экран, чтобы избежать каких-либо проблем.

person justingregoryuk    schedule 21.02.2014
comment
просто отображать черный экран, чтобы избежать каких-либо проблем? вы имеете в виду, помимо всех новых проблем, вызванных тем фактом, что экран на самом деле все еще включен? - person Michael; 18.01.2019

Лучший способ - использовать DialogFragment, вы показываете черный экран и закрываете его.

@Override
  public final void onSensorChanged(SensorEvent event) {
   float distance = event.values[0];
     if(distance <10f)
    showDialogFragment()
     else
    hideDialogFragment()

   }
person amir    schedule 24.03.2021
comment
В этом случае пользователь будет касаться экрана, получать входящие уведомления и т. д. Поэтому при звонке необходимо выключать экран. - person Solkin; 23.04.2021