/* * Copyright 2008-2013, ETH Zürich, Samuel Welten, Michael Kuhn, Tobias Langner, * Sandro Affentranger, Lukas Bossard, Michael Grob, Rahul Jain, * Dominic Langenegger, Sonia Mayor Alonso, Roger Odermatt, Tobias Schlueter, * Yannick Stucki, Sebastian Wendland, Samuel Zehnder, Samuel Zihlmann, * Samuel Zweifel * * This file is part of Jukefox. * * Jukefox is free software: you can redistribute it and/or modify it under the * terms of the GNU General Public License as published by the Free Software * Foundation, either version 3 of the License, or any later version. Jukefox 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 General Public License for more details. * * You should have received a copy of the GNU General Public License along with * Jukefox. If not, see <http://www.gnu.org/licenses/>. */ package ch.ethz.dcg.pancho3.data.context; import java.util.Timer; import java.util.TimerTask; import android.app.Activity; import android.content.Context; import android.hardware.Sensor; import android.hardware.SensorEvent; import android.hardware.SensorEventListener; import android.hardware.SensorManager; import android.net.ConnectivityManager; import ch.ethz.dcg.jukefox.commons.utils.Log; import ch.ethz.dcg.jukefox.controller.player.IOnPlayerStateChangeListener; import ch.ethz.dcg.jukefox.controller.player.IReadOnlyPlayerController; import ch.ethz.dcg.jukefox.data.context.AbstractContextResult; import ch.ethz.dcg.jukefox.data.context.IContextProvider; import ch.ethz.dcg.jukefox.manager.AndroidSettingsManager; import ch.ethz.dcg.jukefox.model.collection.BaseAlbum; import ch.ethz.dcg.jukefox.model.collection.BaseArtist; import ch.ethz.dcg.jukefox.model.collection.PlaylistSong; import ch.ethz.dcg.jukefox.model.player.PlayerState; import ch.ethz.dcg.pancho3.commons.utils.AndroidUtils; import ch.ethz.dcg.pancho3.model.JukefoxApplication; public class AndroidContextProvider implements IOnPlayerStateChangeListener, IContextProvider { public static final String TAG = AndroidContextProvider.class.getSimpleName(); private static final long NETWORK_STATE_POLL_INTERVALL = 10 * 1000; private SensorManager sm; private SensorEventListener proximityListener; private SensorEventListener lightListener; private SensorEventListener orientationListener; private SensorEventListener accelerationListener; private Sensor proximitySensor; private Sensor lightSensor; private Sensor orientationSensor; private Sensor accelerationSensor; private boolean sensorsRegistered = false; private AccelerationDataHandler accelerationDataHandler; private LightDataHandler lightDataHandler; private ProximityDataHandler proximityDataHandler; private OrientationDataHandler orientationDataHandler; private NetworkStateDataHandler networkStateDataHandler; private ConnectivityManager connectivity = null; private Timer networkConnectivityPoll = null; private IReadOnlyPlayerController playerController; public AndroidContextProvider() { sm = (SensorManager) JukefoxApplication.getAppContext().getSystemService(Activity.SENSOR_SERVICE); accelerationDataHandler = new AccelerationDataHandler(); orientationDataHandler = new OrientationDataHandler(); lightDataHandler = new LightDataHandler(); proximityDataHandler = new ProximityDataHandler(); networkStateDataHandler = new NetworkStateDataHandler(); connectivity = (ConnectivityManager) JukefoxApplication.getAppContext().getSystemService( Context.CONNECTIVITY_SERVICE); } /* * (non-Javadoc) * * @see * ch.ethz.dcg.pancho3.data.context.IContextProvider#getLatestContextValues * () */ public AbstractContextResult getLatestContextValues() { AbstractContextResult result = new AndroidContextResult(); result.setOrientationChange(orientationDataHandler.getLatestValue()); AccelerationData accData = accelerationDataHandler.getLatestValue(); if (accData != null) { result.setOrientation(accData.getOrientation()); result.setAccelerationEnergy(accData.getEnergy()); } result.setLight(proximityDataHandler.getLatestValue()); result.setAccelerationEnergy(lightDataHandler.getLatestValue()); result.setNetworkState(networkStateDataHandler.getLatestValue()); return result; } /* * (non-Javadoc) * * @see * ch.ethz.dcg.pancho3.data.context.IContextProvider#getMeanContextValues * (int) */ public AbstractContextResult getMeanContextValues(int millisBack) { AbstractContextResult result = new AndroidContextResult(); try { result.setOrientationChange(orientationDataHandler.getMeanValue(millisBack)); AccelerationData accData = accelerationDataHandler.getMeanValue(millisBack); if (accData != null) { result.setOrientation(accData.getOrientation()); result.setAccelerationEnergy(accData.getEnergy()); } result.setLight(lightDataHandler.getMeanValue(millisBack)); result.setProximity(proximityDataHandler.getMeanValue(millisBack)); result.setNetworkState(networkStateDataHandler.getMeanValue(millisBack)); } catch (Exception e) { Log.w(TAG, e); } return result; } private synchronized void registerSensors() { // Do not register or unregister Sensors for devices for which the // sensors can not be properly unregistered if (AndroidUtils.isSensorProblemDevice()) { if (AndroidSettingsManager.getAndroidSettingsReader().isShakeSkip()) { registerAccelerometerOnly(); } return; } Log.v(TAG, "registorSensors: sensorsRegistered: " + sensorsRegistered); if (sensorsRegistered) { return; } try { createSensorListeners(); accelerationSensor = sm.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); if (accelerationSensor != null) { sm.registerListener(accelerationListener, accelerationSensor, SensorManager.SENSOR_DELAY_GAME); } proximitySensor = sm.getDefaultSensor(Sensor.TYPE_PROXIMITY); if (proximitySensor != null) { proximityDataHandler.setMax(proximitySensor.getMaximumRange()); sm.registerListener(proximityListener, proximitySensor, SensorManager.SENSOR_DELAY_NORMAL); } lightSensor = sm.getDefaultSensor(Sensor.TYPE_LIGHT); if (lightSensor != null) { sm.registerListener(lightListener, lightSensor, SensorManager.SENSOR_DELAY_NORMAL); } orientationSensor = sm.getDefaultSensor(Sensor.TYPE_ORIENTATION); if (orientationSensor != null) { sm.registerListener(orientationListener, orientationSensor, SensorManager.SENSOR_DELAY_NORMAL); } networkConnectivityPoll = new Timer(); networkConnectivityPoll.schedule(new TimerTask() { @Override public void run() { networkStateDataHandler.onNewEvent(connectivity.getActiveNetworkInfo()); } }, 0, NETWORK_STATE_POLL_INTERVALL); } finally { sensorsRegistered = true; } } private void registerAccelerometerOnly() { accelerationListener = new SensorEventListener() { @Override public void onAccuracyChanged(Sensor sensor, int accuracy) { } @Override public void onSensorChanged(SensorEvent event) { accelerationDataHandler.onNewEvent(event); } }; accelerationSensor = sm.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); if (accelerationSensor != null) { sm.registerListener(accelerationListener, accelerationSensor, SensorManager.SENSOR_DELAY_GAME); } } private void unregisterAccelerometerOnly() { unregisterSensorListener(accelerationListener); accelerationListener = null; accelerationSensor = null; } private synchronized void unregisterSensors() { // Do not register or unregister Sensors for devices for which the // sensors can not be properly unregistered if (AndroidUtils.isSensorProblemDevice()) { if (AndroidSettingsManager.getAndroidSettingsReader().isShakeSkip()) { unregisterAccelerometerOnly(); } return; } Log.v(TAG, "unregistorSensors: sensorsRegistered: " + sensorsRegistered); if (!sensorsRegistered) { return; } try { unregisterSensorListener(proximityListener); proximityListener = null; proximitySensor = null; unregisterSensorListener(lightListener); lightListener = null; lightSensor = null; unregisterSensorListener(orientationListener); orientationListener = null; orientationSensor = null; unregisterSensorListener(accelerationListener); accelerationListener = null; accelerationSensor = null; if (networkConnectivityPoll != null) { networkConnectivityPoll.cancel(); } } finally { sensorsRegistered = false; } } private void unregisterSensorListener(SensorEventListener listener) { try { sm.unregisterListener(listener); } catch (Exception e) { Log.w(TAG, e); } } private synchronized void createSensorListeners() { proximityListener = new SensorEventListener() { @Override public void onAccuracyChanged(Sensor sensor, int accuracy) { } @Override public void onSensorChanged(SensorEvent event) { proximityDataHandler.onNewEvent(event); } }; lightListener = new SensorEventListener() { @Override public void onAccuracyChanged(Sensor sensor, int accuracy) { } @Override public void onSensorChanged(SensorEvent event) { lightDataHandler.onNewEvent(event); } }; orientationListener = new SensorEventListener() { @Override public void onAccuracyChanged(Sensor sensor, int accuracy) { } @Override public void onSensorChanged(SensorEvent event) { orientationDataHandler.onNewEvent(event); } }; accelerationListener = new SensorEventListener() { @Override public void onAccuracyChanged(Sensor sensor, int accuracy) { } @Override public void onSensorChanged(SensorEvent event) { accelerationDataHandler.onNewEvent(event); } }; } /* * (non-Javadoc) * * @see * ch.ethz.dcg.pancho3.data.context.IContextProvider#reregisterSensors() */ public void reregisterSensors() { unregisterSensors(); registerSensors(); } @Override public void onPlayerStateChanged(final PlayerState playerState) { new Thread(new Runnable() { @Override public void run() { if (playerState == PlayerState.PLAY) { // Log.v(TAG, "registering sensors"); registerSensors(); } else { // Log.v(TAG, "unregistering sensors"); unregisterSensors(); } } }).start(); } /* * (non-Javadoc) * * @see ch.ethz.dcg.pancho3.data.context.IContextProvider#onSongCompleted() */ @Override public void onSongCompleted() { } /* * (non-Javadoc) * * @see ch.ethz.dcg.pancho3.data.context.IContextProvider#onSongStarted() */ @Override public void onSongStarted() { } @Override public void onSongCompleted(PlaylistSong<BaseArtist, BaseAlbum> song) { } @Override public void onSongSkipped(PlaylistSong<BaseArtist, BaseAlbum> song, int position) { } @Override public void onSongStarted(PlaylistSong<BaseArtist, BaseAlbum> song) { } @Override public void setPlayerController(IReadOnlyPlayerController playerController) { this.playerController = playerController; this.playerController.addOnPlayerStateChangeListener(this); } }