Proximity Example

This example shows how to access the proximity sensor on a device, if present, and read the values it reports.

A screenshot of the application.

Not all Android devices have proximity sensors, though it may be fairly common on mobile phones. The available sensors on a device can be found by running the Sensor List example.

We begin by importing the classes and modules used or referred to in our code. The most relevant to this example are the sensor classes from the android.hardware module.

from java.lang import Math, String
from android.app import Activity
from android.content import Context
from android.hardware import Sensor, SensorEvent, SensorEventListener, \
                             SensorManager
import android.os
from android.view import View, ViewGroup
from android.widget import LinearLayout, TextView

The ProximityActivity is derived from the standard Activity class and represents the application. Android will create an instance of this class when the user runs it.

class ProximityActivity(Activity):

    __interfaces__ = [SensorEventListener]

The class implements the SensorEventListener interface, declaring this by including it in the list of interfaces defined by the __interfaces__ attribute. Implementing this interface involves implementing two methods that are described later.

The initialisation method simply calls the corresponding method in the base class.

    def __init__(self):
    
        Activity.__init__(self)

The onCreate method calls the base class's onCreate method to help set up the activity. We obtain an object that represents the proximity sensor and set up the user interface.

    @args(void, [android.os.Bundle])
    def onCreate(self, bundle):
    
        Activity.onCreate(self, bundle)

Information about the available sensors is obtained from the device's sensor service. This is obtained using the getSystemService method. The instance we obtain from this method needs to be cast to a suitable type so that we can access its methods.

        sensorManager = self.getSystemService(Context.SENSOR_SERVICE)
        self.sensorManager = CAST(sensorManager, SensorManager)

The proximity sensor is obtained by passing the appropriate constant to the method responsible for returning the default sensor for each type. The value returned may be None, so we must check it before trying to access the sensor.

        self.sensor = self.sensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY)

We create two TextViews. The first is used as a label to show the name of the sensor, or a message in case no sensor is available. The second is used to display the proximity reading from the sensor.

        self.nameLabel = TextView(self)
        self.sensorLabel = TextView(self)

We create a vertical layout to arrange the views, and add them to it.

        layout = LinearLayout(self)
        layout.setLayoutParams(ViewGroup.LayoutParams(
            ViewGroup.LayoutParams.MATCH_PARENT,
            ViewGroup.LayoutParams.WRAP_CONTENT))
        layout.setOrientation(LinearLayout.VERTICAL)
        
        layout.addView(self.nameLabel)
        layout.addView(self.sensorLabel)

If an proximity sensor was not found, we write a message in the name label and indicate that no sensor is available using an instance attribute. Otherwise, we place three empty labels in the list of TextViews we are maintaining and put them in the layout.

        if self.sensor == None:
            self.nameLabel.setText("No suitable sensor found.")
        
        self.setContentView(layout)

The layout is used as the main content in the activity.

When the activity starts, or the user navigates to it, the onResume method is called. Other than calling the corresponding method in the base class, we check whether we have access to an accelerometer using the value stored in the above method. If so, we show its name in the name label and register the instance of this class as a listener for it. This requires that this class implements the SensorEventListener interface.

    def onResume(self):
    
        Activity.onResume(self)
        
        if self.sensor != None:
            self.nameLabel.setText(self.sensor.getName())
            self.sensorManager.registerListener(self, self.sensor,
                SensorManager.SENSOR_DELAY_UI)

When the user navigates away from the activity the onPause method is called. We call the corresponding method in the base class and unregister the instance of this class as a listener. This prevents it from receiving updates from the sensor until it is registered again.

    def onPause(self):
    
        Activity.onPause(self)
        if self.sensor != None:
            self.sensorManager.unregisterListener(self)

The following two methods must be implemented because they are part of the SensorEventListener interface whose methods are both abstract.

The onAccuracyChanged method is used to inform the activity about changes to the accuracy of the sensor. For this simple example we ignore this and simply implement an empty method.

    @args(void, [Sensor, int])
    def onAccuracyChanged(self, sensor, accuracy):
        pass

The onSensorChanged method is used to inform the activity about changes to the values supplied by the sensor. Since this method is only called if we registered the activity as a listener, we can simply read the values for the acceleration on each axis from the supplied event and write them to the labels that were created earlier.

    @args(void, [SensorEvent])
    def onSensorChanged(self, event):
    
        self.sensorLabel.setText(str(event.values[0]) + " centimetres "
            "(max = " + str(self.sensor.getMaximumRange()) + ")")

Files