package com.example.meinwald.ui.main.map; import android.content.pm.PackageManager; import android.location.Location; import android.os.Bundle; import android.preference.PreferenceManager; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import com.example.meinwald.BuildConfig; import com.example.meinwald.R; import com.google.android.gms.location.FusedLocationProviderClient; import com.google.android.gms.location.LocationServices; 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.CameraPosition; import com.google.android.gms.maps.model.LatLng; import com.google.android.gms.tasks.OnCompleteListener; import com.google.android.gms.tasks.Task; import androidx.annotation.NonNull; import androidx.core.app.ActivityCompat; import androidx.core.content.ContextCompat; import androidx.fragment.app.Fragment; import androidx.fragment.app.FragmentTransaction; import static com.example.meinwald.R.layout.fragment_map; public class MapsFragment extends Fragment implements OnMapReadyCallback { /** * ______________________________________________________________________________________________ * MAPS */ // A default location and default zoom to use when location permission is not granted. private static final LatLng M_DEFAULT_LOCATION = new LatLng(49.5, 11.0); //Nuremberg private static final int DEFAULT_ZOOM = 1; private static final float MAX_ZOOM = (float) 20.0; private static final int PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION = 1; private static final String TAG = MapsFragment.class.getSimpleName(); // Keys for storing activity state. private static final String KEY_CAMERA_POSITION = "camera_position"; private static final String KEY_LOCATION = "location"; private GoogleMap mMap; private CameraPosition mCameraPosition; /** * The entry point to the Fused Location Provider. */ private FusedLocationProviderClient mFusedLocationProviderClient; private boolean mLocationPermissionGranted; /** * The geographical location where the device is currently located. * That is the last-known location retrieved by the Fused Location Provider. */ private Location mLastKnownLocation; /** * Is called when the MapsFragment view is created. Initializes all service connections, the location client and map itself. * @param inflater Calling LayoutInflater * @param container ViewGroup * @param savedInstanceState Applications savedInstanceState * @return */ public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { //get view to inflate View root = inflater.inflate(fragment_map, container, false); //display map fragment SupportMapFragment mapFragment = new SupportMapFragment(); FragmentTransaction transaction = getChildFragmentManager().beginTransaction(); transaction.add(R.id.map, mapFragment).commit(); //construct a FusedLocationProviderClient. mFusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(getActivity()); //wait for map is ready mapFragment.getMapAsync(new OnMapReadyCallback() { @Override public void onMapReady(GoogleMap googleMap) { //save map instance locally mMap = googleMap; //set max zoom level mMap.setMaxZoomPreference(MAX_ZOOM); //retrieve saved instance state mCameraPosition = parseCameraPosition(PreferenceManager.getDefaultSharedPreferences(getContext()).getString(KEY_CAMERA_POSITION, new CameraPosition(new LatLng(45.0,11.0), (float) 1.0, (float) 0.0,(float) 0.0).toString())); mLastKnownLocation = new Location(PreferenceManager.getDefaultSharedPreferences(getContext()).getString(KEY_LOCATION, new LatLng(45.0,11.0).toString())); mCameraPosition = parseCameraPosition(PreferenceManager.getDefaultSharedPreferences(getContext()).getString(KEY_CAMERA_POSITION, new CameraPosition(new LatLng(45.0,11.0), (float) 1.0, (float) 0.0,(float) 0.0).toString())); //move camera to last position mMap.moveCamera(CameraUpdateFactory.newCameraPosition(mCameraPosition)); //get permission getLocationPermission(); //turn on the My Location layer and the related control on the map. updateLocationUI(); // Get the current location of the device and set the position of the map. getDeviceLocation(); } }); return root; } @Override public void onPause() { //save current location and camera position to shared preferences if (mMap.getCameraPosition() != null && mLastKnownLocation != null) { PreferenceManager.getDefaultSharedPreferences(getContext()).edit().putString(KEY_CAMERA_POSITION, mMap.getCameraPosition().toString()).commit(); PreferenceManager.getDefaultSharedPreferences(getContext()).edit().putString(KEY_LOCATION, mLastKnownLocation.toString()).commit(); } super.onPause(); } @Override public void onResume() { super.onResume(); } /** * Parses a string and creates a new CameraPosition from it. * Use CameraPosition.toString() to get corresponding string. * @param posString String which includes a camera position. * @return The parsed position of type CameraPosition. */ private CameraPosition parseCameraPosition(String posString) { //parse string from shared preferences (CameraPosition.toString()) String[] stringsplit = posString.split(" "); float lat = Float.parseFloat(stringsplit[1].split(",")[0].substring(1)); float lng = Float.parseFloat(stringsplit[1].split(",")[1].substring(0,stringsplit[1].split(",")[1].length()-1)); float zoom = Float.parseFloat(stringsplit[2].split("=")[1].substring(0,stringsplit[2].split("=")[1].length()-1)); float tilt = Float.parseFloat(stringsplit[3].split("=")[1].substring(0,stringsplit[3].split("=")[1].length()-1)); float bearing = Float.parseFloat(stringsplit[4].split("=")[1].substring(0,stringsplit[4].split("=")[1].length()-1)); return new CameraPosition(new LatLng(lat,lng),zoom,tilt,bearing); } /** * Request location permission, so that we can get the location of the device. * The result of the permission request is handled by a callback, * onRequestPermissionsResult. * */ private void getLocationPermission() { if (ContextCompat.checkSelfPermission(getActivity().getApplicationContext(), android.Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) { mLocationPermissionGranted = true; } else { ActivityCompat.requestPermissions(getActivity(), new String[]{android.Manifest.permission.ACCESS_FINE_LOCATION}, PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION); } } /** * DOCU ME! * TOOD: What are grant results etc for? * @param requestCode * @param permissions * @param grantResults */ @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { mLocationPermissionGranted = false; switch (requestCode) { case PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION: { // If request is cancelled, the result arrays are empty. if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { updateLocationUI(); mLocationPermissionGranted = true; } } } } /** * Get the best and most recent location of the device, which may be null in rare * cases when a location is not available. * */ private void getDeviceLocation() { try { if (mLocationPermissionGranted) { Task locationResult = mFusedLocationProviderClient.getLastLocation(); locationResult.addOnCompleteListener(getActivity(), new OnCompleteListener() { @Override public void onComplete(@NonNull Task task) { if (task.isSuccessful()) { // Set the last known position to the current location of the device. mLastKnownLocation = task.getResult(); if (BuildConfig.DEBUG) { if (task.getResult() != null) { Log.d(TAG, "getDeviceLocation " + task.getResult().toString()); } } } else { if (BuildConfig.DEBUG) { Log.d(TAG, "Current location is null. Using defaults."); Log.e(TAG, "Exception: %s", task.getException()); } mMap.moveCamera(CameraUpdateFactory .newLatLngZoom(M_DEFAULT_LOCATION, DEFAULT_ZOOM)); //mMap.getUiSettings().setMyLocationButtonEnabled(false); if (BuildConfig.DEBUG) { Log.d(TAG, "getDeviceLocation: task not successful"); } } } }); } } catch (SecurityException e) { if (BuildConfig.DEBUG) { Log.e(TAG, "Exception occurred: "); e.printStackTrace(); } } } private void updateLocationUI() { if (mMap == null) { if (BuildConfig.DEBUG) { Log.d(TAG, "Permission: Map not ready!"); } return; } try { if (mLocationPermissionGranted) { mMap.setMyLocationEnabled(true); mMap.getUiSettings().setMapToolbarEnabled(true); mMap.getUiSettings().setMyLocationButtonEnabled(true); mMap.getUiSettings().setCompassEnabled(true); mMap.getUiSettings().setZoomControlsEnabled(true); if (BuildConfig.DEBUG) { Log.d(TAG, "Permission: Granted!"); } } else { mMap.setMyLocationEnabled(false); mMap.getUiSettings().setMyLocationButtonEnabled(false); mMap.getUiSettings().setZoomControlsEnabled(false); mMap.getUiSettings().setCompassEnabled(false); mMap.getUiSettings().setMapToolbarEnabled(false); mLastKnownLocation = null; if (BuildConfig.DEBUG) { Log.d(TAG, "Permission: Denied!"); } getLocationPermission(); } } catch (SecurityException e) { if (BuildConfig.DEBUG) { Log.e(TAG, "Exception occurred: "); e.printStackTrace(); } } } @Override public void onMapReady(GoogleMap googleMap) { } }