Sensors are to be enabled when App
is created.
The following example enables all sensors.
The events (SensorEvent
, ASensorAccelerometer
, ASensorMagneticField
...)
are sent to the input
callback of App
redef class App
init
do
sensors_support_enabled = true
accelerometer.enabled = true
accelerometer.eventrate = 10000
magnetic_field.enabled = true
gyroscope.enabled = true
light.enabled = true
proximity.enabled = true
end
end
android :: ASensorAccelerometer
Sensor event returned by the Accelerometer sensorandroid :: ASensorMagneticField
Sensor event returned by the Magnetic Field sensorandroid $ ASensorAccelerometer
Sensor event returned by the Accelerometer sensorandroid $ ASensorMagneticField
Sensor event returned by the Magnetic Field sensorSerializable::inspect
to show more useful information
more_collections :: more_collections
Highly specific, but useful, collections-related classes.serialization :: serialization_core
Abstract services to serialize Nit objects to different formatscore :: union_find
union–find algorithm using an efficient disjoint-set data structure
# Access Android sensors
#
# Sensors are to be enabled when `App` is created.
# The following example enables all sensors.
# The events (`SensorEvent`, `ASensorAccelerometer`, `ASensorMagneticField`...)
# are sent to the `input` callback of `App`
#
# ~~~~nitish
# redef class App
# init
# do
# sensors_support_enabled = true
# accelerometer.enabled = true
# accelerometer.eventrate = 10000
# magnetic_field.enabled = true
# gyroscope.enabled = true
# light.enabled = true
# proximity.enabled = true
# end
# end
# ~~~~
module sensors
import android
import gamnit
in "C header" `{
#include <jni.h>
#include <android/sensor.h>
`}
extern class ASensorType `{int`}
new accelerometer: ASensorType `{return ASENSOR_TYPE_ACCELEROMETER;`}
fun is_accelerometer: Bool `{return self == ASENSOR_TYPE_ACCELEROMETER;`}
new magnetic_field: ASensorType `{return ASENSOR_TYPE_MAGNETIC_FIELD;`}
fun is_magnetic_field: Bool `{return self == ASENSOR_TYPE_MAGNETIC_FIELD;`}
new gyroscope:ASensorType `{return ASENSOR_TYPE_GYROSCOPE;`}
fun is_gyroscope: Bool `{ return self == ASENSOR_TYPE_GYROSCOPE;`}
new light: ASensorType `{return ASENSOR_TYPE_LIGHT;`}
fun is_light: Bool `{return self == ASENSOR_TYPE_LIGHT;`}
new proximity: ASensorType `{return ASENSOR_TYPE_PROXIMITY;`}
fun is_proximity:Bool `{return self == ASENSOR_TYPE_PROXIMITY;`}
end
# Manages the sensors
extern class ASensorManager `{ASensorManager*`}
new get_instance: ASensorManager `{return ASensorManager_getInstance();`}
# Returns the list of available sensors
fun get_sensor_list: Pointer `{
ASensorList *list;
ASensorManager_getSensorList(self, list);
return list;
`}
# Create a new sensor event queue and associate it with a looper
fun create_event_queue(app: NativeAppGlue): ASensorEventQueue `{
return ASensorManager_createEventQueue(self, app->looper, LOOPER_ID_USER, NULL, NULL);
`}
# Returns the default sensor of the given type
fun get_default_sensor(sensortype: ASensorType): ASensor `{
return ASensorManager_getDefaultSensor(self, sensortype);
`}
# Destroys the event queue and free all resources associated to it
fun destroy_event_queue(queue: ASensorEventQueue) `{
ASensorManager_destroyEventQueue(self, queue);
`}
end
# Manages the sensors events
extern class ASensorEventQueue `{ASensorEventQueue*`}
# Enable the selected sensor, returns a negative value on error
fun enable_sensor(sensor: ASensor): Int `{
return ASensorEventQueue_enableSensor(self, sensor);
`}
# Disable the selected sensor, returns a negative value on error
fun disable_sensor(sensor: ASensor): Int `{
return ASensorEventQueue_disableSensor(self, sensor);
`}
# Set the delivery rate of events in microseconds for the given sensor
fun set_event_rate(sensor: ASensor, usec: Int): Int `{
return ASensorEventQueue_setEventRate(self, sensor, usec);
`}
# Returns 1 if the queue has events, 0 if it does not have events,
# and a negative value if there is an error
fun has_events: Int `{
return ASensorEventQueue_hasEvents(self);
`}
# Returns the next available events from the queue.
# Returns a negative value if no events are available or an error has occured
# otherwise the number of events returned
fun get_events(events: ASensorEvents, count: Int): Int `{
return ASensorEventQueue_getEvents(self, events, (size_t)count);
`}
end
# Extern class referencing a ASensor
extern class ASensor `{ASensorRef`}
new `{return malloc(sizeof(ASensorRef));`}
fun name: CString `{return (char*)ASensor_getName(self);`}
fun vendor: CString `{return (char*)ASensor_getVendor(self);`}
fun sensor_type: ASensorType `{return ASensor_getType(self);`}
fun resolution: Float `{return ASensor_getResolution(self);`}
fun min_delay: Int `{return ASensor_getMinDelay(self);`}
end
# NIT representation of an Android Sensor used in android_app to initialize sensors
class AndroidSensor
var asensor = new ASensor is writable
var enabled = false is writable
var event_rate = 100000 is writable
fun name: String do return asensor.name.to_s
fun vendor: String do return asensor.vendor.to_s
fun sensor_type: ASensorType do return asensor.sensor_type
fun resolution: Float do return asensor.resolution
fun min_delay: Int do return asensor.min_delay
end
# Extern class referencing a ASensorEvent
extern class ASensorEvent `{ASensorEvent*`}
super SensorEvent
fun version: Int `{return self->version;`}
fun sensor: ASensor `{return (ASensorRef)self->sensor;`}
fun sensor_type: ASensorType `{return self->type;`}
fun timestamp: Int `{return self->timestamp;`}
end
extern class FullSensor `{ASensorEvent*`}
super ASensorLight
super ASensorProximity
fun temperature: Float `{return self->temperature;`}
fun pressure: Float `{return self->pressure;`}
fun data: Pointer `{return self->data;`}
fun vector: ASensorVector `{return &(self->vector);`}
fun acceleration: ASensorVector `{return &(self->acceleration);`}
fun magnetic: ASensorVector `{return &(self->magnetic);`}
end
# Extern class referencing a ASensorVector, attribute of ASensorRef
extern class ASensorVector `{ASensorVector*`}
fun v: Pointer `{return self->v;`}
fun x: Float `{ return self->x;`}
fun y: Float `{return self->y;`}
fun z: Float `{return self->z;`}
fun azimuth: Float `{return self->azimuth;`}
fun pitch: Float `{return self->pitch;`}
fun roll: Float `{return self->roll;`}
fun status: Int `{return self->status;`}
fun reserved: Pointer `{return self->reserved;`}
end
# Sensor event returned by the Accelerometer sensor
extern class ASensorAccelerometer `{ASensorEvent*`}
super ASensorEvent
fun x: Float `{return self->acceleration.x;`}
fun y: Float `{return self->acceleration.y;`}
fun z: Float `{return self->acceleration.z;`}
end
# Sensor event returned by the Magnetic Field sensor
extern class ASensorMagneticField `{ASensorEvent*`}
super ASensorEvent
fun x: Float `{return self->magnetic.x;`}
fun y: Float `{return self->magnetic.y;`}
fun z: Float `{ return self->magnetic.z;`}
end
# Sensor event returned by the gyroscope sensor
extern class ASensorGyroscope `{ASensorEvent*`}
super ASensorEvent
fun x: Float `{return self->vector.x;`}
fun y: Float `{return self->vector.y;`}
fun z: Float `{return self->vector.y;`}
end
# Sensor event returned by the Light sensor
extern class ASensorLight `{ASensorEvent*`}
super ASensorEvent
fun light: Float `{return self->light;`}
end
# sensor event returned by the Proximity Sensor
extern class ASensorProximity `{ASensorEvent*`}
super ASensorEvent
fun distance: Float `{return self->distance;`}
end
# Array of SensorEvents
extern class ASensorEvents `{ASensorEvent*`}
new (length: Int) `{return malloc(sizeof(ASensorEvent)*length);`}
fun [](index: Int): ASensorEvent `{
return self+index;
`}
end
redef class App
var accelerometer = new AndroidSensor
var magnetic_field = new AndroidSensor
var gyroscope = new AndroidSensor
var light = new AndroidSensor
var proximity = new AndroidSensor
var sensormanager: ASensorManager
var eventqueue: ASensorEventQueue
var sensors_support_enabled = false is writable
private fun extern_input_sensor_accelerometer(event: ASensorAccelerometer) do accept_event(event)
private fun extern_input_sensor_magnetic_field(event: ASensorMagneticField) do accept_event(event)
private fun extern_input_sensor_gyroscope(event: ASensorGyroscope) do accept_event(event)
private fun extern_input_sensor_light(event: ASensorLight) do accept_event(event)
private fun extern_input_sensor_proximity(event: ASensorProximity) do accept_event(event)
# Sensors support
# The user decides which sensors he wants to use by setting them enabled
private fun enable_sensors
do
if sensors_support_enabled then enable_sensors_management else return
if accelerometer.enabled then enable_accelerometer
if magnetic_field.enabled then enable_magnetic_field
if gyroscope.enabled then enable_gyroscope
if light.enabled then enable_light
if proximity.enabled then enable_proximity
end
private fun enable_sensors_management
do
sensormanager = new ASensorManager.get_instance
#eventqueue = sensormanager.create_event_queue(new NdkAndroidApp)
eventqueue = initialize_event_queue(sensormanager, native_app_glue.looper)
end
# HACK: need a nit method to get mnit_java_app, then we can use the appropriate sensormanager.create_event_queue method to initialize the event queue
private fun initialize_event_queue(sensormanager: ASensorManager, looper: ALooper): ASensorEventQueue `{
return ASensorManager_createEventQueue(sensormanager, looper, LOOPER_ID_USER, NULL, NULL);
`}
private fun enable_accelerometer
do
accelerometer.asensor = sensormanager.get_default_sensor(new ASensorType.accelerometer)
if accelerometer.asensor.address_is_null then
print "Accelerometer sensor unavailable"
else
if eventqueue.enable_sensor(accelerometer.asensor) < 0 then print "Accelerometer enabling failed"
eventqueue.set_event_rate(accelerometer.asensor, accelerometer.event_rate)
end
end
private fun enable_magnetic_field
do
magnetic_field.asensor = sensormanager.get_default_sensor(new ASensorType.magnetic_field)
if magnetic_field.asensor.address_is_null then
print "Magnetic Field unavailable"
else
if eventqueue.enable_sensor(magnetic_field.asensor) < 0 then print "Magnetic Field enabling failed"
eventqueue.set_event_rate(magnetic_field.asensor, magnetic_field.event_rate)
end
end
private fun enable_gyroscope
do
gyroscope.asensor = sensormanager.get_default_sensor(new ASensorType.gyroscope)
if gyroscope.asensor.address_is_null then
print "Gyroscope sensor unavailable"
else
if eventqueue.enable_sensor(gyroscope.asensor) < 0 then print "Gyroscope enabling failed"
eventqueue.set_event_rate(gyroscope.asensor, gyroscope.event_rate)
end
end
private fun enable_light
do
light.asensor = sensormanager.get_default_sensor(new ASensorType.light)
if light.asensor.address_is_null then
print "Light sensor unavailable"
else
if eventqueue.enable_sensor(light.asensor) < 0 then print "Light enabling failed"
eventqueue.set_event_rate(light.asensor, light.event_rate)
end
end
private fun enable_proximity
do
proximity.asensor = sensormanager.get_default_sensor(new ASensorType.proximity)
if proximity.asensor.address_is_null then
print "Proximity sensor unavailable"
else
if eventqueue.enable_sensor(proximity.asensor) < 0 then print "Proximity enabling failed"
eventqueue.set_event_rate(light.asensor, light.event_rate)
end
end
redef fun run
do
enable_sensors
super
end
redef fun handle_looper_event(ident, event, data)
do
super
handle_sensor_events(ident)
end
private fun handle_sensor_events(ident: Int) import extern_input_sensor_accelerometer, extern_input_sensor_magnetic_field, extern_input_sensor_gyroscope, extern_input_sensor_light, extern_input_sensor_proximity, eventqueue `{
//If a sensor has data, process it
if(ident == LOOPER_ID_USER) {
//maybe add a boolean to the app to know if we want to use Sensor API or ASensorEvent directly ...
ASensorEvent* events = malloc(sizeof(ASensorEvent)*10);
int nbevents;
ASensorEventQueue* queue = App_eventqueue(self);
while((nbevents = ASensorEventQueue_getEvents(queue, events, 10)) > 0) {
int i;
for(i = 0; i < nbevents; i++){
ASensorEvent event = events[i];
switch (event.type) {
case ASENSOR_TYPE_ACCELEROMETER:
App_extern_input_sensor_accelerometer(self, &event);
break;
case ASENSOR_TYPE_MAGNETIC_FIELD:
App_extern_input_sensor_magnetic_field(self, &event);
break;
case ASENSOR_TYPE_GYROSCOPE:
App_extern_input_sensor_gyroscope(self, &event);
break;
case ASENSOR_TYPE_LIGHT:
App_extern_input_sensor_light(self, &event);
break;
case ASENSOR_TYPE_PROXIMITY:
App_extern_input_sensor_proximity(self, &event);
break;
}
}
}
}
`}
end
lib/android/sensors.nit:17,1--372,3