/*******************************************************************************
* Created by Carlos Yaconi
* Copyright 2015 Prey Inc. All rights reserved.
* License: GPLv3
* Full license at "/LICENSE"
******************************************************************************/
package com.prey.services;
import android.app.IntentService;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.location.Location;
import android.util.Log;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.location.FusedLocationProviderApi;
import com.google.android.gms.location.LocationRequest;
import com.google.android.gms.location.LocationServices;
import com.prey.PreyConfig;
import com.prey.PreyLogger;
import java.util.concurrent.TimeUnit;
import static com.google.android.gms.location.LocationServices.FusedLocationApi;
/**
* A utility IntentService, used for a variety of asynchronous background
* operations that do not necessarily need to be tied to a UI.
*/
public class UtilityService extends IntentService {
private static final String ACTION_LOCATION_UPDATED = "location_updated";
private static final String ACTION_REQUEST_LOCATION = "request_location";
/*
* Constants for location update parameters
*/
// Milliseconds per second
public static final int MILLISECONDS_PER_SECOND = 1000;
// The update interval
public static final int UPDATE_INTERVAL_IN_SECONDS = 10;
// A fast interval ceiling
public static final int FAST_CEILING_IN_SECONDS = 1;
// Update interval in milliseconds
public static final long UPDATE_INTERVAL_IN_MILLISECONDS = MILLISECONDS_PER_SECOND * UPDATE_INTERVAL_IN_SECONDS;
// A fast ceiling of update intervals, used when the app is visible
public static final long FAST_INTERVAL_CEILING_IN_MILLISECONDS = MILLISECONDS_PER_SECOND * FAST_CEILING_IN_SECONDS;
private LocationRequest mLocationRequest;
public static IntentFilter getLocationUpdatedIntentFilter() {
return new IntentFilter(UtilityService.ACTION_LOCATION_UPDATED);
}
public static void requestLocation(Context context) {
Intent intent = new Intent(context, UtilityService.class);
intent.setAction(UtilityService.ACTION_REQUEST_LOCATION);
context.startService(intent);
}
public UtilityService() {
super(PreyConfig.TAG);
}
@Override
protected void onHandleIntent(Intent intent) {
String action = intent != null ? intent.getAction() : null;
if (ACTION_REQUEST_LOCATION.equals(action)) {
requestLocationInternal();
} else if (ACTION_LOCATION_UPDATED.equals(action)) {
locationUpdated(intent);
}
}
public static final int GOOGLE_API_CLIENT_TIMEOUT_S = 10; // 10 seconds
public static final String GOOGLE_API_CLIENT_ERROR_MSG =
"Failed to connect to GoogleApiClient (error code = %d)";
/**
* Called when a location update is requested
*/
private void requestLocationInternal() {
PreyLogger.d(ACTION_REQUEST_LOCATION);
GoogleApiClient googleApiClient = new GoogleApiClient.Builder(this)
.addApi(LocationServices.API)
.build();
// It's OK to use blockingConnect() here as we are running in an
// IntentService that executes work on a separate (background) thread.
ConnectionResult connectionResult = googleApiClient.blockingConnect(
GOOGLE_API_CLIENT_TIMEOUT_S, TimeUnit.SECONDS);
if (connectionResult.isSuccess() && googleApiClient.isConnected()) {
Intent locationUpdatedIntent = new Intent(this, UtilityService.class);
locationUpdatedIntent.setAction(ACTION_LOCATION_UPDATED);
// Send last known location out first if available
Location location = FusedLocationApi.getLastLocation(googleApiClient);
if (location != null) {
Intent lastLocationIntent = new Intent(locationUpdatedIntent);
lastLocationIntent.putExtra(
FusedLocationProviderApi.KEY_LOCATION_CHANGED, location);
startService(lastLocationIntent);
}
// Request new location
LocationRequest mLocationRequest = new LocationRequest()
.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);
FusedLocationApi.requestLocationUpdates(
googleApiClient, mLocationRequest,
PendingIntent.getService(this, 0, locationUpdatedIntent, 0));
googleApiClient.disconnect();
} else {
PreyLogger.i(String.format(GOOGLE_API_CLIENT_ERROR_MSG,
connectionResult.getErrorCode()));
}
}
/**
* Called when the location has been updated
*/
private void locationUpdated(Intent intent) {
PreyLogger.d( ACTION_LOCATION_UPDATED);
// Extra new location
Location location =
intent.getParcelableExtra(FusedLocationProviderApi.KEY_LOCATION_CHANGED);
}
public Location getLastLocation() {
return null;
}
}