package com.alimuzaffar.ramadanalarm.fragments;
import android.Manifest;
import android.app.Activity;
import android.app.Fragment;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.content.IntentSender;
import android.content.pm.PackageManager;
import android.location.Location;
import android.location.LocationManager;
import android.os.Bundle;
import android.util.Log;
import com.alimuzaffar.ramadanalarm.Constants;
import com.alimuzaffar.ramadanalarm.util.PermissionUtil;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.common.api.PendingResult;
import com.google.android.gms.common.api.ResultCallback;
import com.google.android.gms.common.api.Status;
import com.google.android.gms.location.LocationListener;
import com.google.android.gms.location.LocationRequest;
import com.google.android.gms.location.LocationServices;
import com.google.android.gms.location.LocationSettingsRequest;
import com.google.android.gms.location.LocationSettingsResult;
import com.google.android.gms.location.LocationSettingsStatusCodes;
public class LocationHelper extends Fragment implements Constants, GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener {
private static Location sLastLocation;
GoogleApiClient mGoogleApiClient;
LocationRequest mCoarseLocationRequest;
private LocationCallback mCallback;
private Activity mActivity;
private static boolean sLoationPermissionDenied;
public static LocationHelper newInstance() {
return new LocationHelper();
}
public LocationHelper() {
// Required empty public constructor
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true);
}
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
if (activity instanceof LocationCallback) {
mCallback = (LocationCallback) activity;
} else {
throw new IllegalArgumentException("activity must extend BaseActivity and implement LocationHelper.LocationCallback");
}
}
@Override
public void onDetach() {
super.onDetach();
mCallback = null;
mActivity = null;
}
public Location getLocation() {
return sLastLocation;
}
public void checkLocationPermissions() {
if (PermissionUtil.hasSelfPermission(getActivity(), Manifest.permission.ACCESS_FINE_LOCATION)) {
initAppAfterCheckingLocation();
} else {
// UNCOMMENT TO SUPPORT ANDROID M RUNTIME PERMISSIONS
// Intent intent = mActivity.getPackageManager().buildRequestPermissionsIntent(new String[]{Manifest.permission.ACCESS_FINE_LOCATION});
// startActivityForResult(intent, REQUEST_LOCATION);
if (!sLoationPermissionDenied) {
requestPermissions(new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, REQUEST_LOCATION);
}
}
}
private void initAppAfterCheckingLocation() {
if (mGoogleApiClient == null) {
buildGoogleApiClient();
} else if (sLastLocation == null) {
if (mGoogleApiClient.isConnected()) {
// check for a location.
checkIfLocationServicesEnabled();
} //else if (mGoogleApiClient.isConnecting()) {
//do nothing
//}
} else {
Log.d("SalaatTimesActivity", sLastLocation.getLatitude() + "," + sLastLocation.getLongitude());
if (mCallback != null) {
mCallback.onLocationChanged(sLastLocation);
}
}
}
private synchronized void buildGoogleApiClient() {
mGoogleApiClient = new GoogleApiClient.Builder(getActivity())
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
mGoogleApiClient.connect();
}
private void checkLocationAndInit() {
if (sLastLocation == null) {
sLastLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
}
if (sLastLocation == null) {
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, createLocationRequest(), new LocationListener() {
@Override
public void onLocationChanged(Location location) {
sLastLocation = location;
if (mCallback != null) {
mCallback.onLocationChanged(sLastLocation);
}
initAppAfterCheckingLocation();
LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this);
}
});
} else {
initAppAfterCheckingLocation();
}
}
private LocationRequest createLocationRequest() {
if (mCoarseLocationRequest == null) {
mCoarseLocationRequest = new LocationRequest();
mCoarseLocationRequest.setInterval(5000);
mCoarseLocationRequest.setFastestInterval(1000);
mCoarseLocationRequest.setNumUpdates(1);
mCoarseLocationRequest.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);
}
return mCoarseLocationRequest;
}
private void checkIfLocationServicesEnabled() {
LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder()
.addLocationRequest(createLocationRequest());
PendingResult<LocationSettingsResult> result =
LocationServices.SettingsApi.checkLocationSettings(mGoogleApiClient, builder.build());
result.setResultCallback(new ResultCallback<LocationSettingsResult>() {
@Override
public void onResult(LocationSettingsResult result) {
final Status status = result.getStatus();
switch (status.getStatusCode()) {
case LocationSettingsStatusCodes.SUCCESS:
// All location settings are satisfied. The client can initialize location
// requests here.
checkLocationAndInit();
break;
case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:
// Location settings are not satisfied. But could be fixed by showing the user
// a dialog.
try {
// Show the dialog by calling startResolutionForResult(),
// and check the result in onActivityResult().
status.startResolutionForResult(getActivity(), REQUEST_CHECK_SETTINGS);
} catch (IntentSender.SendIntentException e) {
// Ignore the error.
}
break;
case LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE:
// Location settings are not satisfied. However, we have no way to fix the
// settings so we won't show the dialog.
break;
}
}
});
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
//final LocationSettingsStates states = LocationSettingsStates.fromIntent(data);
switch (requestCode) {
case REQUEST_CHECK_SETTINGS:
switch (resultCode) {
case Activity.RESULT_OK:
// All required changes were successfully made
checkLocationAndInit();
break;
case Activity.RESULT_CANCELED:
// The user was asked to change settings, but chose not to
if (mCallback != null) {
mCallback.onLocationSettingsFailed();
}
break;
default:
if (mCallback != null) {
mCallback.onLocationSettingsFailed();
}
break;
}
break;
}
}
@Override
public void onConnected(Bundle bundle) {
checkIfLocationServicesEnabled();
}
@Override
public void onConnectionSuspended(int i) {
}
@Override
public void onConnectionFailed(ConnectionResult connectionResult) {
}
public void setLoationPermissionDenied(boolean mLoationPermissionDenied) {
this.sLoationPermissionDenied = mLoationPermissionDenied;
}
public static boolean isLoationPermissionDenied() {
return sLoationPermissionDenied;
}
/**
* Callback received when a permissions request has been completed.
*/
//@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions,
int[] grantResults) {
if (requestCode == REQUEST_LOCATION) {
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
checkLocationPermissions();
} else {
Log.i("BaseActivity", "LOCATION permission was NOT granted.");
setLoationPermissionDenied(true);
}
} else {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
}
// NOT SURE WHERE THIS CODE GOES, BUT ITS NEEDED SO THAT WE CAN BE NOTIFIED
// OF SEVERE LOCATION CHANGES BY THE USER, SO THAT WE CAN RE-CALCULATE THE
// SALAAT TIMES AND UPDATE THE ALARMS.
// ALSO HAVE TO HANDLE CANCELING OF UPDATES IF THE USER REVOKES PERMISSION
// THROUGH SETTINGS
// IMPORTANT: THIS SHOULD NEEDS TO BE SET AGAIN IN THE BOOT RECEIVER.
/*
Intent passiveIntent = new Intent(context, PassiveLocationChangedReceiver.class);
PendingIntent locationListenerPassivePendingIntent = PendingIntent.getActivity(getActivity(), 0, passiveIntent, PendingIntent.FLAG_UPDATE_CURRENT);
locationUpdateRequester.requestPassiveLocationUpdates(getActivity(), locationListenerPassivePendingIntent);
*/
public void requestPassiveLocationUpdates(Context context, PendingIntent pendingIntent) {
long oneHourInMillis = 3600000;
float fiftyKinMeters = 50000.0f;
LocationManager locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
try {
locationManager.requestLocationUpdates(LocationManager.PASSIVE_PROVIDER,
oneHourInMillis, fiftyKinMeters, pendingIntent);
} catch (SecurityException se) {
//do nothing. We should always have permision in order to reach this screen.
}
}
public void removePassiveLocationUpdates(Context context, PendingIntent pendingIntent) {
LocationManager locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
try {
locationManager.removeUpdates(pendingIntent);
} catch (SecurityException se) {
//do nothing. We should always have permision in order to reach this screen.
}
}
public interface LocationCallback {
void onLocationSettingsFailed();
void onLocationChanged(Location location);
}
}