content: 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);
    }
  
  }
  