Google Maps v2 sometimes resets when resuming app - android

I am using Google Maps v2 in my Android application. Everything works fine, but if I leave the application (using the home button), use the device for other stuff and then return to my app, the maps just reset themselves and discard all my settings and listeners.
I think it's because my phone doesn't have that much RAM so when it needs it for running other apps, something that's vital for my app gets lost... If I don't use other apps in the meantime, it resumes with all the settings and listeners intact.
So I have a member variable private GoogleMap map = null;
I need to create the map programatically because I am putting it into a LinearLayout (fragment_wrapper) that I also want to use for other fragments. So I am doing this in my onCreate() method:
mapFragment = MapFragment.newInstance();
FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction();
fragmentTransaction.add(R.id.fragment_wrapper, mapFragment);
fragmentTransaction.commit();
The map doesn't get initialized very quickly, so I need to set its settings and listeners in the onResume() method:
if (map == null) {
map = mapFragment.getMap();
UiSettings settings = map.getUiSettings();
settings.setMyLocationButtonEnabled(false);
settings.setZoomControlsEnabled(false);
(...)
map.setOnMapClickListener((...));
(...)
}
I originally put the if block there so that the app wouldn't have to set the map's settings and listeners again on resuming. But then I noticed it forgets the settings. So I thought that if I deleted the if block, it would just set up the map again since onResume() gets called when the app is resumed. But it doesn't work either... So all the map's settings and listeners are gone which renders the map useless and my app needs to be restarted in order to set up the map again.
Can anyone please tell me what the problem could be and how to solve it? Thank you.

I was finally able to find the solution in the Google Maps v2 sample code, which is located at <android-sdk-folder>\extras\google\google_play_services\samples\maps\. See https://developers.google.com/maps/documentation/android/intro#sample_code. What helped me was the file src\com\example\mapdemo\ProgrammaticDemoActivity.java.
What was happening was that the application got shutdown completely, so its onCreate() method was called again. There you have to somehow find out whether you have already created the map fragment or not. The solution is to try to find a tag of your map fragment. If it can't be found, it means the activity is running for the first time. You create your fragment and add the tag to it. Then the next time the onCreate() gets called, your fragment can be found by the tag and all the settings and listeners are preserved.
So you can for example set a final static variable in your activity: private static final String MAP_FRAGMENT_TAG = "map";
and then use this code in your onCreate() method:
mapFragment = (MapFragment) getFragmentManager().findFragmentByTag(MAP_FRAGMENT_TAG);
if (mapFragment == null) {
mapFragment = MapFragment.newInstance();
FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction();
fragmentTransaction.add(R.id.fragment_wrapper, mapFragment, MAP_FRAGMENT_TAG);
fragmentTransaction.commit();
}
setUpMapIfNeeded();
This in the onResume() method:
setUpMapIfNeeded();
And the setUpMapIfNeeded() method could look like this:
if (map == null) {
map = mapFragment.getMap();
if (map != null) {
setUpMap();
}
}
(So the map sets up already in onCreate() and if not, then in onResume().)
Hope this helps someone.

Related

Google Map AnimateCamera not working the second time

I am struggling with animateCamera() method of the Google Maps. It only works on first launch of activity and if the activity is destroyed and created again, camera animations doesn't work but map is loaded fine. I have tried debugging the code, everything gets executed but map doesn't animate without any error or log. Although animation works when same mapFragment is used in the fragment but in activity it doesn't seem to work.
The solution mentioned in this this question is deprecated now and I am unable to fix this issue.
Map Fragment
SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map);
mapFragment.getMapAsync(this);
mapFragment.setRetainInstance(true);
#Override
public void onMapReady(GoogleMap googleMap) {
if (mMap == null) mMap = googleMap;
}
Code for animating camera
mMap.animateCamera(CameraUpdateFactory.newLatLngZoom(latLng, ZOOM_LEVEL));
Making entire project again from old code fixed the issue. But this issue re-appeared in another app. I found out that application was using old reference to mMap. This can be fixed by either getting reference from fragment manager or just setting mMap = null when activity is destroyed.

Android Google Maps transition from portrait to landscape and vice versa

