Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android: Saving Map State in Google map

I used this code before but now i got some errors in Resuming the Map State. I got this code from David Gassner from its tutorial and now i want to use it again. im a little Bit Confused, I put some tossed message in order to trace. the LogCat report point the error in RESUME starting this line Anybody knows how to fix this?

map.animateCamera(update);          
map.setMapType(mgr.getSavedMapType())

heres the Code:

@Override
protected void onStop() {
    super.onStop();
    MapStateManager mgr = new MapStateManager(this);
    mgr.saveMapState(mMap);
    Toast.makeText(this, "Map State has been save?", Toast.LENGTH_SHORT).show();
}

@Override
protected void onResume() {
    super.onResume();
    MapStateManager mgr = new MapStateManager(this);
    CameraPosition position = mgr.getSavedCameraPosition();
    if (position != null) {
        CameraUpdate update = CameraUpdateFactory.newCameraPosition(position);
        Toast.makeText(this, "entering Resume State", Toast.LENGTH_SHORT).show();
        mMap.moveCamera(update);

        mMap.setMapType(mgr.getSavedMapType());
    }
}
public class MapStateManager {

    private static final String LONGITUDE = "longitude";
    private static final String LATITUDE = "latitude";
    private static final String ZOOM = "zoom";
    private static final String BEARING = "bearing";
    private static final String TILT = "tilt";
    private static final String MAPTYPE = "MAPTYPE";

    private static final String PREFS_NAME ="mapCameraState";

    private SharedPreferences mapStatePrefs;

    public MapStateManager(Context context) {
        mapStatePrefs = context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE);
    }

    public void saveMapState(GoogleMap mapMie) {
        SharedPreferences.Editor editor = mapStatePrefs.edit();
        CameraPosition position = mapMie.getCameraPosition();

        editor.putFloat(LATITUDE, (float) position.target.latitude);
        editor.putFloat(LONGITUDE, (float) position.target.longitude);
        editor.putFloat(ZOOM, position.zoom);
        editor.putFloat(TILT, position.tilt);
        editor.putFloat(BEARING, position.bearing);
        editor.putInt(MAPTYPE, mapMie.getMapType());
        editor.commit();
    }

    public CameraPosition getSavedCameraPosition() {
        double latitude = mapStatePrefs.getFloat(LATITUDE, 0);
        if (latitude == 0) {
            return null;
        }
        double longitude = mapStatePrefs.getFloat(LONGITUDE, 0);
        LatLng target = new LatLng(latitude, longitude);

        float zoom = mapStatePrefs.getFloat(ZOOM, 0);
        float bearing = mapStatePrefs.getFloat(BEARING, 0);
        float tilt = mapStatePrefs.getFloat(TILT, 0);

        CameraPosition position = new CameraPosition(target, zoom, tilt, bearing);
        return position;
    }

    public int getSavedMapType() {
        return mapStatePrefs.getInt(MAPTYPE, GoogleMap.MAP_TYPE_NORMAL);
    }
}

Here is the error from the logcat. I only included the red lines.

> 01-07 12:51:46.145: E/AndroidRuntime(15770): FATAL EXCEPTION: main
01-07 12:51:46.145: E/AndroidRuntime(15770): java.lang.RuntimeException: Unable to resume activity {com.ourThesis.junieNegentien2015/com.ourThesis.junieNegentien2015.MainActivity}: java.lang.NullPointerException
01-07 12:51:46.145: E/AndroidRuntime(15770):    at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2936)
01-07 12:51:46.145: E/AndroidRuntime(15770):    at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:2965)
01-07 12:51:46.145: E/AndroidRuntime(15770):    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2400)
01-07 12:51:46.145: E/AndroidRuntime(15770):    at android.app.ActivityThread.access$600(ActivityThread.java:162)
01-07 12:51:46.145: E/AndroidRuntime(15770):    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1364)
01-07 12:51:46.145: E/AndroidRuntime(15770):    at android.os.Handler.dispatchMessage(Handler.java:107)
01-07 12:51:46.145: E/AndroidRuntime(15770):    at android.os.Looper.loop(Looper.java:194)
01-07 12:51:46.145: E/AndroidRuntime(15770):    at android.app.ActivityThread.main(ActivityThread.java:5371)
01-07 12:51:46.145: E/AndroidRuntime(15770):    at java.lang.reflect.Method.invokeNative(Native Method)
01-07 12:51:46.145: E/AndroidRuntime(15770):    at java.lang.reflect.Method.invoke(Method.java:525)
01-07 12:51:46.145: E/AndroidRuntime(15770):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:841)
01-07 12:51:46.145: E/AndroidRuntime(15770):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:608)
01-07 12:51:46.145: E/AndroidRuntime(15770):    at dalvik.system.NativeStart.main(Native Method)
01-07 12:51:46.145: E/AndroidRuntime(15770): Caused by: java.lang.NullPointerException
01-07 12:51:46.145: E/AndroidRuntime(15770):    at com.ourThesis.junieNegentien2015.MainActivity.onResume(MainActivity.java:183)
01-07 12:51:46.145: E/AndroidRuntime(15770):    at android.app.Instrumentation.callActivityOnResume(Instrumentation.java:1190)
01-07 12:51:46.145: E/AndroidRuntime(15770):    at android.app.Activity.performResume(Activity.java:5213)
01-07 12:51:46.145: E/AndroidRuntime(15770):    at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2923)
01-07 12:51:46.145: E/AndroidRuntime(15770):    ... 12 more

