package org.michenux.yourappidea.map; import android.Manifest; import android.app.Activity; import android.content.Intent; import android.content.IntentSender; import android.location.Location; import android.os.Bundle; import android.support.v4.app.Fragment; import android.util.Log; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import com.afollestad.materialdialogs.MaterialDialog; 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.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.maps.CameraUpdate; 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.SupportMapFragment; import com.google.android.gms.maps.model.LatLng; import com.tbruyelle.rxpermissions.RxPermissions; import org.michenux.drodrolib.ui.snackbar.SnackbarHelper; import org.michenux.yourappidea.BuildConfig; import org.michenux.yourappidea.R; import org.michenux.yourappidea.YourApplication; import rx.Subscription; public class SimpleMapFragment extends Fragment implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, LocationListener, OnMapReadyCallback { private static final int LOCATIONSERVICES_RESOLUTION_RESULCODE = 765; private GoogleMap mMap; private GoogleApiClient mGoogleApiClient; private LocationRequest mRequest; private boolean mPermissionGranted = false; private Subscription mSubscription; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setRetainInstance(true); setHasOptionsMenu(true); if (BuildConfig.DEBUG) { Log.d(YourApplication.LOG_TAG, "simpleMapFragment.onCreate"); } mGoogleApiClient = new GoogleApiClient.Builder(this.getActivity()) .addApi(LocationServices.API) .addConnectionCallbacks(this) .addOnConnectionFailedListener(this) .build(); mRequest = LocationRequest.create() .setInterval(5000) .setFastestInterval(16) .setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { if (BuildConfig.DEBUG) { Log.d(YourApplication.LOG_TAG, "simpleMapFragment.onCreateView"); } return inflater.inflate(R.layout.simplemap_fragment, container, false); } @Override public void onViewCreated(View view, Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); SupportMapFragment mapFragment = getMapFragment(); if (BuildConfig.DEBUG) { Log.d(YourApplication.LOG_TAG, "simpleMapFragment.onViewCreated - mapFragment = " + mapFragment); } if (mapFragment == null) { mapFragment = new SupportMapFragment(); mapFragment.setRetainInstance(true); getChildFragmentManager().beginTransaction().replace(R.id.simplemap, mapFragment, null).commit(); } mapFragment.getMapAsync(this); } private SupportMapFragment getMapFragment() { return (SupportMapFragment) getChildFragmentManager().findFragmentById(R.id.simplemap); } @Override public void onResume() { super.onResume(); mSubscription = RxPermissions.getInstance(this.getActivity()) .request(Manifest.permission.ACCESS_FINE_LOCATION) .subscribe(granted -> { mPermissionGranted = granted; if (granted) { mGoogleApiClient.connect(); } else { SnackbarHelper.showInfoLongMessage(this.getView(), R.string.error_permissionfinelocationrequired); } }); } @Override public void onPause() { super.onPause(); if (mGoogleApiClient.isConnected()) { LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this); } mGoogleApiClient.disconnect(); mSubscription.unsubscribe(); } @Override public void onConnected(Bundle bundle) { enableLocationOnMap(); registerLocationUpdates(); } @SuppressWarnings({"MissingPermission"}) private void registerLocationUpdates() { PendingResult<Status> result = LocationServices.FusedLocationApi .requestLocationUpdates( mGoogleApiClient, mRequest, this); result.setResultCallback(status -> { if (status.isSuccess()) { // Successfully registered } else if (status.hasResolution()) { // Google provides a way to fix the issue try { status.startResolutionForResult( SimpleMapFragment.this.getActivity(), // your current activity used to receive the result LOCATIONSERVICES_RESOLUTION_RESULCODE); // the result code you'll look for in your onActivityResult method to retry registering } catch (IntentSender.SendIntentException e) { Log.e(YourApplication.LOG_TAG, "SimpleMapFragment start resolution failure: ", e); } } else { // No recovery. Weep softly or inform the user. Log.e(YourApplication.LOG_TAG, "SimpleMapFragment registering failed: " + status.getStatusMessage()); } }); } @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == LOCATIONSERVICES_RESOLUTION_RESULCODE && resultCode == Activity.RESULT_OK) { registerLocationUpdates(); } } @Override public void onLocationChanged(Location location) { if (BuildConfig.DEBUG) { Log.d(YourApplication.LOG_TAG, "simpleMapFragment.onLocationChanged"); } if (mMap != null) { LatLng loc = new LatLng(location.getLatitude(), location.getLongitude()); CameraUpdate cameraUpdate = CameraUpdateFactory.newLatLngZoom(loc, 15); mMap.animateCamera(cameraUpdate); } } @SuppressWarnings({"MissingPermission"}) private void enableLocationOnMap() { if (mPermissionGranted && mMap != null && !mMap.isMyLocationEnabled()) { mMap.setMyLocationEnabled(true); } } @Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { inflater.inflate(R.menu.simplemap_menu, menu); } @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.simplemap_menu_info: new MaterialDialog.Builder(this.getActivity()) .title(R.string.simplemap_info_title) .items(R.array.simplemap_info_details) .positiveText(R.string.close) .show(); return true; } return super.onOptionsItemSelected(item); } @Override public void onConnectionFailed(ConnectionResult connectionResult) { SnackbarHelper.showInfoLongMessage(this.getView(), R.string.error_connectionfailed); } @Override public void onConnectionSuspended(int i) { SnackbarHelper.showInfoLongMessage(this.getView(), R.string.error_connectionsuspended); } @Override public void onMapReady(GoogleMap googleMap) { if (BuildConfig.DEBUG) { Log.d(YourApplication.LOG_TAG, "simpleMapFragment.onMapCreated - map: " + googleMap); } if (googleMap != null) { mMap = googleMap; this.enableLocationOnMap(); } } }