My application only displays the map on Google maps. My problem is when I change the position of my screen (the application I installed on my tablet), turning it there's a white screen that appears before displaying the map.
My configuration; res / layout / main.xml and res / layout-land / main.xml to switch from portrait to landscape mode.
What should add or do to resolve this behavior?
Since you have specified the map fragment in the layout file, you can safely find it using findFragmentById in onCreate like so:
MapFragment mMapFragment; // this is neither GoogleMap or MapView!
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mMapFragment = (MapFragment)getFragmentManager().findFragmentById(R.id.map);
initializeMap();
}
#Override
public void onResume() {
super.onResume();
// map init was already done in onCreate, will not do it twice
}
Then when you need the GoogleMap object you ask for it and have it delivered via a callback. When the callback executes, the map is guaranteed to be not null. This will work since Google Play services library v6.5.
private void initializeMap() {
mMapFragment.getMapAsync(new OnMapReadyCallback() {
#Override
public void onMapReady(GoogleMap googleMap) {
// googleMap will never be null here
// do not store it in a variable, always make a getMapAsync call
// do your map setup here
}
}
}
This is as quick as it gets so you shouldn't experience any flickering.
Note: In the original post you mentioned you had different layouts for portrait and landscape. If you really do, make sure both contain corresponding fragment IDs, otherwise you're bound to get exceptions. You also mentioned the layout was main.xml not activity_main.xml so make sure you use the layout you intended.
I solved my problem reading this (Activity restart on rotation Android) Activity restart on rotation Android

Android google map v2 is not working after the application is closed and reopened

When the application opens I create a new instance of a google map during onAttachedToWindow(), this works fine while the application is open. When I close the application and re-open it the google map does not load correctly, it just shows grey tiles.
#Override
public void onAttachedToWindow() {
if (hasCreated()) {
uiGoogleMap = ((SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map_content_map_fragment)).getMap();
}
}
When should the google map be initialised to ensure it is loaded when the application is closed and re-opened?
EDIT:
I have tried initialising the map in onResume() and onCreate() and get the same problem
on Google API2 this hassle has been eliminated.
What you need to do is just initialize the map you created on your xml.
uiGoogleMap = ((MapFragment) getFragmentManager().findFragmentById(R.id.map_content_map_fragment))
.getMap();
So when you close and re-open it it will be available. no need to override anything.
I think that the best place would be to create a class that extends SupportMapFragment, and initialise the map in:
#Override
public void onAttach(Activity activity)
Besides that though, I think if you initialise the map in onResume of the container activity it should be ok. But if you by initialising you mean adding the mapfragment to the activity, I would suggest doing it in the xml or in your activity's onCreate. Just my two pennies.

Android: Google Maps API v2 rendering issue with markers and camera animation

EDIT
I've found a better STR:
Make sure to set "Do not keep activities" in Developer options in Settings.
Open the app with a SupportMapFragment as a child fragment of another fragment.
Switch to another app
Open your app again
Notice you can't interact with the map and no animations work.
Open another screen within the app
Notice there's a single frame or so of the map with the markers drawn on screen.
I have an issue with Google Maps API v2.
I am animating the camera to zoom to a set of custom marker bitmaps rendered on a MapFragment.
On selecting one of these marker tooltips I open a geo: intent (for the Google Maps app etc.)
When the user presses back it reopens my activity with the fragment back stack rebuilt.
My issue is that it doesn't render camera animations or the markers on coming back, though there is a brief display of those markers when the user presses back to go to the previous fragment.
The GoogleMap instance has the markers, but it doesn't render them - I'm guessing because the MapFragment/MapView thinks it doesn't need to be rendered.
How do I force a render of the MapView? Failing that, how do I get the MapView to recognise that the model has changed?
The issue was to do with the way I was handling my child fragments.
Every time the parent fragment would call onCreate the children fragments would get recreated.
I did the following to handle my child fragments, but there may be a better way:
private static final String TAG_FRAGMENT_MAP = "TagFragmentMap";
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// ...
if (savedInstanceState == null) {
// create the fragments for the first time
ft.add(R.id.view_flip, new SupportMapFragment(), TAG_FRAGMENT_MAP);
ft.commit();
}
}
// ...
public void onViewStateRestored(Bundle savedInstanceState) {
super.onViewStateRestored(savedInstanceState);
mMapFragment = (SupportMapFragment)findFragmentByTag(TAG_FRAGMENT_MAP);
}

How to swap between map fragment and list fragment in android while updating both fragments with AsyncTask

My strategy for doing this was very simple while using a MapView, but I am now transitioning over to Android Maps v2 and have to use a MapFragment. My scenario involves getting a list of events, and then I need to Geodecode these in the background to get their latitude and longitude to calculate distance from user and also to place onto the map. I have an actionbar button that allows the user to switch between the list and map fragment, but my issue is how do I keep both fragments in memory and avoid their lifecycle so that I can continually add markers to the map fragment while updating the list adapter in the list fragment?
Currently I replace the FrameLayout by FragmentTransaction.replace with each Fragment, but this causes the other one to get destroyed, whereas I simply want it to be hidden (before I would simply set the MapView visibility to View.GONE).
EDIT
My code ended up being:
#Override
public void swapFragments() {
FragmentManager fm = getSupportFragmentManager();
FragmentTransaction transaction = fm.beginTransaction();
if (listFragment.isVisible()) {
transaction.hide(listFragment);
if (mapFragment.isAdded()) {
transaction.show(mapFragment);
} else {
transaction.add(R.id.root, mapFragment);
}
} else {
transaction.hide(mapFragment);
transaction.show(listFragment);
}
transaction.commit();
}
I've been working on something similar. What I do is create both fragments in the onCreate() portion of my main FragmentActivity --- then based on the onclick action, I show and hide the appropriate fragments. I supplement this by adding to the back stack before I commit my hiding of the listFragment so that when a user presses back, they'll get the list again and not the previous activity.
However, at the moment, I'm having trouble with getting the GoogleMap to not be null in my MapFragment for some reason.
I solved this issue -- you can find a similar answer here MapFragment Error - CameraUpdateFactory is not initialized

Categories

Resources