I'm facing an issue when using Google Maps v2 in Android. I want to have a MapView as part of a layout. I'm able to ge the MapView along with a marker, however the tiles themselves don't load UNLESS I click on the map. For each click I do, an additional tile will be painted (so it takes like 4 or 5 clicks to get the whole map).
I'm using Maps V2 but in this particular case, not in a fragment. As a note, the map works ok in another place in which I'm using a MapFragment.
The following are the important snippets of code:
Snippet of the activity:
public class ViewNodeDetailsGame extends MapActivity implements View.OnClickListener, OnMapReadyCallback {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mBundle = savedInstanceState;
setContentView(R.layout.activity_view_node_details_game);
// Maps related
MapsInitializer.initialize(this);
// ... the data is fetched asynchronously here. Then, getLocation() is called
}
private void getLocation(final LinearLayout llLocation) {
mMapView = (MapView)llLocation.findViewById(R.id.map);
mMapView.onCreate(mBundle);
mMapView.getMapAsync(this);
}
#Override
public void onMapReady(GoogleMap map) {
LatLng sydney = new LatLng(-34, 151);
map.addMarker(new MarkerOptions().position(sydney).title("Marker in Sydney"));
map.setMapType(GoogleMap.MAP_TYPE_NORMAL);
map.animateCamera(CameraUpdateFactory.newLatLng(sydney));
map.getUiSettings().setMyLocationButtonEnabled(true);
map.getUiSettings().setZoomControlsEnabled(true);
map.getUiSettings().setCompassEnabled(true);
map.getUiSettings().setAllGesturesEnabled(true);
}
#Override
public void onResume() {
super.onResume();
if (mMapView != null) {
mMapView.onResume();
}
}
#Override
public void onPause() {
super.onPause();
if (mMapView != null) {
mMapView.onPause();
}
}
#Override
public void onLowMemory() {
super.onLowMemory();
if (mMapView != null) {
mMapView.onLowMemory();
}
}
#Override
public void onSaveInstanceState(Bundle outState)
{
super.onSaveInstanceState(outState);
if (mMapView != null) {
mMapView.onSaveInstanceState(outState);
}
}
#Override
public void onDestroy() {
super.onDestoy();
if (mMapView != null) {
mMapView.onDestroy();
}
}
Snippet of the layout. This layout is added programmatically:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#fff"
android:padding="5dp"
android:orientation="vertical">
<com.google.android.gms.maps.MapView
android:id="#+id/map"
android:clickable="true"
android:enabled="true"
android:layout_width="match_parent"
android:layout_height="250dp" />
<!-- More stuff below -->
I am including my API_KEY in the AndroidManifest.xml file:
<!-- lots of stuff above this... -->
<meta-data
android:name="com.google.android.geo.API_KEY"
android:value="AIza --rest of my key here--"
/>
</application>
The following images show the progression of tile painting I get with each click. Any tips are appreciated.
It's because you don't call
mMapView.onResume() in Activity's onResume() callback.
Related
When starting a new map activity the map loads really slow and doesn't start the loading until clicking the screen.
The Layout is the following:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:layout_height="match_parent" android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
android:paddingBottom="#dimen/activity_vertical_margin"
tools:context="com.example.android.momintuition.DirectionsActivity">
<com.google.android.gms.maps.MapView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:map="http://schemas.android.com/apk/res-auto"
android:id="#+id/mapView"
android:paddingTop="62px"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clickable="true"
map:uiCompass="true"
map:zOrderOnTop="true"
map:uiZoomControls="true"
android:background="#00000000" />
</RelativeLayout>
The new activity looks like this:
public class DirectionsActivity extends AppCompatActivity implements OnMapReadyCallback {
GoogleMap mMap; // Might be null if Google Play services APK is not available.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_directions);
MapView mv = (MapView) findViewById(R.id.mapView);
mv.onCreate(savedInstanceState);
mMap = mv.getMapAsync(this);
}
#Override
public void onMapReady(GoogleMap googleMap) {
this.map = googleMap;
CameraUpdate cameraUpdate =
CameraUpdateFactory.newLatLngZoom(new LatLng(43.1, -87.9), 10);
map.animateCamera(cameraUpdate);
}
}
I am new to Android. Am I missing something? Thank you!
The problem in this case was that I didn't implement the following methods(even if it was specified in the documentation):
#Override
public void onResume() {
mapView.onResume();
super.onResume();
}
#Override
public void onPause() {
super.onPause();
mapView.onPause();
}
#Override
public void onDestroy() {
super.onDestroy();
mapView.onDestroy();
}
#Override
public void onLowMemory() {
super.onLowMemory();
mapView.onLowMemory();
}
It is counterintuitive to me why this methods might affect showing the map but it does fix the problem.
TL;DR These lines made my map load.
itemMap.onResume();
mapView.onEnterAmbient(null);
For people having the same problem:
I'm using maps inside a RecyclerView, and I was having the same problem, so I implemented racula's answer by having an ArrayList of type MapView, and I would add the mapView to the list when it was initialized.
And in the Activity Lifecycle methods I would get the mapViewList from the adapter, and call the appropriate method. And now the map was loading when I resumed the application.
//In the Activity
#Override
protected void onResume() {
super.onResume();
for(MapView mapView : adapter.getMapViewList()){
if (mapView != null){
mapView.onResume();
}
}
}
So finally I tested a few things, and added the "itemMap.onResume();" and the "mapView.onEnterAmbient(null);" methods, and the map started loading and working just fine.
Here's a simple version of my Adapter class
//RecyclerView Adapter and inside it the ViewHolder
class ReminderAdapter extends RecyclerView.Adapter<ReminderAdapter.MyViewHolder> {
private ArrayList<MapView> mapViewList;
#Override
public RecyclerViewAdapter.MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.item_layout, parent, false);
return new MyViewHolder(itemView);
}
#Override
public void onBindViewHolder(final ReminderAdapter.MyViewHolder holder, int position) {
(...)
holder.initializeMapView(new LatLng(getLat(), getLng()));
}
ArrayList<MapView> getMapViewList(){
return mapViewList;
}
(...)
class MyViewHolder extends RecyclerView.ViewHolder implements OnMapReadyCallback{
#Override
public void onMapReady(GoogleMap googleMap) {
MapsInitializer.initialize(context);
googleMap.moveCamera(CameraUpdateFactory.newLatLngZoom(latLng, 15f));
googleMap.addMarker(new MarkerOptions().position(latLng));
this.googleMap = googleMap;
itemMap.onResume(); //The methods
itemMap.onEnterAmbient(null); // that made my map work
}
void initializeMapView(LatLng latLng){
if(itemMap != null){
this.latLng = latLng;
itemMap.onCreate(bundle);
itemMap.getMapAsync(this);
mapViewList.add(itemMap); // adds the MapView to the list
}
}
}
}
I have an Activity (which inflates a map fragment) which implements the GoogleMap.onCameraChangedListener, and I have overriden the onCameraChange method.
The problem is that whenever I move across the map, i.e. the camera position changes, the onCameraChange method is never called.
What could be causing this?
Try this :
public class MapActivity extends AppCompatActivity implements
GoogleMap.OnCameraChangeListener{
private GoogleMap googleMap;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.googlemap_layout);
setUpMapIfNeeded();
}
#Override
public void onCameraChange(CameraPosition cameraPosition) {
double latitude = cameraPosition.target.latitude;
double longitude = cameraPosition.target.longitude;
}
private void setUpMapIfNeeded() {
if (googleMap == null) {
// Try to obtain the map from the SupportMapFragment.
googleMap = ((SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map)).getMap();
if (googleMap != null) {
googleMap.setMyLocationEnabled(true);
googleMap.getUiSettings().setMyLocationButtonEnabled(true);
googleMap.getUiSettings().setRotateGesturesEnabled(false);
googleMap.getUiSettings().setZoomControlsEnabled(false);
googleMap.setOnCameraChangeListener(this);
}
}
}
}
Layout :
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<fragment
android:id="#+id/map"
android:layout_width="match_parent"
android:layout_height="match_parent"
class="com.google.android.gms.maps.SupportMapFragment" />
</RelativeLayout>
I want to add one Marker in Google map. I successfully loaded map in my app but when I tried to add a Marker, the app got crashed. I don't know why. Please some one help me!
My code:
public class BasicMapActivity extends FragmentActivity {
private GoogleMap mMap;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.basic_demo);
setUpMap();
}
#Override
protected void onResume() {
super.onResume();
}
private void setUpMap() {
mMap.addMarker(new MarkerOptions().position(new LatLng(0, 0)).title("Marker"));
}
}
Layout.xml file:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<fragment
android:id="#+id/map2"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
class="com.google.android.gms.maps.SupportMapFragment" />
</LinearLayout>
Create a method setUpMapIfNeeded() and called on onResume() and onCreate()
private void setUpMapIfNeeded() {
// Do a null check to confirm that we have not already instantiated the map.
if (mMap == null) {
// Try to obtain the map from the SupportMapFragment.
mMap = ((SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map))
.getMap();
// Check if we were successful in obtaining the map.
if (mMap != null) {
setUpMap();
}
}
}
First you need to obtain the map from the SupportMapFragment and then you add Marker into map using
mMap.addMarker(new MarkerOptions().position(new LatLng(Your_lat, Your_long)).title("Marker"));
Try This
private void setUpMap() {
Marker pos_Marker = googleMap.addMarker(new MarkerOptions().position(starting).icon(BitmapDescriptorFactory.fromResource(R.drawable.ic_laumcher)).title("Starting Location").draggable(false));
pos_Marker.showInfoWindow();
}
I would like to put an Google Map in a fragment, but please be noted that I want to put it inside the onActivityCreated, and the fragment class just need to extend fragment class only.
And my final layout will be:
This is a fragment contains a text, map and button.
~~~~~~~~~~~~~~~
Textview.....
Map.....
Button....
~~~~~~~~~~~~~~~
Also, the map need include my current location.
May I know how to do that? with java and xml please :)
In your Fragment layout put a MapView widget:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:map="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- My TextView -->
<com.google.android.gms.maps.MapView android:id="#+id/my_map"
android:layout_width="match_parent"
android:layout_height="match_parent"
map:uiZoomControls="false"
map:uiCompass="false"
map:uiRotateGestures="false"
map:uiScrollGestures="true"
map:uiTiltGestures="false"
map:uiZoomGestures="true"
android:visibility="visible"/>
<!-- My Button and eventually others widgets -->
</RelativeLayout>
Your fragment will inflate your custom layout with the MapView and the others widgets you need in . Here a pseudo code about how to setup the MapView.
public class MyCustomFragmentWithMap extends Fragment {
private MapView mMapView = null;
private GoogleMap mMyMap = null;
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
try {
MapsInitializer.initialize(getActivity());
} catch (GooglePlayServicesNotAvailableException err) {
Log.e(TAG, err.getMessage(), err);
}
mMapView = (MapView)getView().findViewById(R.id.my_map);
mMapView.onCreate(savedInstanceState);
mMyMap = mMapView.getMap();
mMyMap.setMyLocationEnabled(true);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.my_custom_fragment_with_map, container, false);
/* All the widgets setup as usual ... */
return view;
}
#Override
public void onResume() {
super.onResume();
if (mMapView != null)
mMapView.onResume();
}
#Override
public void onPause() {
if (mMapView != null)
mMapView.onPause();
super.onPause();
}
#Override
public void onDestroy() {
if (mMapView != null)
mMapView.onDestroy();
super.onDestroy();
}
#Override
public void onLowMemory() {
super.onLowMemory();
if (mMapView != null)
mMapView.onLowMemory();
}
#Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
if (mMapView != null)
mMapView.onSaveInstanceState(outState);
}
I'm assuming that you already know how to setup the Google Maps Android API v2 (obtaining the api key, setting permissions in manifest and all the boring stuffs :-P).
Am trying to create and app with one activity but multiple fragment. i am using android.support.v4.* to build the fragment.
Each item i have created so far by extending Fragment, I want to use the google Map Api2 in my application,
All the tutoril i found so far adding the "SupportMapFragment" as an element to layout file.
"<fragment
class="com.google.android.gms.maps.SupportMapFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"/>"
But i cannot use this way because nested fragment not supporting, how can i use the google map api2 as a fragment in my application
use the mapview as suggested in Comments
public class InteractiveMapsWidget extends Fragment {
private MapView mMapView;
private GoogleMap mMap;
public void onCreate(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
Log.i(TAG, "ON CREATED");
Activity activity = getActivity();
if (activity != null) {
Bundle bundle = getArguments();
`
}
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
Log.i(TAG, "onCreateView");
new DataWorkerAsyncTask(getActivity()).execute(widgetId);
mMapView = (MapView) view.findViewById(R.id.map);
mMapView.onCreate(savedInstanceState);
setUpMapIfNeeded();
return view;
}
#Override
public void onResume() {
super.onResume();
mMapView.onResume();
setUpMapIfNeeded();
}
private void setUpMapIfNeeded() {
if (mMap == null) {
mMap = ((MapView) view.findViewById(R.id.map)).getMap();
if (mMap != null) {
setUpMap();
}
}
}
private void setUpMap() {
mMap.addMarker(new MarkerOptions().position(new LatLng(0, 0)).title("Marker"));
}
#Override
public void onPause() {
mMapView.onPause();
super.onPause();
}
#Override
public void onDestroy() {
mMapView.onDestroy();
super.onDestroy();
}
#Override
public void onLowMemory() {
super.onLowMemory();
mMapView.onLowMemory();
}
#Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
}
}
Layout
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:map="http://schemas.android.com/apk/res-auto"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<LinearLayout
android:id="#+id/root_container"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<com.google.android.gms.maps.MapView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/map"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
</LinearLayout>