我的 android 应用程序有一个奇怪的问题。我实现了地图,我得到了应该完成的 api-key,将它插入到我的应用程序中......当我通过 Eclipse 直接在手机上启动应用程序时,它可以工作。当我将应用程序导出到 apk 并将其传递给朋友以便在其他手机上进行测试时,地图永远不会显示并且应用程序崩溃,因为 mapController 为 null:
07-24 14:52:07.425: E/AndroidRuntime(4107): FATAL EXCEPTION: main
07-24 14:52:07.425: E/AndroidRuntime(4107): java.lang.NullPointerException
07-24 14:52:07.425: E/AndroidRuntime(4107): at com.google.android.maps.MapController.animateTo(MapController.java:232)
07-24 14:52:07.425: E/AndroidRuntime(4107): at com.google.android.maps.MapController.animateTo(MapController.java:203)
07-24 14:52:07.425: E/AndroidRuntime(4107): at com.emaborsa.cablePark.activities.MainActivity$5.onItemClick(MainActivity.java:492)
07-24 14:52:07.425: E/AndroidRuntime(4107): at com.emaborsa.cablePark.popUpMenu.MapPopupMenu$1.onClick(MapPopupMenu.java:163)
07-24 14:52:07.425: E/AndroidRuntime(4107): at android.view.View.performClick(View.java:4084)
07-24 14:52:07.425: E/AndroidRuntime(4107): at android.view.View$PerformClick.run(View.java:16966)
07-24 14:52:07.425: E/AndroidRuntime(4107): at android.os.Handler.handleCallback(Handler.java:615)
07-24 14:52:07.425: E/AndroidRuntime(4107): at android.os.Handler.dispatchMessage(Handler.java:92)
07-24 14:52:07.425: E/AndroidRuntime(4107): at android.os.Looper.loop(Looper.java:137)
07-24 14:52:07.425: E/AndroidRuntime(4107): at android.app.ActivityThread.main(ActivityThread.java:4745)
07-24 14:52:07.425: E/AndroidRuntime(4107): at java.lang.reflect.Method.invokeNative(Native Method)
07-24 14:52:07.425: E/AndroidRuntime(4107): at java.lang.reflect.Method.invoke(Method.java:511)
07-24 14:52:07.425: E/AndroidRuntime(4107): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
07-24 14:52:07.425: E/AndroidRuntime(4107): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
07-24 14:52:07.425: E/AndroidRuntime(4107): at dalvik.system.NativeStart.main(Native Method)
编码:
public class MainActivity extends MapActivity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.e("Log", "onCreate()");
this.application = (CableParkApplication) getApplication();
database = new DatabaseManager(getApplicationContext());
if (getWindowManager().getDefaultDisplay().getRotation() == VERTICAL) {
setContentView(R.layout.main_v);
} else {
setContentView(R.layout.main_h);
}
if (savedInstanceState != null) {
this.currentView = savedInstanceState.getInt(CURRENT_VIEW);
this.mapType = savedInstanceState.getBoolean(MAP_TYPE);
this.country = savedInstanceState.getString(COUNTRY);
showMapMenu((LinearLayout) ((ImageView) mapViewContainer.findViewById(R.id.map_menu_open)).getParent());
}
initViews();
myLocationOverlay = new MyLocationOverlay(getApplicationContext(), mapView);
mapView.getOverlays().add(myLocationOverlay);
mapHandler = new MapHandler(this, mapView);
mapHandler.initMap(mapType);
addListeners();
showActualFrame();
}
protected void initViews() {
// initializes main view
mainView = (LinearLayout) findViewById(R.id.mainView);
LinearLayout main_view_vertical = (LinearLayout) getLayoutInflater().inflate(R.layout.mainview_v, null);
mainView.addView(main_view_vertical);
// initializes search view
searchMainView = (LinearLayout) findViewById(R.id.searchView);
LinearLayout search_view_vertical = (LinearLayout) getLayoutInflater().inflate(R.layout.searchview_v, null);
searchMainView.addView(search_view_vertical);
searchTextCountry = (TextView) findViewById(R.id.selectCountry);
selectCountryFlag = (ImageView) searchMainView.findViewById(R.id.selectCountryFlag);
searchEditTextKey = (EditText) findViewById(R.id.searchEditTextKey);
searchTextView = (TextView) findViewById(R.id.searchTextView);
searchButton = (LinearLayout) findViewById(R.id.searchButton);
if (country != null && !country.equals("")) {
searchTextCountry.setText(country);
String flag = country.toLowerCase().replace(" ", "");
int resId = getResources().getIdentifier(flag, "drawable", CableParkApplication.PACKAGE);
selectCountryFlag.setImageResource(resId);
}
// initializes diary view
diaryMainView = (LinearLayout) findViewById(R.id.diaryView);
LinearLayout diary_view_vertical = (LinearLayout) getLayoutInflater().inflate(R.layout.diaryview_v, null);
diaryMainView.addView(diary_view_vertical);
// initializes map(container) view
mapViewContainer = (LinearLayout) findViewById(R.id.mapViewContainer);
LinearLayout map_view_container_vertical = (LinearLayout) getLayoutInflater().inflate(R.layout.mapviewcontainer_v, null);
mapViewContainer.addView(map_view_container_vertical);
mapView = (MapView) findViewById(R.id.mapView);
if (!application.isLoaded()) {
application.setLoaded(true);
Animation myFadeInAnimation = AnimationUtils.loadAnimation(this, R.anim.fadein);
myFadeInAnimation.setAnimationListener(new SplashAnimation(MainActivity.this, getWindowManager().getDefaultDisplay()
.getRotation()));
mainView.startAnimation(myFadeInAnimation);
} else {
findViewById(R.id.buttonsLayout).setVisibility(View.VISIBLE);
findViewById(R.id.id).setVisibility(View.INVISIBLE);
}
// initializes bottom buttons
searchImageLayout = (LinearLayout) findViewById(R.id.searchImageLayout);
mapImageLayout = ((LinearLayout) findViewById(R.id.mapImageLayout));
diaryImageLayout = ((LinearLayout) findViewById(R.id.diaryImageLayout));
}
private void addListeners() {
searchButton.setOnTouchListener(new View.OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
searchButton.setBackgroundResource(R.drawable.singlebuttondown);
searchTextView.setTextColor(Color.YELLOW);
return true;
} else if (event.getAction() == MotionEvent.ACTION_UP) {
searchButton.setBackgroundResource(R.drawable.singlebutton);
searchTextView.setTextColor(getResources().getColor(R.color.gray));
if (doSearch()) {
showSearchResult();
hideSoftPad();
showMap(null);
} else {
showNoResultDialog();
}
return true;
}
return false;
}
});
searchEditTextKey.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
if (searchEditTextKey.getText().toString().equals("....?")) {
searchEditTextKey.setText("");
}
}
});
searchEditTextKey.setOnEditorActionListener(new TextView.OnEditorActionListener() {
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
if (actionId == EditorInfo.IME_ACTION_SEARCH) {
if (doSearch()) {
showSearchResult();
hideSoftPad();
showMap(null);
} else {
showNoResultDialog();
}
return true;
}
return false;
}
});
}
protected void showActualFrame() {
switch (currentView) {
case SEARCH:
showSearch(searchMainView);
break;
case MAP:
showMap(mapView);
break;
case DIARY:
showDiary(diaryMainView);
break;
default:
showFrame(mainView);
}
}
@Override
protected void onResume() {
Log.e("Log", "onResume()");
broadcastReceiver = new MessageReceiver();
IntentFilter inFilter = new IntentFilter();
inFilter.addAction(CableParkApplication.CANCEL);
inFilter.addAction(CableParkApplication.COUNTRY);
inFilter.addAction(CableParkApplication.SINGLE_PARK);
registerReceiver(broadcastReceiver, inFilter);
super.onResume();
myLocationOverlay.enableMyLocation();
myLocationOverlay.enableCompass();
};
@Override
protected void onPause() {
unregisterReceiver(broadcastReceiver);
this.zoomLevel = mapView.getZoomLevel();
this.mapCenter = mapView.getMapCenter();
super.onPause();
myLocationOverlay.disableMyLocation();
myLocationOverlay.disableCompass();
Log.e("Log", "onPause()");
}
// customized the onBackButton
@Override
public void onBackPressed() {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("Leave?").setCancelable(false).setMessage("Close the application?").setCancelable(true)
.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
finish();
}
}).setNegativeButton("No", null);
AlertDialog dialog = builder.create();
dialog.show();
}
@Override
protected boolean isRouteDisplayed() {
return false;
}
public void showSearch(View v) {
mapView.removeAllViews();
currentView = SEARCH;
searchEditTextKey.setText("");
setBackground(searchImageLayout);
showFrame(searchMainView);
}
public void showMap(View v) {
currentView = MAP;
setBackground(mapImageLayout);
showFrame(mapViewContainer);
mapView.setVisibility(View.VISIBLE);
}
public void showDiary(View v) {
mapView.removeAllViews();
currentView = DIARY;
setBackground(diaryImageLayout);
showFrame(diaryMainView);
}
protected void showFrame(View view) {
mainView.setVisibility(View.INVISIBLE);
mapView.setVisibility(View.INVISIBLE);
mapViewContainer.setVisibility(View.INVISIBLE);
diaryMainView.setVisibility(View.INVISIBLE);
searchMainView.setVisibility(View.INVISIBLE);
view.setVisibility(View.VISIBLE);
}
protected void setBackground(LinearLayout layout) {
searchImageLayout.setBackgroundResource(R.drawable.buttons);
mapImageLayout.setBackgroundResource(R.drawable.buttons);
diaryImageLayout.setBackgroundResource(R.drawable.buttons);
layout.setBackgroundResource(R.drawable.buttonsdown);
}
private boolean doSearch() {
String key = searchEditTextKey.getText().toString();
String country = (String) searchTextCountry.getText();
database.connectForReading();
Vector<Park> parks = database.getParks(country, key);
database.disconnect();
application.setParkSearch(parks);
return parks.size() > 0;
}
private void showSearchResult() {
Vector<Park> parks = application.getParkSearch();
mapHandler.drawGeopoints(parks);
CenterGeoPointCalculator cgpc = new CenterGeoPointCalculator(parks);
cgpc.calc();
mapHandler.centerMap(cgpc, getWindowManager().getDefaultDisplay().getRotation());
mapView.getController().animateTo(cgpc.getCenterPoint());
}
public void showCountriesDialog(View v) {
searchTextCountry.setTextColor(Color.YELLOW);
CountriesAdapter adapter = new CountriesAdapter(MainActivity.this, application.getCountries());
dialog = new CountriesDialog(MainActivity.this, adapter);
dialog.show();
}
public void showNoResultDialog() {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setMessage("No parks found.\nTry another country or another search key.").setCancelable(false)
.setNegativeButton("OK", null);
AlertDialog alert = builder.create();
alert.show();
}
private class MessageReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (action.equals(CableParkApplication.COUNTRY)) {
country = intent.getStringExtra("country");
searchTextCountry.setText(country);
String flag = country.toLowerCase().replace(" ", "");
int resId = context.getResources().getIdentifier(flag, "drawable", CableParkApplication.PACKAGE);
selectCountryFlag.setImageResource(resId);
searchTextCountry.setTextColor(Color.WHITE);
dialog.dismiss();
} else if (action.equals(CableParkApplication.COUNTRY)) {
searchTextCountry.setTextColor(Color.WHITE);
dialog.dismiss();
} else if (action.equals(CableParkApplication.SINGLE_PARK)) {
int parkId = intent.getIntExtra("park", -1);
if (parkId > 0) {
mapView.removeAllViews();
Intent i = new Intent(context, SinglePark.class);
i.putExtra("park", parkId);
startActivity(i);
}
}
}
}
@Override
protected void onSaveInstanceState(Bundle outState) {
Log.e("Log", "onSaveInstanceState()");
super.onSaveInstanceState(outState);
if (popupMenu != null) {
popupMenu.dismiss();
}
outState.putInt(CURRENT_VIEW, currentView);
outState.putBoolean(MAP_TYPE, mapType);
outState.putString(COUNTRY, (String) searchTextCountry.getText());
}
public void showMapMenu(View v) {
mapView.removeAllViews();
popupMenu = new MapPopupMenu(this);
final ImageView mapMenuOpen = (ImageView) v.findViewById(R.id.map_menu_open);
mapMenuOpen.setImageResource(R.drawable.menu_close);
Drawable image = getResources().getDrawable(R.drawable.location);
if (mapView.getZoomLevel() < 5
|| (myLocationOverlay.isMyLocationEnabled() && !mapHandler.isMyLocationVisible(application.getCurrentLocation()))) {
MenuEntry myLocation = new MenuEntry(ID_MOVE_TO_ME, "Show", image);
popupMenu.addActionItem(myLocation);
} else if (myLocationOverlay.isMyLocationEnabled()) {
MenuEntry hideLocation = new MenuEntry(ID_DISABLE_LOC, "Hide", image);
popupMenu.addActionItem(hideLocation);
} else {
MenuEntry showLocation = new MenuEntry(ID_ENABLE_LOC, "Show", image);
popupMenu.addActionItem(showLocation);
}
image = getResources().getDrawable(R.drawable.compass);
if (myLocationOverlay.isCompassEnabled()) {
MenuEntry hideCompass = new MenuEntry(ID_DISABLE_COMP, "Hide", image);
popupMenu.addActionItem(hideCompass);
} else {
MenuEntry showCompass = new MenuEntry(ID_ENABLE_COMP, "Show", image);
popupMenu.addActionItem(showCompass);
}
image = getResources().getDrawable(R.drawable.map_menu);
if (mapHandler.getShownMap() == MapHandler.SATELLITE) {
MenuEntry showMap = new MenuEntry(ID_SHOW_MAP, "Map", image);
popupMenu.addActionItem(showMap);
} else {
MenuEntry showTraffic = new MenuEntry(ID_SHOW_TRAFFIC, "Hybrid", image);
popupMenu.addActionItem(showTraffic);
}
popupMenu.setAnimStyle(MapPopupMenu.ANIM_GROW_FROM_RIGHT);
// Set listener for action item clicked
popupMenu.setOnActionItemClickListener(new MapPopupMenu.OnActionItemClickListener() {
public void onItemClick(MapPopupMenu source, int pos, int actionId) {
switch (actionId) {
case ID_DISABLE_COMP:
myLocationOverlay.disableCompass();
break;
case ID_ENABLE_COMP:
myLocationOverlay.enableCompass();
break;
case ID_DISABLE_LOC:
myLocationOverlay.disableMyLocation();
break;
case ID_ENABLE_LOC:
myLocationOverlay.enableMyLocation();
mapView.getController().animateTo(application.getCurrentLocation());//line 492 controller seems to be null...
break;
case ID_SHOW_MAP:
mapType = mapHandler.showMap(MapHandler.MAP);
break;
case ID_SHOW_TRAFFIC:
mapType = mapHandler.showMap(MapHandler.SATELLITE);
break;
case ID_MOVE_TO_ME:
myLocationOverlay.enableMyLocation();
mapView.getController().animateTo(application.getCurrentLocation());
mapView.getController().setZoom(MapHandler.MYLOCATION_ZOOM);
break;
}
mapMenuOpen.setImageResource(R.drawable.menu_open);
}
});
popupMenu.setOnDismissListener(new MapPopupMenu.OnDismissListener() {
public void onDismiss() {
mapMenuOpen.setImageResource(R.drawable.menu_open);
}
});
popupMenu.show(v, mapMenuOpen);
}
private void hideSoftPad() {
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(searchEditTextKey.getWindowToken(), 0);
}
@Override
protected void onRestart() {
mapView.getController().setZoom(zoomLevel);
mapView.getController().setCenter(mapCenter);
Log.e("Log", "onRestart()");
super.onRestart();
}
}
我的 getCurrentLocation() 方法:
public GeoPoint getCurrentLocation() {
// Get the location manager
locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
// Define the criteria how to select the locatioin provider -> use
// default
Criteria criteria = new Criteria();
String provider = locationManager.getBestProvider(criteria, false);
Location location = locationManager.getLastKnownLocation(provider);
// Initialize the location fields
if (location != null) {
int lat = (int) (location.getLatitude() * 1E6);
int lng = (int) (location.getLongitude() * 1E6);
return new GeoPoint(lat, lng);
} else {
return null;
}
}
...如果该方法返回 null,我理解异常。但是它怎么会在我的手机上返回一些东西,而在所有其他手机上返回 null 呢?