Android: apague la pantalla cuando esté cerca de la cara

Mi aplicación permite al usuario acceder a su correo de voz corporativo. Normalmente, durante una llamada telefónica cuando el usuario sostiene el dispositivo hasta su oreja, la pantalla se apaga para que accidentalmente no presione los botones con su cara. Me gustaría hacer que mi aplicación haga lo mismo cuando el usuario está escuchando su correo de voz.

¿Alguien sabe cómo hacer esto?

Lo que está viendo es el uso de un sensor de proximidad. Para los dispositivos que tienen uno, puede acceder a él a través de SensorManager .

Si puede ver el código fuente abierto sin causar problemas, consulte la fuente de la aplicación del teléfono Android . Específicamente src / com / android / phone / PhoneApp.java y src / com / android / phone / InCallScreen.java .

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

Además, si observa el código de la clase PowerManager, PROXIMITY_SCREEN_OFF_WAKE_LOCK está documentado (pero oculto) y debe hacer lo que desee (no estoy seguro de a qué nivel de API esto funciona), pero no en la tabla por alguna razón .

 /** * 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; 

Si no tiene miedo de utilizar una función potencial no documentada, debería hacer exactamente lo que necesita.

a partir del API nivel 21 (Lollipop) puede obtener este tipo de locking de proximidad así:

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

entonces depende de usted adquirir y liberar el locking.

PD: PowerManager#getSupportedWakeLockFlags estaba oculto, pero ahora existe nomore. Han inventado isWakeLockLevelSupported en isWakeLockLevelSupported lugar.

Probablemente ya no lo necesite, pero para aquellos que estén interesados ​​en el código, pueden echar un vistazo a mi proyecto SpeakerProximity en http://code.google.com/p/speakerproximity/