可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I'm trying to explore using the MapView class for GoogleMap display, with no luck, as most codes examples are using MapFragment which I do not want.
I am using Google Maps Android API v2.
At first, just for testing with here from Google's example, I managed to get the typical normal map to display.
public class POnlineMapView extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.online_map_activity);
}
}
The code above works perfectly which show that everything has been set up properly.
I am now trying to use the MapView class to manipulate the display settings such as the center point, but it seems like I am obtaining a null object everytime I try to obtain the GoogleMap object. Why is this so?
public class POnlineMapView extends Activity {
private MapView myMapView;
private GoogleMap map;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
myMapView = new MapView(getApplicationContext());
Bundle b = getIntent().getExtras();
double longitude = b.getDouble("longitude");
double latitude = b.getDouble("latitude");
setContentView(R.layout.online_map_activity);
map = myMapView.getMap();
CameraUpdate center= CameraUpdateFactory.newLatLng(new LatLng(latitude,longitude));
CameraUpdate zoom=CameraUpdateFactory.zoomTo(17);
map.moveCamera(center); //this gives a NullPointerException, probably due to the myMapView.getMap() method?
map.animateCamera(zoom);
}
}
回答1:
Check whether Google Play Service are installed (and updated)
See Google Maps Android API v2 throws GooglePlayServicesNotAvailableException, out of date, SupportMapFragment.getMap() returns null
Please also read https://developers.google.com/maps/documentation/android/map (section Verify Map availability)
回答2:
This seems like an old question, but I was having the same problem trying to use MapView.
Assuming you have properly imported the Google Play Services lib, you have to check if you have access to Google Services, you can do this in your onCreate method, and you have to initialize the Google Maps Android AP. you can do this by adding the following code to your onCreate method
try {
MapsInitializer.initialize(this);
} catch (GooglePlayServicesNotAvailableException e) {
Log.e("Address Map", "Could not initialize google play", e);
}
switch (GooglePlayServicesUtil.isGooglePlayServicesAvailable(this) )
{
case ConnectionResult.SUCCESS:
Toast.makeText(getApplicationContext(), "SUCCESS", Toast.LENGTH_SHORT).show();
break;
case ConnectionResult.SERVICE_MISSING:
Toast.makeText(getApplicationContext(), "SERVICE MISSING", Toast.LENGTH_SHORT).show();
break;
case ConnectionResult.SERVICE_VERSION_UPDATE_REQUIRED:
Toast.makeText(getApplicationContext(), "UPDATE REQUIRED", Toast.LENGTH_SHORT).show();
break;
default: Toast.makeText(getApplicationContext(), GooglePlayServicesUtil.isGooglePlayServicesAvailable(this), Toast.LENGTH_SHORT).show();
}
If you get SUCCESS, then everything is working so far.
You also have to implement the mothods of the Activity lyfecycle and call the corresponding methond of your map view inside every one of these methods:
@Override
protected void onResume() {
myMapView.onResume();
super.onResume();
}
@Override
protected void onPause() {
myMapView.onResume();
super.onPause();
}
@Override
protected void onDestroy() {
myMapView.onDestroy();
super.onDestroy();
//((MapView)findViewById(R.id.mapView)).onDestroy();
}
@Override
public void onLowMemory() {
super.onLowMemory();
myMapView.onLowMemory();
}
Finally, you have to check that you have added your Google Maps API key to your Manifest file:
<meta-data
android:name="com.google.android.maps.v2.API_KEY"
android:value="YOUR KEY"/>
you can find instructions to get your key here: https://developers.google.com/maps/documentation/android/start#installing_the_google_maps_android_v2_api
Edit:
Forgot to mention, you also have to set your applications permissions on the manifest file
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
This has to be set inside the application block ...
回答3:
Thanks, you finally gave me a clue to initialize the Map programatically, how stupid I oversaw it :)
Well, sometimes there is no option to use MapFragment (or SupportMapFragment alike), i.e. when you want to use the map from a fragment! This is actually a very common case when working with tabs (ActionBar) where the pattern is to use fragments. So you've got your own fragment per tab and in that fragment for a map you want to inflate your layout which contains a fragment for the MapFragment, et voila - good luck!
Now, according to the MapView specs it is no way said that using of the MapView is discouraged or deprecated, so why should I not use it? I did not want hacks in maintaining nested fragments without having support from SDK ( even the recent support lib v13 seems to have bugs and nested fragments from layout are not supported ), so using MapView turned for me into KISS.
Below is my CustomMapFragment I use with layout inflation (allowing complex layout) and embedded map, you're welcome to use it. You may also want to extend the Fragment from support-lib rather than SDK.
The onCreateView() method inflates the layout (just provide you're own) and expects the layout to have viewgroup (relativelayout,linearlayout,etc) with id "mapViewHolder" where the mapView will be attached to upon layout creation. The activity has to implement CustomMapFragment.Handler interface, otherwise ClassCastException will be thrown.
import android.app.Activity;
import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast;
import com.google.android.gms.common.GooglePlayServicesNotAvailableException;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.MapView;
import com.google.android.gms.maps.MapsInitializer;
import R;
public class AppMapFragment extends Fragment {
/*
* to interact with activity
*/
public static interface Handler {
void onMapResume(GoogleMap map);
}
private Handler handler;
private MapView mapView;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
try {
// initialize explicitely, since we're working with MapView (not MapFragment)
MapsInitializer.initialize(getActivity());
this.mapView = new MapView(getActivity());
this.mapView.onCreate(savedInstanceState);
} catch (GooglePlayServicesNotAvailableException e) {
Toast.makeText(getActivity(), "Please install Google Play Store and retry again!", Toast.LENGTH_LONG).show();
getActivity().finish();
}
}
@Override
public void onResume() {
super.onResume();
this.mapView.onResume();
this.handler.onMapResume(this.mapView.getMap());
}
@Override
public void onPause() {
super.onPause();
this.mapView.onPause();
}
@Override
public void onDestroy() {
super.onDestroy();
this.mapView.onDestroy();
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
this.mapView.onSaveInstanceState(outState);
}
@Override
public void onLowMemory() {
super.onLowMemory();
this.mapView.onLowMemory();
}
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
this.handler = (Handler) activity;
} catch (ClassCastException e) {
throw new ClassCastException("Your activity has to implement the interface " + this.handler.getClass().getName());
}
}
public AppMapFragment() {
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_results_map, container, false);
((ViewGroup) rootView.findViewById(R.id.mapViewHolder)).addView(this.mapView);
return rootView;
}
}
回答4:
One difference between MapFragment and MapView is that you have to manually manage the lifecycle of MapView, while MapFragment takes care of it by itself.
You must call the following methods from the parent Activity/Fragment's corresponding methods.
onCreate(Bundle)
onResume()
onPause()
onDestroy()
onSaveInstanceState()
onLowMemory()
I verified this with RawMapViewDemoActivity in samples of Google Play Services, which can be installed in the Extras section of Android SDK Manager.
The sample showed the map at first, and it showed a blank page once I commented out the 6 lines of mMapView.onXXX().
Maybe the lifecycle is the reason why most examples we see everywhere use MapFragment.
回答5:
Try out this way:
private MapView myMapView;
private GoogleMap map;
myMapView = (MapView) findViewById(R.id.map);
if (map == null) {
map = ((MapView) findViewById(R.id.map)).getMap();
}
回答6:
I didn't have luck with the map view either.
I did have luck with the MapFragment.
Try this:
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.model.LatLng;
public class TestActivity extends FragmentActivity {
SupportMapFragment mapFragment;
GoogleMap map;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (mapFragment == null) {
mapFragment = new SupportMapFragment();
getSupportFragmentManager().beginTransaction()
.add(android.R.id.content, mapFragment).commit();
}
}
@Override
protected void onResume() {
super.onResume();
setupMap();
}
private void setupMap() {
if (map != null)
return;
map = mapFragment.getMap();
if (map == null)
return;
doZoom();
}
private void doZoom() {
if (map != null) {
map.animateCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(45.424900,
-75.694968), 17));
}
}
}