8

I know in Galaxy Samsung SIII it is possible to configure in settings an option to avoid the screen turns off when user is looking into the screen. I think the phone uses the camera or a kind of a sensor of presence.

  1. is it possible to do it programmatically?
  2. even if yes, some devices won't be capable to do that. I imagine some possibilities here: using the camera, accelerometer, or even user activity: if the screen is on, touches, I don't know. There is a specific library about "user presence" to android? Using the best of all sensors when available?
Felipe
  • 16,649
  • 11
  • 68
  • 92
  • 2
    Usually if I want X I'll look for Y: Inactivity -> http://stackoverflow.com/questions/4208730/how-to-detect-user-inactivity-in-android There is also an answer pertaining to Activity by the user. – Nate-Wilkins Dec 19 '12 at 15:36
  • 3
    The SIII uses the front facing camera to check periodically for facial features. (There's info in the docs, including a warning that it reduces battery life by enabling it.) – Ken White Dec 19 '12 at 15:58
  • But @KenWhite, I think there is a kind of "face recognition" software (or chipset) also. Do you know if is it possible to use that? Or your app need to do your own face recognition? I know iOS has native functions about that. – Felipe Dec 19 '12 at 17:04
  • @FelipeMicaroniLalli: No, not for the feature you're asking about. There is a "proximity sensor" that detects whether your phone is held to your ear, but for the "stay on when user looks at screen" it uses the front camera. `Settings->Display->Smart stay`, and turn off and on. "Smart stay detects your eyes *with the front camera* so that the screen stays on when you are looking at it", with an animated image that demonstrates. – Ken White Dec 19 '12 at 17:15
  • @KenWhite, I got it, thanks! But this: "detects your eyes" should be a software, library or even a chipset. Do you know if is possible to access it programmatically? Or is it hidden by Samsung? There is any library to detect eyes or face recognition in android? – Felipe Dec 19 '12 at 17:37

2 Answers2

6

Yes, there's something like that.

You can use SensorManager to get sensor events. For example, Light Sensor will be usefull for you:

private SensorManager sensorManager;
private Sensor lightSensor;
private float lightAmount;

public void onCreate(Bundle savedInstanceState) {
     super.onCreate(savedInstanceState);
     setContentView(R.layout.main);
     sensorManager = (SensorManager)getSystemService(SENSOR_SERVICE);
     lightSensor = sensorManager.getDefaultSensor(Sensor.TYPE_LIGHT);

     SensorEventListener listener = new SensorEventListener() {
         @Override
         public void onSensorChanged(SensorEvent event) {
             // returns the current light amount
             lightAmount = event.data[0];
         }

     lightSensor.registerListener(listener);
}

But of course he can't do all the job alone. Program your light sensor to see when the screen becomes brighter, if true that should mean the user is no longer looking to it. And you can use the accelerometer (as you said) to help you out. I found some code and adapted it, the class should be something like this:

public class AccelerometerDetector {

    boolean isAvailable = false;
    boolean isEnabled = false;

    /**
     * Constructor.
     *
     * @param enable : True to enable the accelerometer
     * @throws UnsupportedOperationException
     *  - thrown if the Accelerometer is not available on the current device.
     */
    public AccelerometerDetector(boolean enable) 
            throws UnsupportedOperationException 
    {
            /* Check if the sensor is available */
            for (String accelerometer : Sensors.getSupportedSensors())
                    if (accelerometer.equals(Sensors.SENSOR_ACCELEROMETER))
                            isAvailable = true;

            if (!accelerometerAvailable)
                    throw new UnsupportedOperationException(
                                    "Accelerometer is not available.");

            if (enable)
                    setEnableAccelerometer(true);
    }

    /**
     * Set if the Accelerometer is enabled or not.
     *
     * @param enable
     * @throws UnsupportedOperationException
     */
    public void setEnableAccelerometer(boolean enable)
            throws UnsupportedOperationException 
    {
            if (!accelerometerAvailable)
                    throw new UnsupportedOperationException(
                                    "Accelerometer is not available.");

            /* If should be enabled and isn't already */
            if (enable && !this.isEnabled) {
                    Sensors.enableSensor(Sensors.SENSOR_ACCELEROMETER);
                    this.isEnabled = true;
            } else /* If should be disabled and isn't already */
            if (!enable && this.isEnabled) {
                    Sensors.disableSensor(Sensors.SENSOR_ACCELEROMETER);
                    this.isEnabled = false;
            }
    }

    /**
     * Read the values provided by the Accelerometer.
     *
     * @return Current Accelerometer-values.
     * @throws UnsupportedOperationException
     *             if the Accelerometer is not available on this device.
     * @throws IllegalStateException
     *             if the Accelerometer was disabled.
     */
    public float[] readAccelerometer() 
            throws UnsupportedOperationException, IllegalStateException 
    {
            if (!isAvailable)
                    throw new UnsupportedOperationException(
                                    "Accelerometer is not available.");

            if (!this.isEnabled)
                    throw new IllegalStateException(
                                    "Accelerometer was disabled.");
            /* Get number of sensor-values the sensor will return. Could be
             * variable, depending of the amount of axis (1D, 2D or 3D
             * accelerometer). */
            int sensorValues = Sensors
                            .getNumSensorValues(Sensors.SENSOR_ACCELEROMETER);
            float[] values = new float[sensorValues];

            /* Make the OS fill the array we passed. */
            Sensors.readSensor(Sensors.SENSOR_ACCELEROMETER, values);

            return values;
    }
}

Also declare this feature in your Manifest.xml:

<uses-feature android:name="android.hardware.sensor.light" />
<uses-feature android:name="android.hardware.sensor.accelerometer" />

What you called "Presence Sensor" might be the Light/Proximity Sensor. But you can't use the Proximity Sensor because it usually only has 5cm range.

enter image description here

Sergio Carneiro
  • 3,726
  • 4
  • 35
  • 51
  • Thanks Sergio! I'll test it. There is an special permission to use these sensors? – Felipe Dec 19 '12 at 15:48
  • 1
    Yes it is! I just forgot to tell you, I'll edit my question ^^ – Sergio Carneiro Dec 19 '12 at 15:48
  • the first piece of code, the "light sensor" is that one of 5cm or it is something like "the screen is on/off"? I think if I can know the screen is ON is already good enough. – Felipe Dec 19 '12 at 17:06
  • 2
    The light sensor is to determine how much light the screen is receiving, if it receives few light it can mean 2 things: the user is looking to the phone or is in a dark place, so if you link the accelerometer to see if the device is shaking you can pressupose the user is looking and holding it. But if you only want to know if the screen is ON it's much simpler. See [this](http://thinkandroid.wordpress.com/2010/01/24/handling-screen-off-and-screen-on-intents/) – Sergio Carneiro Dec 19 '12 at 17:18
  • 1
    Thanks one more time @SergioCarneiro. I think "light sensor" here is not that much useful. When the screen is ON and the accelerometer is "shaking", I think I can suppose the user is using the phone. – Felipe Dec 19 '12 at 17:39
0

You can use device's front camera to detect user's face and hence check the presence of the user. The good thing is this can work on any android phone with the front camera.

Here is the library from GitHub that demonstrates how you can achieve it using Google Play Services' Vission APIs.

Keval Patel
  • 592
  • 3
  • 13