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);
}
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.
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 .
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.
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.
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.
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);
}
}
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);
}
mapFragment.setRetainInstance(true);
You can use it at onCreate to save map fragment state
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With