20

I want to use proximity sensor in my project. I searched for proximity sensor tutorial. And I found a sensor tutorial at http://www.vogella.com/articles/AndroidSensor/article.html#sensoroverview_manager. I tried to use proximity sensor as following code:

@Override
public void onSensorChanged(SensorEvent event)
{
    if(event.sensor.getType() == Sensor.TYPE_PROXIMITY)
    {
        Toast.makeText(getApplicationContext(), "working", Toast.LENGTH_SHORT).show();
    }
}

My Activity is implementing SensorEventListener. But its not working. Do I need to use any permission to use proximity sensor? Or My code is wrong for doing this stuff. Your help will be very appreciated. Thank you

Sanjay Joshi
  • 2,036
  • 6
  • 33
  • 48

4 Answers4

28

I use this code:

import android.content.Context;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity implements SensorEventListener {

    private SensorManager mSensorManager;
    private Sensor mProximity;
    private static final int SENSOR_SENSITIVITY = 4;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);


        mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
        mProximity = mSensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY);

    }

    @Override
    protected void onResume() {
        super.onResume();
        mSensorManager.registerListener(this, mProximity, SensorManager.SENSOR_DELAY_NORMAL);
    }

    @Override
    protected void onPause() {
        super.onPause();
        mSensorManager.unregisterListener(this);
    }

    @Override
    public void onSensorChanged(SensorEvent event) {
        if (event.sensor.getType() == Sensor.TYPE_PROXIMITY) {
            if (event.values[0] >= -SENSOR_SENSITIVITY && event.values[0] <= SENSOR_SENSITIVITY) {
                //near
                Toast.makeText(getApplicationContext(), "near", Toast.LENGTH_SHORT).show();
            } else {
                //far
                Toast.makeText(getApplicationContext(), "far", Toast.LENGTH_SHORT).show();
            }
        }
    }

    @Override
    public void onAccuracyChanged(Sensor sensor, int accuracy) {

    }

}

Also you can check this code in GitHub

Cabezas
  • 9,329
  • 7
  • 67
  • 69
  • 2
    This is unlikely to work. My device (Moto X 2013 on Android 5.1.1) reports `3.0` as near state, so this code would always show "far" – Marcin Koziński May 12 '16 at 19:28
  • 1
    Hi Marcin Kozinski, I had the same problem, you can check my other question and answer [here](http://stackoverflow.com/questions/35767115/unregisterlistener-doesnt-work-with-proximity-screen-off-wake-lock). I hope that I can help you. – Cabezas May 13 '16 at 10:14
  • 2
    Are you sure you've linked to the right question/answer? It looks unrelated and has the same problem: assumes "near" is always `0`, so on some phones it will never report "near". For now I am just checking `if (event.values[0] < sensor.getMaximumRange())`, though I am not sure this is the correct approach either. – Marcin Koziński May 14 '16 at 11:45
  • Do not use `(event.values[0] == 0)` because `event.values[0]` returns a float value, and if you receive 0.00001 the condition will not be satisfied. Use less or equals (<=) with a maximum distance (like 1 or 2 centimeters) to make it work properly. – Thiago Nov 04 '16 at 19:22
  • 4
    Actually, those values can change from device to device. You should use `event.sensor.getMaximumRange()` as `far` value and everything else as `near`. – afe Mar 01 '17 at 10:31
  • Don't use light sensor - see answer below that uses Power Manager. – Vlad Apr 09 '18 at 20:14
  • @Vlad [Device battery life will be significantly affected by the use of this API. Do not acquire PowerManager.WakeLocks unless you really need them, use the minimum levels possible, and be sure to release them as soon as possible.](https://developer.android.com/reference/android/os/PowerManager.html) – Cabezas Apr 10 '18 at 08:06
8

The right way to use proximity sensor is via PowerManager. Forget about light sensor and use Android abstraction and already written code!

public class ProximityViaPowerManager {

private Context context;
private WakeLock proximityWakeLock;

public ProximityViaPowerManager(Context context) {
    this.context = context;
}

public boolean enableProximityWakeLock() {
    if (proximityWakeLock != null) {
      return true;
    }
    PowerManager powerManager = 
 context.getApplicationContext().getSystemService(Context.POWER_SERVICE);
    proximityWakeLock = powerManager.newWakeLock(PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK, TAG);
    proximityWakeLock.acquire();
    return true;
  }

  public void disableProximityWakeLock() {
    if (proximityWakeLock != null) {
      proximityWakeLock.release();
      proximityWakeLock = null;
    }
  }
}

Ensure correct enable/disable capability in Android life cycle resume/pause and add the permission to manifest:

<uses-permission android:name="android.permission.WAKE_LOCK" />
Vlad
  • 4,425
  • 1
  • 30
  • 39
  • 1
    [Device battery life will be significantly affected by the use of this API. Do not acquire PowerManager.WakeLocks unless you really need them, use the minimum levels possible, and be sure to release them as soon as possible.](https://developer.android.com/reference/android/os/PowerManager.html) – Cabezas Apr 10 '18 at 08:07
5

you are to register your listener. In your activity:

@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
protected void onResume() {
    // Register a listener for the sensor.
    super.onResume();
    mSensorManager.registerListener(this, mProximity, SensorManager.SENSOR_DELAY_NORMAL);
}

and then in you overriden onSensorChanged() method you can do your stuff with sensor data.

Sorry if my answer is too late =)

2

You can follow this code which has the basic framework using which we can program any sensor.

Change this line

linearAcceleration = senseManager.getDefaultSensor(Sensor.TYPE_LINEAR_ACCELERATION);

to

proximity = senseManager.getDefaultSensor(Sensor.TYPE_PROXIMITY);
Tunaki
  • 132,869
  • 46
  • 340
  • 423