/*
* This file is part of Sensorium.
*
* Sensorium 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.
*
* Sensorium 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 Sensorium. If not, see
* <http://www.gnu.org/licenses/>.
*
*
*/
/*@IF_PLAY_SERVICES@
package at.univie.sensorium.sensors;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.List;
import java.util.Locale;
import android.location.Address;
import android.location.Geocoder;
import android.location.Location;
import android.os.Bundle;
import android.util.Log;
import at.univie.sensorium.SensorRegistry;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GooglePlayServicesClient.ConnectionCallbacks;
import com.google.android.gms.common.GooglePlayServicesClient.OnConnectionFailedListener;
import com.google.android.gms.common.GooglePlayServicesUtil;
import com.google.android.gms.location.LocationClient;
import com.google.android.gms.location.LocationListener;
import com.google.android.gms.location.LocationRequest;
public class FusedLocationSensor extends AbstractSensor implements LocationListener, ConnectionCallbacks {
private LocationClient mLocationClient;
private static final int priority = LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY;
private static final int updateIntervallMillis = 60000;
private static final int fastestUpdateIntervallMillis = 10000;
private SensorValue longitude;
private SensorValue latitude;
private SensorValue altitude;
private SensorValue accuracy;
private SensorValue bearing;
private SensorValue speed;
private SensorValue address;
public FusedLocationSensor() {
super();
setName("Fused Location");
longitude = new SensorValue(SensorValue.UNIT.DEGREE, SensorValue.TYPE.LONGITUDE);
latitude = new SensorValue(SensorValue.UNIT.DEGREE, SensorValue.TYPE.LATITUDE);
altitude = new SensorValue(SensorValue.UNIT.METER, SensorValue.TYPE.ALTITUDE);
accuracy = new SensorValue(SensorValue.UNIT.METER, SensorValue.TYPE.ACCURACY);
bearing = new SensorValue(SensorValue.UNIT.DEGREE, SensorValue.TYPE.BEARING);
speed = new SensorValue(SensorValue.UNIT.METERSPERSECOND, SensorValue.TYPE.VELOCITY);
address = new SensorValue(SensorValue.UNIT.STRING, SensorValue.TYPE.ADDRESS);
}
@Override
protected void _enable() throws SensorException {
if (playServicesAvailable()) {
mLocationClient = new LocationClient(getContext(), this, connectionFailedListener);
mLocationClient.connect();
// cannot init here, wait for the onConnected callback
} else {
throw new SensorException("Play service not available, not enabling fused location sensor");
}
}
@Override
protected void _disable() {
if (mLocationClient != null) {
mLocationClient.removeLocationUpdates(this);
mLocationClient.disconnect();
}
}
@Override
public void onConnected(Bundle arg0) {
Location mCurrentLocation = mLocationClient.getLastLocation();
if (mCurrentLocation != null) {
longitude.setValue(mCurrentLocation.getLongitude());
latitude.setValue(mCurrentLocation.getLatitude());
altitude.setValue(mCurrentLocation.getAltitude());
accuracy.setValue(mCurrentLocation.getAccuracy());
bearing.setValue(mCurrentLocation.getBearing());
speed.setValue(mCurrentLocation.getSpeed());
}
LocationRequest mLocationRequest = LocationRequest.create();
mLocationRequest.setPriority(priority);
mLocationRequest.setInterval(updateIntervallMillis);
mLocationRequest.setFastestInterval(fastestUpdateIntervallMillis);
mLocationClient.requestLocationUpdates(mLocationRequest, this);
}
@Override
public void onDisconnected() {
// Toast.makeText(getContext(), "Disconnected. Please re-connect.",
// Toast.LENGTH_SHORT).show();
}
@Override
public void onLocationChanged(Location location) {
longitude.setValue(location.getLongitude());
latitude.setValue(location.getLatitude());
altitude.setValue(location.getAltitude());
accuracy.setValue(location.getAccuracy());
bearing.setValue(location.getBearing());
speed.setValue(location.getSpeed());
Geocoder myLocation = new Geocoder(getContext().getApplicationContext(), Locale.getDefault());
List<Address> list = null;
try {
list = myLocation.getFromLocation(location.getLatitude(), location.getLongitude(), 1);
if (list != null && list.size() > 0) {
Address addr = list.get(0);
String addressText = String.format("%s, %s, %s", addr.getMaxAddressLineIndex() > 0 ? addr.getAddressLine(0) : "", addr.getLocality(), // location.getAdminArea(),
addr.getCountryName());
address.setValue(addressText);
} else
address.setValue("n/a");
} catch (IOException e) {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
e.printStackTrace(pw);
Log.d(SensorRegistry.TAG, sw.toString());
}
notifyListeners();
}
// check for play serves as shown in the android example
private boolean playServicesAvailable() {
int resultCode = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this.getContext());
if (ConnectionResult.SUCCESS == resultCode) {
Log.d(SensorRegistry.TAG, "Google Play services is available.");
return true;
} else {
String result = "";
switch (resultCode) {
case (ConnectionResult.DEVELOPER_ERROR):
result = "developer error";
break;
case (ConnectionResult.INTERNAL_ERROR):
result = "internal error";
break;
case (ConnectionResult.LICENSE_CHECK_FAILED):
result = "license check failed";
break;
case (ConnectionResult.NETWORK_ERROR):
result = "network error";
break;
case (ConnectionResult.RESOLUTION_REQUIRED):
result = "resolution required";
break;
case (ConnectionResult.SERVICE_DISABLED):
result = "service disabled";
break;
case (ConnectionResult.SERVICE_INVALID):
result = "service invalid";
break;
case (ConnectionResult.SERVICE_MISSING):
result = "service missing";
break;
case (ConnectionResult.SERVICE_VERSION_UPDATE_REQUIRED):
result = "service version update required";
break;
case (ConnectionResult.SIGN_IN_REQUIRED):
result = "sign in required";
break;
}
Log.d(SensorRegistry.TAG, "Google Play services not available with cause: " + result + ".");
return false;
}
}
private OnConnectionFailedListener connectionFailedListener = new OnConnectionFailedListener() {
// int CONNECTION_FAILURE_RESOLUTION_REQUEST = 9000;
@Override
public void onConnectionFailed(ConnectionResult connectionResult) { // NOOP
// for
// now
// if (connectionResult.hasResolution()) {
// try {
// connectionResult.startResolutionForResult(this,
// CONNECTION_FAILURE_RESOLUTION_REQUEST);
// } catch (IntentSender.SendIntentException e) {
// // Log the error
// e.printStackTrace();
// }
// } else {
// showErrorDialog(connectionResult.getErrorCode());
// }
}
};
}
@ENDIF_PLAY_SERVICES@*/