/*
* Copyright (C) 2012, Katy Hilgenberg.
* Special acknowledgments to: Knowledge & Data Engineering Group, University of Kassel (http://www.kde.cs.uni-kassel.de).
* Contact: sdcf@cs.uni-kassel.de
*
* This file is part of the SDCFramework (Sensor Data Collection Framework) project.
*
* The SDCFramework is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* The SDCFramework is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with the SDCFramework. If not, see <http://www.gnu.org/licenses/>.
*/
package de.unikassel.android.sdcframework.devices;
import java.security.InvalidParameterException;
import de.unikassel.android.sdcframework.data.Sample;
import de.unikassel.android.sdcframework.data.independent.SampleData;
import de.unikassel.android.sdcframework.devices.facade.SampleProvidingSensorDevice;
import de.unikassel.android.sdcframework.devices.facade.SensorDeviceIdentifier;
import de.unikassel.android.sdcframework.util.Logger;
import de.unikassel.android.sdcframework.util.TimeInformation;
import de.unikassel.android.sdcframework.util.TimeProvider;
import android.content.Context;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
/**
* Base class for an {@link android.hardware.Sensor Android Sensor} type. <br/>
* <br/>
* Does provide the sensor listener and the logic for listener registration
* depending on the scanner running state. Any extending class has just to
* implement the abstract handler methods for sensor changes and the methods
* from the {@link SampleProvidingSensorDevice} interface.
*
* @see AccelerometerDevice
* @author Katy Hilgenberg
*
*/
public abstract class AbstractAndroidSensorDevice
extends ScannerStateAwareSensorDevice
implements SampleProvidingSensorDevice
{
/**
* The sensor listener
*/
private SensorEventListener sensorListener;
/**
* The corresponding Android sensor
*/
private final Sensor sensor;
/**
* The sensor delay
*/
private final int sensorDelay;
/**
*
* Constructor
*
* @param deviceId
* the device identifier
* @param androidSensorType
* the Android sensor type
* @param context
* the application context
* @param sensorDelay
* the sensor delay
* @throws InvalidParameterException
* if sensor type is unavailable or unknown
*/
public AbstractAndroidSensorDevice( SensorDeviceIdentifier deviceId,
int androidSensorType, Context context, int sensorDelay )
throws InvalidParameterException
{
super( deviceId );
this.sensorDelay = sensorDelay;
SensorManager sensorManager =
(SensorManager) context.getSystemService( Context.SENSOR_SERVICE );
this.sensor = sensorManager.getDefaultSensor( androidSensorType );
if ( this.getSensor() == null || androidSensorType == Sensor.TYPE_ALL )
throw new InvalidParameterException( "invalid sensor type or unavailable" );
}
/**
* Setter for the sensor event listener
*
* @param sensorListener
* the sensor event listener
*/
private final void setListener( SensorEventListener sensorListener )
{
this.sensorListener = sensorListener;
}
/**
* Getter for the sensor listener
*
* @return the sensor listener
*/
public final SensorEventListener getListener()
{
if ( sensorListener == null )
{
setListener( new SensorEventListener()
{
/*
* (non-Javadoc)
*
* @see
* android.hardware.SensorEventListener#onSensorChanged(android.hardware
* .SensorEvent)
*/
@Override
public void onSensorChanged( SensorEvent event )
{
try
{
if ( getSensor().equals( event.sensor ) )
{
doHandleSensorChanged( event );
}
}
catch ( Exception e )
{
Logger.getInstance().error( this, "Exception in onSensorChanged" );
}
}
/*
* (non-Javadoc)
*
* @see
* android.hardware.SensorEventListener#onAccuracyChanged(android.hardware
* .Sensor, int)
*/
@Override
public void onAccuracyChanged( Sensor changedSensor, int accuracy )
{
try
{
if ( getSensor().equals( changedSensor ) )
{
doHandleSensorAccuracyChanged( changedSensor, accuracy );
}
}
catch ( Exception e )
{
Logger.getInstance().error( this, "Exception in onAccuracyChanged" );
}
}
} );
}
return sensorListener;
}
/**
* Getter for the sensor
*
* @return the sensor
*/
public final Sensor getSensor()
{
return sensor;
}
/*
* (non-Javadoc)
*
* @see de.unikassel.android.sdcframework.devices.facade.SensorDevice#
* isDeviceInSystemEnabled(android.content.Context)
*/
@Override
public final boolean isDeviceInSystemEnabled( Context context )
{
return sensor != null;
}
/*
* (non-Javadoc)
*
* @see de.unikassel.android.sdcframework.devices.AbstractSensorDevice#
* doSignalDeviceNotEnabledInSystem(android.content.Context)
*/
@Override
protected final void doSignalDeviceNotEnabledInSystem(
Context applicationContext )
{
// nothing to do as sensor is either available or not
}
/**
* Does register the sensor listener for the device type
*
* @param context
* the application context
*/
private final void registerListener( Context context )
{
SensorManager sensorManager =
(SensorManager) context.getSystemService( Context.SENSOR_SERVICE );
sensorManager.registerListener( getListener(), getSensor(), sensorDelay );
}
/**
* Does unregister the sensor listener for the device type
*
* @param context
* the application context
*/
private final void unregisterListener( Context context )
{
SensorManager sensorManager =
(SensorManager) context.getSystemService( Context.SENSOR_SERVICE );
sensorManager.unregisterListener( getListener() );
}
/*
* (non-Javadoc)
*
* @see
* de.unikassel.android.sdcframework.devices.ScannerStateAwareSensorDevice
* #onScannerRunningStateChange(boolean)
*/
@Override
protected final void
onScannerRunningStateChange( boolean isRunning, Context context )
{
// depending on scanner running state add listener or remove it
if ( isRunning )
registerListener( context );
else
unregisterListener( context );
}
/**
* Handler for the sensor changed event ( with incoming updated sensor data )
*
* @param event
* the sensor event to handle
*/
protected abstract void doHandleSensorChanged( SensorEvent event );
/**
* Handler for the sensor accuracy changed event
*
* @param sensor
* the sensor
* @param accuracy
* the accuracy
*/
protected void doHandleSensorAccuracyChanged( Sensor sensor, int accuracy )
{
// for the moment this seems not of interest
// can be overridden of extending types
}
/*
* (non-Javadoc)
*
* @see
* de.unikassel.android.sdcframework.devices.facade.SampleProvidingSensorDevice
* #getSample()
*/
@Override
public final synchronized Sample getSample()
{
TimeInformation ti = TimeProvider.getInstance().getAccurateTimeInformation();
Sample sample =
SampleFactory.getInstance().createSample( ti, getDeviceIdentifier(),
getConfiguration().getSamplePriority().ordinal(),
getCurrentSampleData().doClone() );
return sample;
}
/**
* Getter for the current sample data
*
* @return the current sample data
*/
protected abstract SampleData getCurrentSampleData();
}