@Tim Castelijns, Below is the modified mode but still not working can you take a look?

private SupportMapFragment mapFragment;
    private GoogleMap map;  
    private Location mCurrentLocation;
    private GoogleApiClient mGoogleApiClient;

    @Override
    protected void onCreate(Bundle savedInstanceState) { 
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main); 
        setupMapIfNeeded();
        mToolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(mToolbar);

    }

    private void setupMapIfNeeded() {
        mapFragment = ((SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map));             
        if (mapFragment != null) {          
            mapFragment.getMapAsync(new OnMapReadyCallback()
            {
                @Override
                public void onMapReady(GoogleMap map) 
                {
                    loadMap(map);                                       
                }
            });
        } else 
        {
            Toast.makeText(this, "Error - Map Fragment was null!!", Toast.LENGTH_SHORT).show();
        }
    }

    protected void loadMap(GoogleMap googleMap) {
        map = googleMap;
        if (map != null) {
            // Map is ready
            Toast.makeText(this, "Map Fragment was loaded properly!", Toast.LENGTH_LONG).show();
            initListeners();            

            // map is loaded, trace your location
            mGoogleApiClient = new GoogleApiClient.Builder(this)
                    .addApi(LocationServices.API)               
                    .addConnectionCallbacks(this)
                    .addOnConnectionFailedListener(this)
                    .build();
            connectClient();

            //calling resume state
            resumeState(map);

        } else {
            Toast.makeText(this, "Error - Map was null!!", Toast.LENGTH_SHORT).show();
        }
    }

    protected void connectClient() {
        // Connect the client.
        if (isGooglePlayServicesAvailable() && mGoogleApiClient != null) {
            mGoogleApiClient.connect();
            Toast.makeText(this, "Google API Client successfully connected", Toast.LENGTH_LONG).show();
        }
    }

    /*
     * Called when the Activity becomes visible.
    */
    @Override
    protected void onStart() {
        super.onStart();
        connectClient();
        }

    public void resumeState(GoogleMap googleMap) {      
        map = googleMap;
        MapStateManager mgr = new MapStateManager(this);
        CameraPosition position = mgr.getSavedCameraPosition();
        if (position != null) {
            CameraUpdate update = CameraUpdateFactory.newCameraPosition(position);
            Toast.makeText(this, "entering Resume State", Toast.LENGTH_LONG).show();
            map.moveCamera(update);

            map.setMapType(mgr.getSavedMapType());
        }
    }

    /*
     * Called when the Activity is no longer visible.
     */    
    @Override
    protected void onPause() {
        super.onPause();
        MapStateManager mgr = new MapStateManager(this);
        mgr.saveMapState(map);
        Toast.makeText(this, "Map State has been save?", Toast.LENGTH_LONG).show();
    }

    @Override
    protected void onResume() {     
        super.onResume();       
        setupMapIfNeeded();
    }

    @Override
    public void onConnected(Bundle dataBundle) {
        // Display the connection status
        Location location = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
        if (location != null) {
            Toast.makeText(this, "GPS location was found!", Toast.LENGTH_SHORT).show();
            LatLng latLng = new LatLng(location.getLatitude(), location.getLongitude());
            CameraUpdate cameraUpdate = CameraUpdateFactory.newLatLngZoom(latLng, 16);
            map.animateCamera(cameraUpdate);
            /*startLocationUpdates();*/
        } else {
            Toast.makeText(this, "Current location was null, enable GPS on your mobile!", Toast.LENGTH_SHORT).show();
        }
    }

    private void initListeners() {
        map.setMapType(GoogleMap.MAP_TYPE_HYBRID);
        map.getUiSettings().setZoomControlsEnabled(true);
        map.setMyLocationEnabled(true);
        map.setOnMarkerClickListener(null);        
        map.setOnMapLongClickListener(null);
        map.setOnInfoWindowClickListener(null);
        map.setOnMapClickListener(null);
        map.setTrafficEnabled(true);
        map.setOnMapLongClickListener(this);
        map.setOnMapClickListener(this);
        map.setPadding(0, 80, 0, 0);

    }
like image 209
Larigyn Avatar asked Jan 06 '16 15:01

Larigyn


People also ask

Can you save a Google map with pins?

Open the Google Maps app. Find a location on the map where you'd like to drop a pin. Tap and hold the spot until a pin appears, then tap the Save icon at the bottom of the screen and select a list to save it to.

How do I view saved Places on Google Maps on Android?

On your Android phone or tablet, open the Google Maps app . Tap the search box. Enter the name of the place you saved. Tap the search suggestion for the place. To show saved places while you search, turn on Web & App Activity. On your Android phone or tablet, open the Google Maps app .

How do I save an address on Google Maps?

