我一直在尝试实现android的MapView v2。除了这个bug之外,我还能正常工作。
这是我从头开始加载应用程序时的样子...
如您所见,那里没有问题。
现在,当我按下“主页”按钮并尝试从“最近的应用程序”窗口访问应用程序时,我得到:
并保持这种状态,直到我解雇该应用并从头开始重新加载。
以下是我的一些代码。
Layout.xml
<LinearLayout
android:id="@+id/maps_container"
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"
android:name="com.google.android.gms.maps.SupportMapFragment"
android:layout_marginBottom="100dip"
android:layout_marginLeft="10dip"
android:layout_marginRight="10dip"
android:layout_marginTop="100dip"/>
</LinearLayout>
活动:
public class MyActivity extends BaseActivity {
private GoogleMap mMaps;
private LinearLayout mMapsContainer;
@Override
public void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.my_layout);
mMapsContainer = (LinearLayout) findViewById(R.id.maps_container);
mMaps =((SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map)).getMap();
}
@Override
public void onPause() {
super.onPause();
}
@Override
public void onResume() {
super.onResume();
if (mMaps == null) {
mMaps = ((SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map)).getMap();
}
getSupportFragmentManager().findFragmentById(R.id.map).onResume();
}
}
BaseActivity:
public abstract class BaseActivity extends FragmentActivity implements
LocationListener,
GooglePlayServicesClient.ConnectionCallbacks,
GooglePlayServicesClient.OnConnectionFailedListener {
// A request to connect to Location Services
private LocationRequest mLocationRequest;
// Stores the current instantiation of the location client in this object
private LocationClient mLocationClient;
// Handle to SharedPreferences for this app
SharedPreferences mPrefs;
// Handle to a SharedPreferences editor
SharedPreferences.Editor mEditor;
boolean mUpdatesRequested = false;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Create a new global location parameters object
mLocationRequest = LocationRequest.create();
mLocationRequest.setInterval(LocationUtils.UPDATE_INTERVAL_IN_MILLISECONDS);
// Use high accuracy
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
// Set the interval ceiling to one minute
mLocationRequest.setFastestInterval(LocationUtils.FAST_INTERVAL_CEILING_IN_MILLISECONDS);
// Note that location updates are off until the user turns them on
mUpdatesRequested = false;
// Open Shared Preferences
mPrefs = getSharedPreferences(LocationUtils.SHARED_PREFERENCES, Context.MODE_PRIVATE);
// Get an editor
mEditor = mPrefs.edit();
/*
* Create a new location client, using the enclosing class to
* handle callbacks.
*/
mLocationClient = new LocationClient(this, this, this);
}
@Override
public void onStop() {
// If the client is connected
if (mLocationClient.isConnected()) {
stopPeriodicUpdates();
}
// After disconnect() is called, the client is considered "dead".
mLocationClient.disconnect();
super.onStop();
}
@Override
public void onPause() {
// Save the current setting for updates
mEditor.putBoolean(LocationUtils.KEY_UPDATES_REQUESTED, mUpdatesRequested);
mEditor.commit();
super.onPause();
}
@Override
public void onStart() {
super.onStart();
/*
* Connect the client. Don't re-start any requests here;
* instead, wait for onResume()
*/
mLocationClient.connect();
}
@Override
public void onResume() {
super.onResume();
// If the app already has a setting for getting location updates, get it
if (mPrefs.contains(LocationUtils.KEY_UPDATES_REQUESTED)) {
mUpdatesRequested = mPrefs.getBoolean(LocationUtils.KEY_UPDATES_REQUESTED, false);
// Otherwise, turn off location updates until requested
} else {
mEditor.putBoolean(LocationUtils.KEY_UPDATES_REQUESTED, false);
mEditor.commit();
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
// Choose what to do based on the request code
switch (requestCode) {
// If the request code matches the code sent in onConnectionFailed
case LocationUtils.CONNECTION_FAILURE_RESOLUTION_REQUEST :
switch (resultCode) {
// If Google Play services resolved the problem
case Activity.RESULT_OK:
break;
// If any other result was returned by Google Play services
default:
// Log the result
break;
}
// If any other request code was received
default:
// Report that this Activity received an unknown requestCode
Log.d(LocationUtils.APPTAG,
getString(R.string.unknown_activity_request_code, requestCode));
break;
}
}
private boolean servicesConnected() {
// Check that Google Play services is available
int resultCode =
GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
// If Google Play services is available
if (ConnectionResult.SUCCESS == resultCode) {
// In debug mode, log the status
Log.d(LocationUtils.APPTAG, getString(R.string.play_services_available));
// Continue
return true;
// Google Play services was not available for some reason
} else {
// Display an error dialog
Dialog dialog = GooglePlayServicesUtil.getErrorDialog(resultCode, this, 0);
if (dialog != null) {
ErrorDialogFragment errorFragment = new ErrorDialogFragment();
errorFragment.setDialog(dialog);
// errorFragment.show(getSupportFragmentManager(), LocationUtils.APPTAG);
}
return false;
}
}
public void getAddress(View v) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD && !Geocoder.isPresent()) {
// No geocoder is present. Issue an error message
Toast.makeText(this, R.string.no_geocoder_available, Toast.LENGTH_LONG).show();
return;
}
if (servicesConnected()) {
// Get the current location
Location currentLocation = mLocationClient.getLastLocation();
// Start the background task
(new GetAddressTask(this)).execute(currentLocation);
}
}
public void startUpdates(View v) {
mUpdatesRequested = true;
if (servicesConnected()) {
startPeriodicUpdates();
}
}
public void stopUpdates(View v) {
mUpdatesRequested = false;
if (servicesConnected()) {
stopPeriodicUpdates();
}
}
@Override
public void onConnected(Bundle bundle) {
if (mUpdatesRequested) {
startPeriodicUpdates();
}
EventBus.getDefault().post(new EventMessage().new LocationServicesConnected());
}
@Override
public void onDisconnected() {
}
@Override
public void onConnectionFailed(ConnectionResult connectionResult) {
if (connectionResult.hasResolution()) {
try {
// Start an Activity that tries to resolve the error
connectionResult.startResolutionForResult(
this,
LocationUtils.CONNECTION_FAILURE_RESOLUTION_REQUEST);
} catch (IntentSender.SendIntentException e) {
e.printStackTrace();
}
} else {
// If no resolution is available, display a dialog to the user with the error.
showErrorDialog(connectionResult.getErrorCode());
}
}
@Override
public void onLocationChanged(Location location) {
EventBus.getDefault().post(new EventMessage().new LocationChangedEvent(location));
}
private void startPeriodicUpdates() {
mLocationClient.requestLocationUpdates(mLocationRequest, this);
}
private void stopPeriodicUpdates() {
mLocationClient.removeLocationUpdates(this);
}
protected class GetAddressTask extends AsyncTask<Location, Void, String> {
// Store the context passed to the AsyncTask when the system instantiates it.
Context localContext;
// Constructor called by the system to instantiate the task
public GetAddressTask(Context context) {
// Required by the semantics of AsyncTask
super();
// Set a Context for the background task
localContext = context;
}
@Override
protected String doInBackground(Location... params) {
Geocoder geocoder = new Geocoder(localContext, Locale.getDefault());
// Get the current location from the input parameter list
Location location = params[0];
// Create a list to contain the result address
List<Address> addresses = null;
// Try to get an address for the current location. Catch IO or network problems.
try {
/*
* Call the synchronous getFromLocation() method with the latitude and
* longitude of the current location. Return at most 1 address.
*/
addresses = geocoder.getFromLocation(location.getLatitude(),
location.getLongitude(), 1
);
// Catch network or other I/O problems.
} catch (IOException exception1) {
// Log an error and return an error message
Log.e(LocationUtils.APPTAG, getString(R.string.IO_Exception_getFromLocation));
// print the stack trace
exception1.printStackTrace();
// Return an error message
return (getString(R.string.IO_Exception_getFromLocation));
// Catch incorrect latitude or longitude values
} catch (IllegalArgumentException exception2) {
// Construct a message containing the invalid arguments
String errorString = getString(
R.string.illegal_argument_exception,
location.getLatitude(),
location.getLongitude()
);
// Log the error and print the stack trace
Log.e(LocationUtils.APPTAG, errorString);
exception2.printStackTrace();
//
return errorString;
}
// If the reverse geocode returned an address
if (addresses != null && addresses.size() > 0) {
// Get the first address
Address address = addresses.get(0);
// Format the first line of address
String addressText = getString(R.string.address_output_string,
// If there's a street address, add it
address.getMaxAddressLineIndex() > 0 ?
address.getAddressLine(0) : "",
// Locality is usually a city
address.getLocality(),
// The country of the address
address.getCountryName()
);
// Return the text
return addressText;
// If there aren't any addresses, post a message
} else {
return getString(R.string.no_address_found);
}
}
/**
* A method that's called once doInBackground() completes. Set the text of the
* UI element that displays the address. This method runs on the UI thread.
*/
@Override
protected void onPostExecute(String address) {
}
}
/**
* Show a dialog returned by Google Play services for the
* connection error code
*
* @param errorCode An error code returned from onConnectionFailed
*/
private void showErrorDialog(int errorCode) {
// Get the error dialog from Google Play services
Dialog errorDialog = GooglePlayServicesUtil.getErrorDialog(
errorCode,
this,
LocationUtils.CONNECTION_FAILURE_RESOLUTION_REQUEST);
// If Google Play services can provide an error dialog
if (errorDialog != null) {
// Create a new DialogFragment in which to show the error dialog
ErrorDialogFragment errorFragment = new ErrorDialogFragment();
// Set the dialog in the DialogFragment
errorFragment.setDialog(errorDialog);
// Show the error dialog in the DialogFragment
// errorFragment.show(getSupportFragmentManager(), LocationUtils.APPTAG);
}
}
/**
* Define a DialogFragment to display the error dialog generated in
* showErrorDialog.
*/
public static class ErrorDialogFragment extends DialogFragment {
// Global field to contain the error dialog
private Dialog mDialog;
/**
* Default constructor. Sets the dialog field to null
*/
public ErrorDialogFragment() {
super();
mDialog = null;
}
/**
* Set the dialog to display
*
* @param dialog An error dialog
*/
public void setDialog(Dialog dialog) {
mDialog = dialog;
}
/*
* This method must return a Dialog to the DialogFragment.
*/
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
return mDialog;
}
}
}
答案 0 :(得分:3)
我在文件manifest.xml上禁用硬件加速,我的应用程序在第二次加载时不再显示黑色地图。我在模拟器中尝试。
<application android:hardwareAccelerated="false">
...
</application
来自这篇文章:http://developer.android.com/guide/topics/graphics/hardware-accel.html
答案 1 :(得分:0)
有点晚了但是,我发现WebViews(甚至在其他片段上)有时会“崩溃”GL引擎或导致MapView中出现黑屏的东西。我在LogCat中找到了这个:
09-30 10:58:17.765: E/libEGL(29805): call to OpenGL ES API with no current context (logged once per thread)
09-30 10:58:17.765: W/Adreno200-EGL(29805): <qeglDrvAPI_eglSwapBuffers:3421>: EGL_BAD_CONTEXT
09-30 10:58:17.765: W/HardwareRenderer(29805): EGL error: EGL_BAD_CONTEXT
09-30 10:58:17.775: W/HardwareRenderer(29805): Mountain View, we've had a problem here.
切换回软件渲染。 要在分离WebView时修复此问题,我在片段中调用destroy函数:
@Override
public void onDestroyView() {
if (webView != null) {
webView.destroy();
webView = null;
}
super.onDestroyView();
}
也许它会给你一个解决这个问题的方向。