/*
* This source is part of the
* _____ ___ ____
* __ / / _ \/ _ | / __/___ _______ _
* / // / , _/ __ |/ _/_/ _ \/ __/ _ `/
* \___/_/|_/_/ |_/_/ (_)___/_/ \_, /
* /___/
* repository.
*
* Copyright (C) 2014-2015 Carmen Alvarez (c@rmen.ca)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ca.rmen.android.networkmonitor.app.service.datasources;
import android.content.ContentValues;
import android.content.Context;
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
import android.location.Location;
import android.preference.PreferenceManager;
import ca.rmen.android.networkmonitor.Constants;
import ca.rmen.android.networkmonitor.app.prefs.NetMonPreferences;
import ca.rmen.android.networkmonitor.app.prefs.NetMonPreferences.LocationFetchingStrategy;
import ca.rmen.android.networkmonitor.provider.NetMonColumns;
import ca.rmen.android.networkmonitor.util.Log;
import ca.rmen.android.networkmonitor.util.PermissionUtil;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.location.LocationListener;
import com.google.android.gms.location.LocationRequest;
import com.google.android.gms.location.LocationServices;
/**
* Retrieves the device's location, using Google Play Services.
*/
public class GmsDeviceLocationDataSource implements NetMonDataSource {
private static final String TAG = Constants.TAG + GmsDeviceLocationDataSource.class.getSimpleName();
private final GoogleApiClient mLocationClient;
private Location mMostRecentLocation;
private Context mContext;
GmsDeviceLocationDataSource(Object locationClient) {
mLocationClient = (GoogleApiClient) locationClient;
}
@Override
public void onCreate(Context context) {
Log.v(TAG, "onCreate");
mContext = context;
PreferenceManager.getDefaultSharedPreferences(context).registerOnSharedPreferenceChangeListener(mPreferenceListener);
registerLocationListener();
}
/**
* @return the last location the device recorded in a ContentValues with keys {@link NetMonColumns#DEVICE_LATITUDE} and
* {@link NetMonColumns#DEVICE_LONGITUDE}. Uses Google Play Services.
*/
@Override
@SuppressWarnings("MissingPermission")
public ContentValues getContentValues() {
Log.v(TAG, "getContentValues");
ContentValues values = new ContentValues(3);
if (!PermissionUtil.hasLocationPermission(mContext)) {
Log.v(TAG, "No location permission.");
return values;
}
if (!mLocationClient.isConnected()) {
Log.v(TAG, "LocationClient not connected, doing nothing");
return values;
}
// Try getting the location from the LocationClient
mMostRecentLocation = LocationServices.FusedLocationApi.getLastLocation(mLocationClient);
Log.v(TAG, "Most recent location: " + mMostRecentLocation);
if (mMostRecentLocation != null) {
values.put(NetMonColumns.DEVICE_LATITUDE, mMostRecentLocation.getLatitude());
values.put(NetMonColumns.DEVICE_LONGITUDE, mMostRecentLocation.getLongitude());
values.put(NetMonColumns.DEVICE_POSITION_ACCURACY, mMostRecentLocation.getAccuracy());
values.put(NetMonColumns.DEVICE_SPEED, mMostRecentLocation.getSpeed());
}
return values;
}
@Override
public void onDestroy() {
Log.v(TAG, "onDestroy");
PreferenceManager.getDefaultSharedPreferences(mContext).unregisterOnSharedPreferenceChangeListener(mPreferenceListener);
if (mLocationClient != null && mLocationClient.isConnected()) {
LocationServices.FusedLocationApi.removeLocationUpdates(mLocationClient, mGmsLocationListener);
mLocationClient.disconnect();
}
}
/**
* Depending on the location fetching strategy, and the application's test interval register a listener to
* receive location updates.
*/
@SuppressWarnings("MissingPermission")
private void registerLocationListener() {
LocationFetchingStrategy locationFetchingStrategy = NetMonPreferences.getInstance(mContext).getLocationFetchingStrategy();
Log.v(TAG, "registerLocationListener: strategy = " + locationFetchingStrategy);
if (!mLocationClient.isConnected()) {
Log.v(TAG, "LocationClient not connected, doing nothing");
return;
}
if (!PermissionUtil.hasLocationPermission(mContext)) {
Log.v(TAG, "LocationClient not connected, doing nothing");
return;
}
LocationServices.FusedLocationApi.removeLocationUpdates(mLocationClient, mGmsLocationListener);
LocationRequest request = new LocationRequest();
if (locationFetchingStrategy == LocationFetchingStrategy.HIGH_ACCURACY_GMS) {
request.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
int pollingInterval = NetMonPreferences.getInstance(mContext).getUpdateInterval();
if (pollingInterval < NetMonPreferences.PREF_MIN_POLLING_INTERVAL) pollingInterval = NetMonPreferences.PREF_MIN_POLLING_INTERVAL;
request.setFastestInterval(pollingInterval);
} else {
request.setPriority(LocationRequest.PRIORITY_LOW_POWER);
request.setNumUpdates(1);
}
LocationServices.FusedLocationApi.requestLocationUpdates(mLocationClient, request, mGmsLocationListener);
}
private final LocationListener mGmsLocationListener = new LocationListener() {
@Override
public void onLocationChanged(Location location) {
Log.v(TAG, "onLocationChanged, location = " + location);
mMostRecentLocation = location;
}
};
private final OnSharedPreferenceChangeListener mPreferenceListener = (sharedPreferences, key) -> {
Log.v(TAG, "onSharedPreferenceChanged: key = " + key);
if (NetMonPreferences.PREF_LOCATION_FETCHING_STRATEGY.equals(key) || NetMonPreferences.PREF_UPDATE_INTERVAL.equals(key)) {
registerLocationListener();
}
};
}