First, open the Google Maps app on your iPhone or Android phone. Then, select an address you’d like to save. You can do this by searching for a place, tapping a marker, or touching and holding a spot on the map. From the location’s description, tap Save and choose which list you want to save it to.

How do I save a list of places on the map?

Search for a place, tap a marker, or touch and hold a spot on the map. At the bottom of the screen, tap the name or address of the place. Tap Save and choose a list.

How to save Google Maps for offline use?

In fact, the official Google instructions to save maps are unclear and confusing as these instructions differ for applications and Android versions. A quick and alternate way to save any map for offline use is to type “ok map” in the search bar. As soon as you tap the search button, the map will be ready to downloaded with your selected area.


3 Answers

The problem is that your mMap is null when you are resuming, and then you cannot use mMap.moveCamera(); for example, which leads to your app crashing.

Solution for this is to check if the map needs to be set up before trying to use it again.

I slightly modified your code to check if the map needs to be set up in both onCreate and onResume. Note that I use onPause instead of onStop because it is the counterpart to onResume.

private GoogleMap mMap;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_maps);
    setupMapIfNeeded();
}

private void setupMapIfNeeded() {
    // Obtain the SupportMapFragment and get notified when the map is ready to be used.
    if (mMap == null) {
        SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
                .findFragmentById(R.id.map);
        mapFragment.getMapAsync(this);
    }
}
@Override
public void onMapReady(GoogleMap googleMap) {
    mMap = googleMap;

    MapStateManager mgr = new MapStateManager(this);
    CameraPosition position = mgr.getSavedCameraPosition();
    if (position != null) {
        CameraUpdate update = CameraUpdateFactory.newCameraPosition(position);
        Toast.makeText(this, "entering Resume State", Toast.LENGTH_SHORT).show();
        mMap.moveCamera(update);

        mMap.setMapType(mgr.getSavedMapType());
    }
}

@Override
protected void onPause() {
    super.onPause();
    MapStateManager mgr = new MapStateManager(this);
    mgr.saveMapState(mMap);
    Toast.makeText(this, "Map State has been save?", Toast.LENGTH_SHORT).show();
}

@Override
protected void onResume() {
    super.onResume();
    setupMapIfNeeded();
}

MapstateManager is exactly the same.

public class MapStateManager {

    private static final String LONGITUDE = "longitude";
    private static final String LATITUDE = "latitude";
    private static final String ZOOM = "zoom";
    private static final String BEARING = "bearing";
    private static final String TILT = "tilt";
    private static final String MAPTYPE = "MAPTYPE";

    private static final String PREFS_NAME ="mapCameraState";

    private SharedPreferences mapStatePrefs;

    public MapStateManager(Context context) {
        mapStatePrefs = context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE);
    }

    public void saveMapState(GoogleMap mapMie) {
        SharedPreferences.Editor editor = mapStatePrefs.edit();
        CameraPosition position = mapMie.getCameraPosition();

        editor.putFloat(LATITUDE, (float) position.target.latitude);
        editor.putFloat(LONGITUDE, (float) position.target.longitude);
        editor.putFloat(ZOOM, position.zoom);
        editor.putFloat(TILT, position.tilt);
        editor.putFloat(BEARING, position.bearing);
        editor.putInt(MAPTYPE, mapMie.getMapType());
        editor.commit();
    }

    public CameraPosition getSavedCameraPosition() {
        double latitude = mapStatePrefs.getFloat(LATITUDE, 0);
        if (latitude == 0) {
            return null;
        }
        double longitude = mapStatePrefs.getFloat(LONGITUDE, 0);
        LatLng target = new LatLng(latitude, longitude);

        float zoom = mapStatePrefs.getFloat(ZOOM, 0);
        float bearing = mapStatePrefs.getFloat(BEARING, 0);
        float tilt = mapStatePrefs.getFloat(TILT, 0);

        CameraPosition position = new CameraPosition(target, zoom, tilt, bearing);
        return position;
    }

    public int getSavedMapType() {
        return mapStatePrefs.getInt(MAPTYPE, GoogleMap.MAP_TYPE_NORMAL);
    }
}
like image 142
Tim Avatar answered Oct 01 '22 03:10

Tim


If you want to just save and restore the camera position between orientation changes, you could just save the CameraPosition instance itself on your saveInstanceState Bundle. CameraPosition implements ReflectedParcelable so this should work.

@Override
public void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);

    if (googleMap != null) {
        outState.putParcelable(STATE_KEY_MAP_CAMERA, googleMap.getCameraPosition());
    }
}

And to restored it do the following

if (savedInstanceState != null) {
    CameraUpdate cameraPos = CameraUpdateFactory.newCameraPosition(
        (CameraPosition)(savedInstanceState.getParcelable(STATE_KEY_MAP_CAMERA)));
    googleMap.moveCamera(cameraPos);
}
like image 39
theshadowchild Avatar answered Oct 01 '22 02:10

theshadowchild


mapFragment.setRetainInstance(true);You can use it at onCreate to save map fragment state

like image 37
Mikhail Avatar answered Oct 01 '22 01:10

Mikhail