package io.homeassistant.android.location; import android.Manifest; import android.app.PendingIntent; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.SharedPreferences; import android.content.pm.PackageManager; import android.location.Location; import android.os.BatteryManager; import android.os.Bundle; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.v4.app.ActivityCompat; import android.text.TextUtils; import android.util.Log; import android.widget.Toast; import com.google.android.gms.common.ConnectionResult; import com.google.android.gms.common.api.GoogleApiClient; import com.google.android.gms.location.LocationRequest; import com.google.android.gms.location.LocationResult; import com.google.android.gms.location.LocationServices; import io.homeassistant.android.Common; import io.homeassistant.android.HassService; import io.homeassistant.android.Utils; import io.homeassistant.android.api.requests.DeviceTrackerRequest; import static io.homeassistant.android.HassService.EXTRA_ACTION_COMMAND; public class LocationUpdateReceiver extends BroadcastReceiver implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener { public static final String ACTION_START_LOCATION = "io.homeassistant.location.start"; public static final String ACTION_LOCATION_UPDATE = "io.homeassistant.location.update"; private static final String TAG = "LocationUpdater"; private SharedPreferences prefs; private GoogleApiClient apiClient; @Override public void onReceive(Context context, Intent intent) { prefs = Utils.getPrefs(context); switch (intent.getAction()) { case Intent.ACTION_BOOT_COMPLETED: case ACTION_START_LOCATION: apiClient = new GoogleApiClient.Builder(context) .addConnectionCallbacks(this) .addOnConnectionFailedListener(this) .addApi(LocationServices.API) .build(); apiClient.connect(); break; case ACTION_LOCATION_UPDATE: if (prefs.getBoolean(Common.PREF_ENABLE_LOCATION_TRACKING, false) && LocationResult.hasResult(intent)) { LocationResult result = LocationResult.extractResult(intent); Location location = result.getLastLocation(); if (location != null) logLocation(location, context); } break; } } @Override public void onConnected(@Nullable Bundle bundle) { if (ActivityCompat.checkSelfPermission(apiClient.getContext(), Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) { if (prefs.getBoolean(Common.PREF_ENABLE_LOCATION_TRACKING, false) && !TextUtils.isEmpty(prefs.getString(Common.PREF_LOCATION_DEVICE_NAME, null))) { LocationRequest locationRequest = new LocationRequest(); locationRequest.setInterval(prefs.getInt(Common.PREF_LOCATION_UPDATE_INTERVAL, 10) * 60 * 1000); locationRequest.setFastestInterval(5 * 60 * 1000); locationRequest.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY); LocationServices.FusedLocationApi.requestLocationUpdates(apiClient, locationRequest, getPendingIntent(apiClient.getContext())); Log.d(TAG, "Started requesting location updates"); } else { LocationServices.FusedLocationApi.removeLocationUpdates(apiClient, getPendingIntent(apiClient.getContext())); Log.d(TAG, "Stopped requesting location updates"); } } apiClient.disconnect(); } @Override public void onConnectionSuspended(int i) { } @Override public void onConnectionFailed(@NonNull ConnectionResult connectionResult) { Toast.makeText(apiClient.getContext(), "Failure: " + connectionResult.getErrorMessage(), Toast.LENGTH_SHORT).show(); } private PendingIntent getPendingIntent(Context context) { Intent intent = new Intent(context, getClass()); intent.setAction(ACTION_LOCATION_UPDATE); return PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT); } private void logLocation(@NonNull Location location, @NonNull Context context) { Log.d(TAG, "Sending location"); String deviceName = Utils.getPrefs(context).getString(Common.PREF_LOCATION_DEVICE_NAME, null); if (TextUtils.isEmpty(deviceName)) { return; } Intent batteryStatus = context.registerReceiver(null, new IntentFilter(Intent.ACTION_BATTERY_CHANGED)); int percentage = 0; if (batteryStatus != null) { int level = batteryStatus.getIntExtra(BatteryManager.EXTRA_LEVEL, 0); int scale = batteryStatus.getIntExtra(BatteryManager.EXTRA_SCALE, 1); percentage = Math.round(level / (float) scale * 100); } Intent serviceIntent = new Intent(context, HassService.class); serviceIntent.putExtra(EXTRA_ACTION_COMMAND, new DeviceTrackerRequest(deviceName, location.getLatitude(), location.getLongitude(), Math.round(location.getAccuracy()), percentage).toString()); context.startService(serviceIntent); } }