package com.jdroid.android.google.maps;
import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v7.widget.Toolbar;
import android.util.SparseArray;
import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.GoogleMap.InfoWindowAdapter;
import com.google.android.gms.maps.GoogleMapOptions;
import com.google.android.gms.maps.OnMapReadyCallback;
import com.google.android.gms.maps.SupportMapFragment;
import com.jdroid.android.activity.ActivityIf;
import com.jdroid.android.application.AbstractApplication;
import com.jdroid.android.application.AppModule;
import com.jdroid.android.exception.ErrorDisplayer;
import com.jdroid.android.fragment.FragmentDelegate;
import com.jdroid.android.fragment.FragmentHelper;
import com.jdroid.android.fragment.FragmentHelper.UseCaseTrigger;
import com.jdroid.android.fragment.FragmentIf;
import com.jdroid.android.google.GooglePlayServicesUtils;
import com.jdroid.android.loading.FragmentLoading;
import com.jdroid.android.permission.PermissionHelper;
import com.jdroid.android.snackbar.SnackbarBuilder;
import com.jdroid.android.usecase.AbstractUseCase;
import com.jdroid.android.usecase.listener.UseCaseListener;
import com.jdroid.java.exception.AbstractException;
public abstract class AbstractMapFragment extends SupportMapFragment implements FragmentIf {
private FragmentHelper fragmentHelper;
private GoogleMap map;
private ViewGroup mapContainer;
private View updateGoogleplayServicesContainer;
private Boolean snackbarDisplayed = false;
private PermissionHelper locationPermissionHelper;
protected FragmentIf getFragmentIf() {
return (FragmentIf)this.getActivity();
}
/**
Calling this before super.oncreate() when you try to use a toolbar and the view contains a map
https://code.google.com/p/android/issues/detail?id=175140
*/
public static void doMapToolbarWorkaround(Bundle savedInstanceState){
// FIXME This is just a workaround to the following error: ClassNotFoundException when unmarshalling android.support.v7.widget.Toolbar$SavedState
// It seems to be a problem with the SupportMapFragment implementation
// https://code.google.com/p/android/issues/detail?id=175140
if (savedInstanceState != null) {
SparseArray sparseArray = (SparseArray)savedInstanceState.get("android:view_state");
if (sparseArray != null) {
Integer keyToRemove = null;
for (int i = 0; i < sparseArray.size(); i++) {
int key = sparseArray.keyAt(i);
// get the object by the key.
Object each = sparseArray.get(key);
if (each.toString().startsWith("android.support.v7.widget.Toolbar$SavedState")) {
keyToRemove = key;
}
}
if (keyToRemove != null) {
sparseArray.remove(keyToRemove);
}
}
}
}
public static void setGoogleMapOptions(Bundle bundle, GoogleMapOptions googleMapOptions) {
bundle.putParcelable("MapOptions", googleMapOptions);
}
@Override
public void onCreate(Bundle savedInstanceState) {
doMapToolbarWorkaround(savedInstanceState);
super.onCreate(savedInstanceState);
fragmentHelper = AbstractApplication.get().createFragmentHelper(this);
fragmentHelper.onCreate(savedInstanceState);
if (savedInstanceState == null) {
setRetainInstance(true);
}
if (isLocationEnabled()) {
locationPermissionHelper = PermissionHelper.createLocationPermissionHelper(this);
locationPermissionHelper.setAppInfoDialogMessageResId(R.string.jdroid_locationPermissionRequired);
locationPermissionHelper.setOnRequestPermissionsResultListener(new PermissionHelper.OnRequestPermissionsResultListener() {
@Override
public void onRequestPermissionsGranted() {
if (map != null) {
map.setMyLocationEnabled(true);
}
}
@Override
public void onRequestPermissionsDenied() {
// Nothing to do
}
});
}
getMapAsync(new OnMapReadyCallback() {
@Override
public void onMapReady(final GoogleMap googleMap) {
map = googleMap;
// Setting an info window adapter allows us to change the both the contents and look of the
// info window.
InfoWindowAdapter infoWindowAdapter = getInfoWindowAdapter();
if (infoWindowAdapter != null) {
map.setInfoWindowAdapter(infoWindowAdapter);
}
map.setMapType(GoogleMap.MAP_TYPE_NORMAL);
AbstractMapFragment.this.onMapReady(map);
getGoogleMap().setOnMapLoadedCallback(new GoogleMap.OnMapLoadedCallback() {
@Override
public void onMapLoaded() {
AbstractMapFragment.this.onMapLoaded(googleMap);
}
});
if (locationPermissionHelper != null) {
Boolean locationPermissionGranted = locationPermissionHelper.checkPermission(false);
if (locationPermissionGranted) {
map.setMyLocationEnabled(true);
} else if (snackbarToSuggestLocationPermissionEnabled()) {
locationPermissionHelper.setOnRequestPermissionsResultListener(new PermissionHelper.OnRequestPermissionsResultListener() {
@Override
public void onRequestPermissionsGranted() {
if (map != null) {
map.setMyLocationEnabled(true);
}
}
@Override
public void onRequestPermissionsDenied() {
if (!snackbarDisplayed) {
SnackbarBuilder snackbarBuilder = new SnackbarBuilder();
snackbarBuilder.setActionTextResId(R.string.jdroid_allow);
snackbarBuilder.setDuration(5000);
snackbarBuilder.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
locationPermissionHelper.checkPermission(true);
snackbarDisplayed = true;
}
});
snackbarBuilder.setDescription(R.string.jdroid_locationPermissionSuggested);
snackbarBuilder.build(getActivity()).show();
}
}
});
}
}
}
});
}
protected Boolean snackbarToSuggestLocationPermissionEnabled() {
return false;
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
locationPermissionHelper.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = fragmentHelper.onCreateView(inflater, container, savedInstanceState);
mapContainer = (ViewGroup)view.findViewById(R.id.mapContainer);
View mapView = super.onCreateView(inflater, mapContainer, savedInstanceState);
mapContainer.addView(mapView);
return view;
}
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
fragmentHelper.onViewCreated(view, savedInstanceState);
updateGoogleplayServicesContainer = findView(R.id.updateGoogleplayServicesContainer);
}
protected void onMapReady(@NonNull GoogleMap googleMap) {
// Do Nothing
}
protected void onMapLoaded(@NonNull GoogleMap googleMap) {
// Do Nothing
}
@Override
public Integer getBaseFragmentLayout() {
return fragmentHelper.getBaseFragmentLayout();
}
@Override
public Integer getContentFragmentLayout() {
return R.layout.jdroid_map_fragment;
}
@Override
public void onNewIntent(Intent intent) {
fragmentHelper.onNewIntent(intent);
}
@Override
public void onStart() {
super.onStart();
fragmentHelper.onStart();
}
@Override
public void onResume() {
super.onResume();
fragmentHelper.onResume();
if (locationPermissionHelper != null) {
locationPermissionHelper.onResume();
}
if (GooglePlayServicesUtils.isGooglePlayServicesAvailable(getActivity())) {
displayMap();
} else {
showUpdateGooglePlayServices();
}
}
private void displayMap() {
updateGoogleplayServicesContainer.setVisibility(View.GONE);
mapContainer.setVisibility(View.VISIBLE);
}
private void showUpdateGooglePlayServices() {
mapContainer.setVisibility(View.GONE);
updateGoogleplayServicesContainer.setVisibility(View.VISIBLE);
Button button = findView(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
GooglePlayServicesUtils.launchGooglePlayServicesUpdate(getActivity());
}
});
}
protected InfoWindowAdapter getInfoWindowAdapter() {
return null;
}
protected Boolean isLocationEnabled() {
return false;
}
public GoogleMap getGoogleMap() {
return map;
}
@Override
public Boolean shouldRetainInstance() {
return fragmentHelper.shouldRetainInstance();
}
/**
* @see android.support.v4.app.Fragment#onActivityCreated(android.os.Bundle)
*/
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
fragmentHelper.onActivityCreated(savedInstanceState);
}
/**
* @see android.support.v4.app.Fragment#onPause()
*/
@Override
public void onPause() {
fragmentHelper.onBeforePause();
super.onPause();
fragmentHelper.onPause();
}
/**
* @see android.support.v4.app.Fragment#onStop()
*/
@Override
public void onStop() {
super.onStop();
fragmentHelper.onStop();
}
/**
* @see android.support.v4.app.Fragment#onDestroyView()
*/
@Override
public void onDestroyView() {
super.onDestroyView();
fragmentHelper.onDestroyView();
}
/**
* @see android.support.v4.app.Fragment#onDestroy()
*/
@Override
public void onDestroy() {
fragmentHelper.onBeforeDestroy();
super.onDestroy();
fragmentHelper.onDestroy();
}
/**
* @see com.jdroid.android.fragment.FragmentIf#findView(int)
*/
@Override
public <V extends View> V findView(int id) {
return fragmentHelper.findView(id);
}
/**
* @see com.jdroid.android.fragment.FragmentIf#findViewOnActivity(int)
*/
@Override
public <V extends View> V findViewOnActivity(int id) {
return fragmentHelper.findViewOnActivity(id);
}
/**
* @see com.jdroid.android.fragment.FragmentIf#inflate(int)
*/
@Override
public View inflate(int resource) {
return fragmentHelper.inflate(resource);
}
/**
* @see UseCaseListener#onStartUseCase()
*/
@Override
public void onStartUseCase() {
fragmentHelper.onStartUseCase();
}
/**
* @see UseCaseListener#onUpdateUseCase()
*/
@Override
public void onUpdateUseCase() {
fragmentHelper.onUpdateUseCase();
}
/**
* @see UseCaseListener#onFinishFailedUseCase(com.jdroid.java.exception.AbstractException)
*/
@Override
public void onFinishFailedUseCase(AbstractException abstractException) {
fragmentHelper.onFinishFailedUseCase(abstractException);
}
@Override
public ErrorDisplayer createErrorDisplayer(AbstractException abstractException) {
return fragmentHelper.createErrorDisplayer(abstractException);
}
/**
* @see UseCaseListener#onFinishUseCase()
*/
@Override
public void onFinishUseCase() {
fragmentHelper.onFinishUseCase();
}
/**
* @see com.jdroid.android.fragment.FragmentIf#executeOnUIThread(java.lang.Runnable)
*/
@Override
public void executeOnUIThread(Runnable runnable) {
fragmentHelper.executeOnUIThread(runnable);
}
/**
* @see com.jdroid.android.fragment.FragmentIf#getExtra(java.lang.String)
*/
@Override
public <E> E getExtra(String key) {
return fragmentHelper.<E>getExtra(key);
}
/**
* @see com.jdroid.android.fragment.FragmentIf#getArgument(java.lang.String)
*/
@Override
public <E> E getArgument(String key) {
return fragmentHelper.<E>getArgument(key);
}
/**
* @see com.jdroid.android.fragment.FragmentIf#getArgument(java.lang.String, java.lang.Object)
*/
@Override
public <E> E getArgument(String key, E defaultValue) {
return fragmentHelper.<E>getArgument(key, defaultValue);
}
@Override
public void executeUseCase(AbstractUseCase useCase) {
fragmentHelper.executeUseCase(useCase);
}
@Override
public void executeUseCase(AbstractUseCase useCase, Long delaySeconds) {
fragmentHelper.executeUseCase(useCase, delaySeconds);
}
@Override
public void beforeInitAppBar(Toolbar appBar) {
fragmentHelper.beforeInitAppBar(appBar);
}
@Override
public void afterInitAppBar(Toolbar appBar) {
fragmentHelper.afterInitAppBar(appBar);
}
@Override
public Toolbar getAppBar() {
return fragmentHelper.getAppBar();
}
@Override
public void registerUseCase(AbstractUseCase useCase, UseCaseListener listener) {
fragmentHelper.registerUseCase(useCase, listener);
}
@Override
public void registerUseCase(AbstractUseCase useCase, UseCaseListener listener,
UseCaseTrigger useCaseTrigger) {
fragmentHelper.registerUseCase(useCase, listener, useCaseTrigger);
}
@Override
public void unregisterUseCase(AbstractUseCase useCase, UseCaseListener listener) {
fragmentHelper.unregisterUseCase(useCase, listener);
}
/**
* @see com.jdroid.android.fragment.FragmentIf#getActivityIf()
*/
@Override
public ActivityIf getActivityIf() {
return fragmentHelper.getActivityIf();
}
// //////////////////////// Analytics //////////////////////// //
/**
* @see com.jdroid.android.fragment.FragmentIf#shouldTrackOnFragmentStart()
*/
@Override
public Boolean shouldTrackOnFragmentStart() {
return fragmentHelper.shouldTrackOnFragmentStart();
}
@NonNull
@Override
public String getScreenViewName() {
return fragmentHelper.getScreenViewName();
}
// //////////////////////// Loading //////////////////////// //
/**
* @see com.jdroid.android.fragment.FragmentIf#showLoading()
*/
@Override
public void showLoading() {
fragmentHelper.showLoading();
}
/**
* @see com.jdroid.android.fragment.FragmentIf#dismissLoading()
*/
@Override
public void dismissLoading() {
fragmentHelper.dismissLoading();
}
/**
* @see com.jdroid.android.fragment.FragmentIf#getDefaultLoading()
*/
@Override
public FragmentLoading getDefaultLoading() {
return fragmentHelper.getDefaultLoading();
}
/**
* @see com.jdroid.android.fragment.FragmentIf#setLoading(com.jdroid.android.loading.FragmentLoading)
*/
@Override
public void setLoading(FragmentLoading loading) {
fragmentHelper.setLoading(loading);
}
@Override
public Integer getMenuResourceId() {
return fragmentHelper.getMenuResourceId();
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
return fragmentHelper.onOptionsItemSelected(item);
}
@Override
public Boolean isSecondaryFragment() {
return fragmentHelper.isSecondaryFragment();
}
@Override
public FragmentDelegate createFragmentDelegate(AppModule appModule) {
return fragmentHelper.createFragmentDelegate(appModule);
}
@Override
public FragmentDelegate getFragmentDelegate(AppModule appModule) {
return fragmentHelper.getFragmentDelegate(appModule);
}
@Override
public Boolean onBackPressedHandled() {
return fragmentHelper.onBackPressedHandled();
}
}