Android: выключать экран, когда близко к лицу

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

Кто-нибудь знает, как это сделать?


person mtmurdock    schedule 10.06.2010    source источник


Ответы (4)


То, что вы видите, это использование датчика приближения. Доступ к устройствам, на которых он есть, осуществляется через SensorManager.

person CommonsWare    schedule 10.06.2010
comment
да, я изучал это, но у меня возникли проблемы с выяснением фактической реализации. Вы видели какие-нибудь примеры того, как его использовать? - person mtmurdock; 11.06.2010
comment
@mtmurdock: нет, извините, не видел. Я просто знаю, что речь идет о датчике. - person CommonsWare; 11.06.2010

Если вам разрешено просматривать открытый исходный код, не создавая себе проблем, проверьте источник Приложение для телефона Android. В частности, src/com/android/phone/PhoneApp.java и src/com/android/phone/InCallScreen.java.

Из src/com/android/phone/PhoneApp.java:

 //Around line 519
 // Wake lock used to control proximity sensor behavior.
 if ((pm.getSupportedWakeLockFlags()
          & PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK) != 0x0) {
     mProximityWakeLock = pm.newWakeLock(
         PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK,
         LOG_TAG);
 }

 ....
// Around line 1334
if (((state == Phone.State.OFFHOOK) || mBeginningCall)&& !screenOnImmediately) {
  // Phone is in use!  Arrange for the screen to turn off
  // automatically when the sensor detects a close object.
  if (!mProximityWakeLock.isHeld()) {
      if (DBG) Log.d(LOG_TAG, "updateProximitySensorMode: acquiring...");
      mProximityWakeLock.acquire();
  } else {
      if (VDBG) Log.d(LOG_TAG, "updateProximitySensorMode: lock already held.");
  }
} else {
  // Phone is either idle, or ringing.  We don't want any
  // special proximity sensor behavior in either case.
  if (mProximityWakeLock.isHeld()) {
    if (DBG) Log.d(LOG_TAG, "updateProximitySensorMode: releasing...");
    // Wait until user has moved the phone away from his head if we are
    // releasing due to the phone call ending.
    // Qtherwise, turn screen on immediately
    int flags =
        (screenOnImmediately ? 0 : PowerManager.WAIT_FOR_PROXIMITY_NEGATIVE);
    mProximityWakeLock.release(flags);
  }
}

Кроме того, если вы посмотрите на код класса PowerManager, PROXIMITY_SCREEN_OFF_WAKE_LOCK задокументирован (но скрыт) и должен делать то, что вы хотите (однако я не уверен, для какого уровня API это работает), но по какой-то причине не в таблице .

/**
 * Wake lock that turns the screen off when the proximity sensor activates.
 * Since not all devices have proximity sensors, use
 * {@link #getSupportedWakeLockFlags() getSupportedWakeLockFlags()} to determine if
 * this wake lock mode is supported.
 *
 * {@hide}
 */
public static final int PROXIMITY_SCREEN_OFF_WAKE_LOCK = WAKE_BIT_PROXIMITY_SCREEN_OFF;

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

person Dre    schedule 10.06.2010
comment
Это много, чтобы просеять ... боюсь, я не смог найти там многого, если только вы не можете указать мне на некоторые более конкретные части. - person mtmurdock; 11.06.2010
comment
Там добавлена ​​полная информация - раньше этого не хотелось, на случай, если информация из открытого исходного кода вызовет проблему. - person Dre; 11.06.2010
comment
Обратите внимание, что в Android 4.2.1 метод getSupportedWakeLockFlags больше не существует, и вам нужно использовать isWakeLockLevelSupported. grepcode.com/file_/repository.grepcode.com/java/ext/ - person Muzikant; 03.03.2014
comment
PROXIMITY_SCREEN_OFF_WAKE_LOCK является общедоступным с уровня API 21 (Lollipop). - person Eliezer; 02.01.2015

начиная с уровня API 21 (Lollipop), вы можете получить блокировку пробуждения по близости вот так:

if(powerManager.isWakeLockLevelSupported(PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK)) {
        PowerManager.WakeLock wakeLock = powerManager.newWakeLock(PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK, TAG);
        wakeLock.setReferenceCounted(false);
        return wakeLock;
    } else {
        return null;
    }
}

тогда вам решать получить и снять блокировку.

PS: PowerManager#getSupportedWakeLockFlags был скрыт, но больше не существует. Вместо этого они изобрели isWakeLockLevelSupported.

person guness    schedule 26.08.2015
comment
Несмотря на то, что он говорит, что требуется уровень API 21, он кажется обратно совместимым, поскольку флаг всегда был там, просто скрыт. - person kotucz; 16.02.2016
comment
что такое powerManager? - person behelit; 17.07.2020
comment

Возможно, вам это больше не нужно, но для тех, кто интересуется кодом, вы можете взглянуть на мой проект SpeakerProximity по адресу http://code.google.com/p/speakerproximity/

person rac2030    schedule 14.10.2010