Last active
February 21, 2019 17:31
-
-
Save techartist/75cc72aa2a6cd202f60dc4cc9a07c759 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.activehours.ui.fragments.funnel; | |
import android.Manifest; | |
import android.annotation.SuppressLint; | |
import android.app.Activity; | |
import android.content.Context; | |
import android.content.DialogInterface; | |
import android.content.Intent; | |
import android.location.Geocoder; | |
import android.location.Location; | |
import android.location.LocationManager; | |
import android.net.Uri; | |
import android.os.Bundle; | |
import android.os.Handler; | |
import android.os.ResultReceiver; | |
import android.provider.Settings; | |
import android.view.LayoutInflater; | |
import android.view.Menu; | |
import android.view.MenuItem; | |
import android.view.View; | |
import android.view.ViewGroup; | |
import android.widget.Button; | |
import android.widget.Toast; | |
import com.activehours.BuildConfig; | |
import com.activehours.R; | |
import com.activehours.models.viewmodel.EnterWorkAddressViewModel; | |
import com.activehours.tracking.AHTracking; | |
import com.activehours.ui.fragments.FragBaseV2; | |
import com.activehours.ui.fragments.FragEnterWorkAddress_ResultResponder; | |
import com.activehours.ui.widgets.AHSupportMapFragment; | |
import com.activehours.util.AHDebouncedOnClickListener; | |
import com.activehours.util.AHDrawable; | |
import com.activehours.util.AHGeoFenceManager; | |
import com.activehours.util.AHGoogleUtils; | |
import com.activehours.util.AHLocation; | |
import com.activehours.util.AHLocationManager; | |
import com.activehours.util.AHRuntimePermissionUtil; | |
import com.activehours.util.AHStatusBarUtil; | |
import com.activehours.util.AHStringUtils; | |
import com.activehours.util.AHVolleyErrorResponseHandlerUtil; | |
import com.activehours.util.FetchAddressIntentService; | |
import com.activehours.util.clientState.ClientStateTracker; | |
import com.ahplatform.swagger.model.AnalyticsEvent; | |
import com.ahplatform.swagger.model.InstantEarnings; | |
import com.ahplatform.swagger.model.LatLongData; | |
import com.ahplatform.swagger.model.LocationData; | |
import com.android.volley.VolleyError; | |
import com.google.android.gms.common.ConnectionResult; | |
import com.google.android.gms.common.api.Status; | |
import com.google.android.gms.maps.CameraUpdateFactory; | |
import com.google.android.gms.maps.GoogleMap; | |
import com.google.android.gms.maps.OnMapReadyCallback; | |
import com.google.android.gms.maps.model.CameraPosition; | |
import com.google.android.gms.maps.model.LatLng; | |
import com.google.android.libraries.places.api.Places; | |
import com.google.android.libraries.places.api.model.Place; | |
import com.google.android.libraries.places.api.net.PlacesClient; | |
import com.google.android.libraries.places.widget.AutocompleteSupportFragment; | |
import com.google.android.libraries.places.widget.listener.PlaceSelectionListener; | |
import java.math.BigDecimal; | |
import java.net.HttpURLConnection; | |
import java.util.ArrayList; | |
import java.util.List; | |
import androidx.annotation.Nullable; | |
import androidx.appcompat.app.AlertDialog; | |
import androidx.fragment.app.FragmentManager; | |
import androidx.fragment.app.FragmentTransaction; | |
import permissions.dispatcher.NeedsPermission; | |
import permissions.dispatcher.OnNeverAskAgain; | |
import permissions.dispatcher.OnPermissionDenied; | |
import permissions.dispatcher.OnShowRationale; | |
import permissions.dispatcher.PermissionRequest; | |
import permissions.dispatcher.RuntimePermissions; | |
import timber.log.Timber; | |
/** | |
* Created by dominic on 5/16/16. | |
*/ | |
@RuntimePermissions | |
public class FragEnterWorkAddress | |
extends FragBaseV2 | |
implements | |
// Google Maps Library callback | |
OnMapReadyCallback, | |
FragEnterWorkAddress_ResultResponder | |
{ | |
private EnterWorkAddressViewModel viewModel; | |
private Place mPlace; | |
private Button okButton; | |
private Location lastKnownLocation; | |
private GoogleMap mMap; | |
private boolean mMapReady = false; | |
private boolean needCenteredOnCurrentLocation = true; | |
private AHSupportMapFragment mMapFragment; | |
private boolean mMapBeingMovedByUser = false; | |
private boolean mEnableGeocoder = false; | |
private String mAddressToCommunicate = null; | |
private static final int REQUEST_CODE_FRAGMENT_TO_DEVICE_SETTINGS = 7; | |
private static final int REQUEST_CODE_FRAGMENT_TO_APP_SETTINGS = 11; | |
private Context context; | |
final Handler handler = new Handler(); | |
AutocompleteSupportFragment mAutocompleteFragment; | |
boolean allowButtonTapHandling = true; | |
public interface ActionListener { | |
void onFragEnterWorkAddress_onUserHasSelectedAnAddress( | |
InstantEarnings ieData, | |
FragEnterWorkAddress_ResultResponder callback // Called when the user selects an address | |
); | |
} | |
private ActionListener actionListener; | |
public static final String TAG = FragEnterWorkAddress.class.getSimpleName(); | |
public static FragEnterWorkAddress newInstance(EnterWorkAddressViewModel viewModel) { | |
final FragEnterWorkAddress fragment = new FragEnterWorkAddress(); | |
Bundle bundle = new Bundle(); | |
bundle.putParcelable(KEY_VIEW_MODEL, viewModel); | |
fragment.setArguments(bundle); | |
return fragment; | |
} | |
@Override | |
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { | |
View rootView = inflater.inflate( | |
// fragment to inflate | |
R.layout.frag_enter_work_address, | |
// container to inflate into | |
container, | |
// always false | |
false | |
); | |
allowButtonTapHandling = true; | |
okButton = rootView.findViewById(R.id.button_ok); | |
okButton.setText(viewModel.getButtonTextOnEntry()); | |
okButton.setOnClickListener(mainButtonClickListener); | |
okButton.setEnabled(false); | |
return rootView; | |
} | |
private AHDebouncedOnClickListener mainButtonClickListener = new AHDebouncedOnClickListener(1000) { | |
@Override | |
public void onDebouncedClick(View v) { | |
AHTracking.logEvent(AnalyticsEvent.INPUT_UPDATEWORKLOCATION_MAINBUTTON_PRESSED); | |
if (allowButtonTapHandling) { | |
userHasSelectedAnAddress(mAddressToCommunicate); | |
} | |
} | |
}; | |
@Override | |
public void onCreate(Bundle savedInstanceState) { | |
super.onCreate(savedInstanceState); | |
Bundle args = getArguments(); | |
this.viewModel = args.getParcelable(KEY_VIEW_MODEL); | |
// check Location access, and then if allowed, connect GoogleApiClient | |
FragEnterWorkAddressPermissionsDispatcher.accessLocationWithPermissionCheck(this); | |
// Initialize Places. | |
Places.initialize(getActivity().getApplicationContext(), BuildConfig.GEO_PLACES_ID); | |
// Create a new Places client instance. | |
PlacesClient placesClient = Places.createClient(getContext()); | |
} | |
@Override | |
public void onPrepareOptionsMenu(Menu menu) { | |
showMenuItem(false, menu, R.id.menu_signup_cs); | |
showMenuItem(true, menu, R.id.menu_current_location); | |
} | |
@Override | |
public boolean onOptionsItemSelected(MenuItem item) { | |
switch (item.getItemId()) { | |
case R.id.menu_current_location: | |
centerMapOnCurrentLocation(); | |
// Fetch the address for our current location and | |
// place that into the search bar | |
// | |
geocodeCurrentLocation(); | |
return true; | |
default: | |
return super.onOptionsItemSelected(item); | |
} | |
} | |
@Override | |
public void onAttach(Context context) { | |
super.onAttach(context); | |
this.context = context; | |
} | |
@Override | |
public void onDetach() { | |
super.onDetach(); | |
this.context = null; | |
} | |
@Override | |
public void onResume() { | |
super.onResume(); | |
setupActionBar(getResources().getString(R.string.work_location), true); | |
AHStatusBarUtil.changeStatusBarColor(getActivity(), R.color.heather); | |
setActionBarTitleForV2Settings(getResources().getString(R.string.work_location)); | |
setHasOptionsMenu(true); | |
AHTracking.logEvent(AnalyticsEvent.VIEW_UPDATEWORKLOCATION_DISPLAYED); | |
} | |
private void continueOnResume(){ | |
if(getActivity() == null) { | |
return; | |
} | |
if(AHLocation.isDeviceLocationPermissionAllowed(getActivity())) { | |
AHLocation.getLastKnowLocation( | |
getActivity(), | |
new AHLocation.LastKnownLocationCallback() { | |
@Override | |
public void onLastKnownLocationAvailable(Location location) { | |
lastKnownLocation = location; | |
if(getContext() != null) { | |
List<Location> locations = new ArrayList<>(); // send the current device location right away: | |
locations.add(location); | |
ClientStateTracker clientStateTracker = new ClientStateTracker(); | |
clientStateTracker.sendImmediatePayload(getContext(), location); | |
} | |
// | |
// Good, we have a location. Finally. Wow Google, what a round about | |
// way to look for location - good job making what used to be a simple | |
// task so abstruse. | |
// | |
// So, now, if we have a location, have a map, and still need to center | |
// on our current location ... do so. | |
// | |
if (lastKnownLocation != null && needCenteredOnCurrentLocation && mMapReady) { | |
needCenteredOnCurrentLocation = false; | |
centerOnLastKnownLocation(); | |
} | |
mEnableGeocoder = Geocoder.isPresent(); | |
} | |
} | |
); | |
// Also start listening for location updates: | |
AHLocationManager.beginListeningForLocation(new AHGeoFenceManager.DataProvider() { | |
@Override | |
public Context onContextNeeded() { | |
return getContext(); | |
} | |
}); | |
return; | |
} | |
new AlertDialog.Builder(getActivity()) | |
.setIcon(AHDrawable.getAlertDialogIcon()) | |
.setTitle(AHRuntimePermissionUtil.getDeviceLocationServicesTitleString()) | |
.setMessage(AHRuntimePermissionUtil.getDeviceLocationServicesContentString()) | |
.setPositiveButton( | |
getResources().getString(R.string.edit), | |
new DialogInterface.OnClickListener() { | |
@Override | |
public void onClick(DialogInterface dialog, int which) { | |
if (dialog != null) { | |
Timber.d( "POSITIVE BUTTON PRESSED"); | |
dialog.dismiss(); | |
// go to Location Device Settings Page | |
final Intent intent = new Intent( | |
Settings.ACTION_LOCATION_SOURCE_SETTINGS | |
); | |
//startActivity(intent); | |
// do not call getActivity().startActivityForResult so that Fragment handles the Result | |
startActivityForResult( | |
intent, | |
REQUEST_CODE_FRAGMENT_TO_DEVICE_SETTINGS | |
); | |
} | |
} | |
} | |
) | |
.setNegativeButton( | |
getResources().getString(R.string.not_now), | |
new DialogInterface.OnClickListener() { | |
@Override | |
public void onClick(DialogInterface dialog, int which) { | |
if (dialog != null) { | |
Timber.d( "NEGATIVE BUTTON PRESSED"); | |
dialog.dismiss(); | |
backWithDelay(); | |
} | |
} | |
} | |
) | |
.setOnCancelListener(new DialogInterface.OnCancelListener() { | |
@Override | |
public void onCancel(DialogInterface dialog) { | |
backWithDelay(); | |
} | |
}) | |
.setCancelable(true) // dismiss on back | |
.show(); | |
} | |
@Override | |
public void onSaveInstanceState(Bundle outState) { | |
super.onSaveInstanceState(outState); | |
} | |
@Override | |
public void onActivityCreated(Bundle savedInstanceState) { | |
super.onActivityCreated(savedInstanceState); | |
actionListener = (ActionListener) getActivity(); | |
} | |
private boolean checkPlayServices(Activity activity) { | |
if (activity == null) { | |
return false; // If we can't check, don't init the map. | |
} | |
int resultCode = AHGoogleUtils.checkGooglePlayServicesAvailable(activity); | |
if (resultCode != ConnectionResult.SUCCESS) { | |
if (!AHGoogleUtils.showErrorDialogIfUserResolvable(activity, resultCode)) { // Should not happen. This device does not support Play Services. // Let's show an ultimate warning. | |
Toast.makeText( | |
activity, | |
getResources().getString(R.string.google_play_not_enabled), | |
Toast.LENGTH_LONG | |
).show(); | |
} | |
return false; | |
} | |
return true; | |
} | |
@Override | |
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { | |
super.onViewCreated(view, savedInstanceState); | |
Activity activity = getActivity(); | |
if (activity == null) { // No Activity in a ui lifecycle event handler? (?) | |
return; // Don't setup the map or address search. | |
} | |
// Check the childFragmentManager to see if these fragments already exist (in the case this activity was recreated). If not, create them. | |
mAutocompleteFragment = (AutocompleteSupportFragment) getChildFragmentManager().findFragmentByTag(AutocompleteSupportFragment.class.getSimpleName()); | |
mMapFragment = (AHSupportMapFragment) getChildFragmentManager().findFragmentByTag(AHSupportMapFragment.class.getSimpleName()); | |
FragmentManager supportFragmentManager = getChildFragmentManager(); | |
FragmentTransaction ft = supportFragmentManager.beginTransaction(); | |
if(mAutocompleteFragment == null) { | |
mAutocompleteFragment = new AutocompleteSupportFragment(); | |
ft.add(R.id.places_container, mAutocompleteFragment, AutocompleteSupportFragment.class.getSimpleName()); | |
} | |
// Let's setup the map only if this device has an up to date Google Play Services. | |
if (mMapFragment == null && checkPlayServices(activity)) { | |
mMapFragment = new AHSupportMapFragment(); | |
ft.add(R.id.map_container, mMapFragment, AHSupportMapFragment.class.getSimpleName()); | |
} | |
ft.commit(); | |
// Setup map if we created a map fragment: | |
if (mMapFragment != null) { | |
mMapFragment.getMapAsync(this); | |
} | |
// Now, configure those fragments | |
// | |
mAutocompleteFragment.setOnPlaceSelectedListener(new PlaceSelectionListener() { | |
@Override | |
public void onPlaceSelected(Place place) { | |
mPlace = place; | |
if (mPlace != null && mPlace.getAddress() != null && mPlace.getLatLng() != null) { | |
Timber.d( "Place: %s",place.getName()); | |
mAddressToCommunicate = mPlace.getAddress().toString(); | |
// The user just selected an address from the Places search box? | |
// Update the last known location. | |
LatLng chosenAddresLatLng = mPlace.getLatLng(); | |
Location temp = new Location(LocationManager.GPS_PROVIDER); | |
temp.setLatitude(chosenAddresLatLng.latitude); | |
temp.setLongitude(chosenAddresLatLng.longitude); | |
lastKnownLocation = temp; | |
okButton.setEnabled(true); | |
okButton.setText(viewModel.getButtonTextAfterChange()); | |
moveMapTo(mPlace.getLatLng().latitude, mPlace.getLatLng().longitude); | |
} | |
} | |
@Override | |
public void onError(Status status) { | |
// TODO: Handle the error. | |
Timber.e( "An error occurred: %s", status); | |
} | |
}); | |
} | |
@Override | |
public void onMapReady(GoogleMap googleMap) { | |
mMap = googleMap; | |
mMap.moveCamera(CameraUpdateFactory.zoomTo(16)); | |
mMapReady = true; | |
if (lastKnownLocation != null) { | |
centerOnLastKnownLocation(); // Center the map | |
needCenteredOnCurrentLocation = false; | |
// Take the current location, convert it into an address, and place | |
// that address into the search bar. | |
geocodeCurrentLocation(); | |
} else { | |
needCenteredOnCurrentLocation = true; | |
} | |
mMap.setOnCameraMoveStartedListener(new GoogleMap.OnCameraMoveStartedListener() { | |
@Override | |
public void onCameraMoveStarted(int reasonID) { | |
if (reasonID == REASON_API_ANIMATION || reasonID == REASON_GESTURE) { | |
mMapBeingMovedByUser = true; | |
} | |
} | |
}); | |
mMap.setOnCameraIdleListener(new GoogleMap.OnCameraIdleListener() { | |
@Override | |
public void onCameraIdle() { | |
// Map settled | |
Timber.d( "onCameraIdle"); | |
if (!isValidState || getActivity() == null) { | |
return; | |
} | |
geocodeCurrentLocation(); | |
mMapBeingMovedByUser = false; | |
} | |
}); | |
} | |
private void geocodeCurrentLocation() { | |
if (mEnableGeocoder && mMap != null) { | |
CameraPosition position = mMap.getCameraPosition(); | |
if (position != null) { | |
LatLng latlng = position.target; | |
if (latlng != null) { | |
Timber.d("Lat/Lon: %s", latlng.toString()); | |
Location temp = new Location(LocationManager.GPS_PROVIDER); | |
temp.setLatitude(latlng.latitude); | |
temp.setLongitude(latlng.longitude); | |
lastKnownLocation = temp; // Update the lat/lon we might send the service | |
mAddressSearchLocation = temp; // Update the lat/lon we'll use to search for an address | |
// Now, start a service which will geocode the location | |
// into an address | |
startIntentService(); | |
} | |
else { | |
Timber.e("No position.target found"); | |
} | |
} else { | |
Timber.e("No position found"); | |
} | |
} | |
} | |
private void centerMapOnCurrentLocation() { | |
AHLocation.getLastKnowLocation( | |
getActivity(), | |
new AHLocation.LastKnownLocationCallback() { | |
@Override | |
public void onLastKnownLocationAvailable(Location location) { | |
lastKnownLocation = location; | |
if (lastKnownLocation != null) { | |
centerOnLastKnownLocation(); | |
} | |
} | |
} | |
); | |
} | |
@SuppressLint("ParcelCreator") | |
class AddressResultReceiver extends ResultReceiver { | |
public AddressResultReceiver(Handler handler) { | |
super(handler); | |
} | |
@Override | |
protected void onReceiveResult(int resultCode, Bundle resultData) { | |
Timber.d( "onReceiveResult - from geocode"); | |
if(!FragEnterWorkAddress.this.isValidState || FragEnterWorkAddress.this.isRemoving()) { // We're in the process of being cleaned up so just abort here: | |
return; | |
} | |
String localAddressOutput = ""; | |
if(resultData != null) { | |
localAddressOutput = resultData.getString(FetchAddressIntentService.Constants.RESULT_DATA_KEY); | |
} | |
// Show a toast message if an address was found. | |
if (resultCode == FetchAddressIntentService.Constants.SUCCESS_RESULT && localAddressOutput != null) { | |
Timber.d("Address found: %s" , localAddressOutput); | |
// If Success_Result AND resultData is null this will cause us to | |
// clear the search box. Which I think is ok. Otherwise it will cause | |
// the address to appear. | |
displayAddressOutput(localAddressOutput); | |
// If the user clicks 'save' then we'll send this address to | |
// our service | |
// | |
mAddressToCommunicate = localAddressOutput; | |
okButton.setEnabled(true); | |
okButton.setText(viewModel.getButtonTextAfterChange()); | |
} else { | |
Timber.d( "Address NOT found: %s", localAddressOutput); | |
displayAddressOutput(getResources().getString(R.string.couldnt_find_address_here)); | |
mAddressToCommunicate = ""; | |
} | |
} | |
} | |
private void displayAddressOutput(String message){ | |
if(mAutocompleteFragment != null){ | |
mAutocompleteFragment.setText(message); | |
} | |
} | |
private Location mAddressSearchLocation; | |
private AddressResultReceiver mResultReceiver; | |
private void startIntentService() { | |
Activity a = getActivity(); | |
mResultReceiver = new AddressResultReceiver(handler); // Added by dom. | |
if (a != null) { | |
Intent intent = new Intent(a, FetchAddressIntentService.class); | |
intent.putExtra(FetchAddressIntentService.Constants.RECEIVER, mResultReceiver); | |
intent.putExtra(FetchAddressIntentService.Constants.LOCATION_DATA_EXTRA, mAddressSearchLocation); | |
a.startService(intent); | |
} else { | |
Intent intent = new Intent(context, FetchAddressIntentService.class); | |
intent.putExtra(FetchAddressIntentService.Constants.RECEIVER, mResultReceiver); | |
intent.putExtra(FetchAddressIntentService.Constants.LOCATION_DATA_EXTRA, mAddressSearchLocation); | |
context.startService(intent); | |
} | |
} | |
private void centerOnLastKnownLocation() { | |
double latitude = lastKnownLocation.getLatitude(); | |
double longitude = lastKnownLocation.getLongitude(); | |
// 405(ish) Waverley Street, Palo Alto | |
// | |
//double latitude = 37.448022300000005; | |
//double longitude = -122.1613089; | |
if (latitude != 0.0 && longitude != 0.0) { | |
okButton.setText(viewModel.getButtonTextOnEntry()); | |
okButton.setEnabled(true); | |
moveMapTo(latitude, longitude); | |
} | |
} | |
private void moveMapTo(double lat, double lon) { | |
if(mMap != null) { | |
LatLng newLocation = new LatLng(lat, lon); | |
mMap.clear(); | |
//mMap.addMarker(new MarkerOptions().position(newLocation).title("Current Location")); | |
mMap.moveCamera(CameraUpdateFactory.newLatLng(newLocation)); | |
} | |
} | |
@Override | |
public void onActivityResult(int requestCode, int resultCode, Intent data) { | |
super.onActivityResult(requestCode, resultCode, data); | |
Timber.d( "on activity result"); | |
if(requestCode == REQUEST_CODE_FRAGMENT_TO_APP_SETTINGS || requestCode == REQUEST_CODE_FRAGMENT_TO_DEVICE_SETTINGS){ | |
if (AHLocation.isAppLocationPermissionAllowed(getActivity())) { | |
// app level location permission GRANTED | |
continueOnResume(); | |
} else { | |
// app level location permission NOT GRANTED | |
backWithDelay(); | |
} | |
} | |
} | |
private void userHasSelectedAnAddress(String address) { | |
List<LocationData> locations = new ArrayList<>(); | |
LocationData d = new LocationData(); | |
if (address != null) { | |
// Let's remove a common problem. | |
// The service chokes on addresses like this: | |
// "123-456 something stree, Palo alto 94002" | |
// | |
// Unfortunately, that's a common pattern for google's address finder to give us. | |
// | |
// Here's an algo which detects this pattern and strips away the first number and dash | |
// | |
address = AHStringUtils.trimDashedAddresses(address); | |
d.setFormattedAddress(address); | |
} | |
if (lastKnownLocation != null) { | |
double latitude = lastKnownLocation.getLatitude(); | |
double longitude = lastKnownLocation.getLongitude(); | |
LatLongData latLongData = new LatLongData(); | |
latLongData.setLatitude(new BigDecimal(latitude)); | |
latLongData.setLongitude((new BigDecimal(longitude))); | |
d.setLatLong(latLongData); | |
} | |
locations.add(d); | |
InstantEarnings ie = new InstantEarnings(); | |
ie.setEnabled(true); | |
ie.setWorkLocations(locations); | |
if (viewModel.getDisableMainButtonAfterPress()) { | |
allowButtonTapHandling = false; | |
} | |
actionListener.onFragEnterWorkAddress_onUserHasSelectedAnAddress(ie, this); | |
} | |
@Override | |
public void onRequestPermissionsResult( | |
int requestCode, | |
String permissions[], | |
int[] grantResults | |
) { | |
super.onRequestPermissionsResult(requestCode, permissions, grantResults); | |
// handling done in library class | |
FragEnterWorkAddressPermissionsDispatcher.onRequestPermissionsResult( | |
this, | |
requestCode, | |
grantResults | |
); | |
} | |
@NeedsPermission(Manifest.permission.ACCESS_FINE_LOCATION) | |
void accessLocation() { | |
continueOnResume(); | |
} | |
@OnShowRationale(Manifest.permission.ACCESS_FINE_LOCATION) | |
void showRationaleForLocation( | |
final PermissionRequest request | |
) { | |
AHRuntimePermissionUtil.onShowRationale( | |
getActivity(), | |
AHRuntimePermissionUtil.RuntimePermissionEnum.Location, | |
request | |
); | |
} | |
@OnPermissionDenied(Manifest.permission.ACCESS_FINE_LOCATION) | |
void showDeniedForLocation() { | |
AHRuntimePermissionUtil.onShowDenied( | |
getActivity(), | |
AHRuntimePermissionUtil.RuntimePermissionEnum.Location | |
); | |
// | |
// | |
backWithDelay(); | |
} | |
@OnNeverAskAgain(Manifest.permission.ACCESS_FINE_LOCATION) | |
void showNeverAskForLocation() { | |
// cannot use generic method above because the negative case needs to call backWithDelay(); | |
final Activity activity = getActivity(); | |
if(activity != null) { | |
AlertDialog alertDialog; | |
alertDialog = new AlertDialog.Builder(getActivity()).create(); | |
alertDialog.setIcon(AHDrawable.getAlertDialogIcon()); | |
alertDialog.setTitle(getResources().getString(R.string.permission_needed)); | |
alertDialog.setMessage(getResources().getString(R.string.enable_location_permissions)); | |
alertDialog.setCancelable(true); | |
alertDialog.setButton( | |
DialogInterface.BUTTON_POSITIVE, | |
getResources().getString(R.string.not_now), | |
new DialogInterface.OnClickListener() { | |
@Override | |
public void onClick(DialogInterface dialog, int which) { | |
if (dialog != null && getActivity() != null) { | |
Timber.d( "POSITIVE BUTTON PRESSED"); | |
// go to App's Settings Page to toggle permission | |
final Intent i = new Intent(); | |
i.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS); | |
i.addCategory(Intent.CATEGORY_DEFAULT); | |
i.setData(Uri.parse("package:" + activity.getPackageName())); | |
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); | |
i.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY); | |
i.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS); | |
Timber.d( "APP SETTINGS"); | |
// do not call getActivity().startActivityForResult so that Fragment handles the Result | |
startActivityForResult( | |
i, | |
REQUEST_CODE_FRAGMENT_TO_APP_SETTINGS | |
); | |
} | |
} | |
} | |
); | |
alertDialog.setButton( | |
DialogInterface.BUTTON_NEGATIVE, | |
getResources().getString(R.string.not_now), | |
new DialogInterface.OnClickListener() { | |
@Override | |
public void onClick(DialogInterface dialog, int which) { | |
if(dialog != null){ | |
Timber.d("NEGATIVE BUTTON PRESSED"); | |
dialog.dismiss(); | |
backWithDelay(); | |
} | |
} | |
} | |
); | |
alertDialog.setOnCancelListener(new DialogInterface.OnCancelListener() { | |
@Override | |
public void onCancel(DialogInterface dialog) { | |
if(dialog != null){ | |
backWithDelay(); | |
} | |
} | |
}); | |
alertDialog.show(); | |
} | |
} | |
private void backWithDelay(){ | |
Handler handler = new Handler(); | |
handler.postDelayed( | |
new Runnable() { | |
public void run() { | |
if(getActivity() != null) { | |
getActivity().onBackPressed(); | |
} | |
} | |
}, | |
// delay in MS so that isValidState becomes TRUE | |
150 | |
); | |
} | |
// The settings controller calls this to let us know that | |
// we can allow the user to tap the button again. | |
// | |
@Override | |
public void onFragEnterWorkAddress_reEnableButtons() { | |
allowButtonTapHandling = true; | |
} | |
@Override | |
public void onFragEnterWorkAddress_failed(VolleyError error) { | |
Activity a = getActivity(); | |
allowButtonTapHandling = true; | |
if (isValidState && a != null) { | |
dismissSupportLoadingFragment(); | |
// We handle 'bad request' ourselves. But all other errors should | |
// go to the error response handler (takes care of generic 500's, auth failures etc) | |
// | |
boolean isErrorNull = (error == null); | |
boolean isBadRequest = error != null && error.networkResponse != null && error.networkResponse.statusCode == HttpURLConnection.HTTP_BAD_REQUEST; | |
if (isErrorNull || isBadRequest) { | |
String message = getResources().getString(R.string.not_a_valid_work_address); | |
Toast.makeText(a, message, Toast.LENGTH_LONG).show(); | |
} else { | |
AHVolleyErrorResponseHandlerUtil.onErrorResponse( | |
a, // a null activity is ok for onErrorResponse | |
error | |
); | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment