/*
* 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.util.concurrent.atomic.AtomicBoolean;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import de.unikassel.android.sdcframework.util.AbstractWorkerThread;
import de.unikassel.android.sdcframework.util.Logger;
/**
* Abstract base class for scanner types, which do receive sensor data from
* system broadcasts after the explicit initiation of a system scan. <br/>
* <br/>
* Such a scanner does run a thread to trigger device scans in the configured
* frequency and it is using a broadcast receiver to receive the scan results. <br/>
* Extending classes have to define the related Intent and to implement the
* {@linkplain #doHandleScanResults(Intent) handler} for received samples, as
* well as the {@linkplain #doStartDeviceScan() start} and
* {@linkplain #doStopDeviceScan() stop} methods for the system scan.
*
* @see WifiDeviceScanner
* @see BluetoothDeviceScanner
* @author Katy Hilgenberg
*
*/
public abstract class SampleReceivingDeviceScanner extends
AbstractSensorDeviceScanner
{
/**
* Inner class for a device polling worker thread
*
* @author Katy Hilgenberg
*
*/
private final class ScanWorkerThread extends AbstractWorkerThread
{
/**
* Constructor
*/
public ScanWorkerThread()
{
super();
}
/*
* (non-Javadoc)
*
* @see
* de.unikassel.android.sdcframework.util.AbstractWorkerThread#doCleanUp()
*/
@Override
protected final void doCleanUp()
{}
/*
* (non-Javadoc)
*
* @see de.unikassel.android.sdcframework.util.AbstractWorkerThread#doWork()
*/
@Override
protected final void doWork()
{
if ( isEnabled() )
{
try
{
if ( isLastScanFinished() )
{
if ( doStartDeviceScan() )
{
setLastScanFinished( false );
int frequency =
getDevice().getConfiguration().getFrequency();
sleep( frequency );
}
}
}
catch ( InterruptedException e )
{}
}
}
}
/**
* The broadcast receiver for the device scan results
*/
protected final BroadcastReceiver receiver;
/**
* the worker thread
*/
protected final ScanWorkerThread worker;
/**
* Flag indicating if last scan has finished ( minimal scan frequency is
* always limited by device speed )
*/
protected AtomicBoolean lastScanFinished;
/**
* Constructor
*/
public SampleReceivingDeviceScanner()
{
super();
this.lastScanFinished = new AtomicBoolean( false );
this.worker = new ScanWorkerThread();
this.receiver = new BroadcastReceiver()
{
/*
* (non-Javadoc)
*
* @see
* android.content.BroadcastReceiver#onReceive(android.content.Context,
* android.content.Intent)
*/
@Override
public void onReceive( Context context, Intent intent )
{
// as long as we do have an active scan running do handle results
if ( !isLastScanFinished() )
{
try
{
doHandleScanResults( intent );
}
catch ( Exception e )
{
Logger.getInstance().error( SampleReceivingDeviceScanner.this,
"Exception in doHandleScanResults (BroadcastReceiver): " + e.getMessage() );
}
}
}
};
}
/*
* (non-Javadoc)
*
* @see
* de.unikassel.android.sdcframework.devices.facade.SensorDeviceScanner#start
* (android.content.Context)
*/
@Override
public final boolean start( Context context )
{
setLastScanFinished( true );
// register broadcast receiver for device scan results
registerReceiver( context );
// start worker thread
worker.startWork();
return worker.isWorking();
}
/*
* (non-Javadoc)
*
* @see
* de.unikassel.android.sdcframework.devices.facade.SensorDeviceScanner#stop
* (android.content.Context)
*/
@Override
public final boolean stop( Context context )
{
if ( !isLastScanFinished() )
{
doStopDeviceScan();
}
setLastScanFinished( false );
// stop working cycle of thread
worker.interrupt();
worker.stopWork();
// unregister broadcast receiver for the device scan results
unregisterReceiver( context );
return true;
}
/**
* Does register the broadcast receiver for device scan results
*
* @param context
* the application context
*/
private final void registerReceiver( Context context )
{
IntentFilter intentFilter = getIntentFilter();
context.registerReceiver( receiver, intentFilter );
}
/**
* Does unregister the broadcast receiver for device scan results
*
* @param context
* the application context
*/
private final void unregisterReceiver( Context context )
{
context.unregisterReceiver( receiver );
}
/**
* Getter for the lastScanFinished
*
* @return the lastScanFinished
*/
public final boolean isLastScanFinished()
{
return lastScanFinished.get();
}
/**
* Setter for the lastScanFinished
*
* @param lastScanFinished
* the lastScanFinished to set
*/
public final void setLastScanFinished( boolean lastScanFinished )
{
this.lastScanFinished.set( lastScanFinished );
}
/*
* (non-Javadoc)
*
* @see
* de.unikassel.android.sdcframework.devices.AbstractSensorDeviceScanner#onDestroy
* (android.content.Context)
*/
@Override
public void onDestroy( Context context )
{
// finally terminate our worker thread
worker.doTerminate();
super.onDestroy( context );
}
/**
* Getter for intent filter used by the broadcast receiver
*
* @return the intent filter used by the broadcast receiver
*/
protected abstract IntentFilter getIntentFilter();
/**
* Handler for the device scan results
*
* @param intent
* the broadcast intent to handle
*/
protected abstract void doHandleScanResults( Intent intent );
/**
* Method to start a device scan
*
* @return true if successful, false otherwise
*/
protected abstract boolean doStartDeviceScan();
/**
* Method to stop a device scan which is called if scanner is stopped while a
* scan is ongoing
*/
protected abstract void doStopDeviceScan();
}