Android:当靠近脸部时关闭屏幕

17

我的应用允许用户访问其公司语音邮件。通常,在电话通话期间,当用户将设备靠近耳朵时,屏幕会关闭,以免意外触碰面部按键。我希望在用户收听语音邮件时,我的应用也能做到同样的事情。

有人知道如何实现吗?

4个回答

26
如果您可以查看开源代码而不会给自己带来问题,请查看Android电话应用程序的源代码。具体来说,是src/com/android/phone/PhoneApp.javasrc/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;

如果您不介意使用可能未记录的功能,它应该可以完全满足您的需求。

1
那是很多需要筛选的内容...恐怕我没有找到太多有用的信息,除非你能指出一些更具体的部分。 - mtmurdock
已添加完整信息--之前不想添加,以防来自开源代码的信息引起问题。 - Dre
3
请注意,使用 Android 4.2.1 版本时,方法getSupportedWakeLockFlags已经不存在了,您需要使用isWakeLockLevelSupported方法。参考链接:http://grepcode.com/file_/repository.grepcode.com/java/ext/com.google.android/android/4.2.1_r1.2/android/os/PowerManager.java/?v=diff&id2=4.1.2_r1 - Muzikant
2
从API级别21(棒棒糖)开始,“PROXIMITY_SCREEN_OFF_WAKE_LOCK”是公共的。 - Eliezer

7

从API 21级(棒棒糖)开始,您可以获取接近唤醒锁,就像这样:

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

那么现在轮到你获取和释放锁了。

附注: PowerManager#getSupportedWakeLockFlags 已经被隐藏,不再存在。他们发明了 isWakeLockLevelSupported 来代替。


2
尽管它说需要API级别21,但似乎是向后兼容的,因为标志一直存在,只是隐藏了。 - kotucz
powerManager是什么? - behelit
https://developer.android.com/reference/android/os/PowerManager - guness

2

1
你所看到的是使用接近传感器。对于具有此功能的设备,您可以通过SensorManager进行访问。

是的,我正在研究这个,但我无法弄清楚实际的实现方法。你看到过如何使用它的示例吗? - mtmurdock
@mtmurdock:不好意思,我没有看到任何东西。我只知道那是有问题的传感器。 - CommonsWare

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接