我在一个活动中有此mapbox地图,当我进入包含mapview的活动时,一切都很好,当我按回去几秒钟后,它崩溃了...我不确定是什么造成这种情况,但我认为是位置图层引擎或onDestroy()方法上,还是mapView生命周期中缺少某些内容?这是我的代码
我已经尝试过deactivate(),removeLocationUpdates()....我不知道是什么导致了它。我非常感谢您的帮助/建议,顺便说一句,我正在使用mapbox sdk 6.8.1 ...操作系统:Oreo 8.1
public class display_store_locations_nearby extends AppCompatActivity
implements OnMapReadyCallback,LocationEngineListener,
PermissionsListener, LocationRecyclerViewAdapter.ClickListener {
private MapView mapView;
private MapboxMap map;
private PermissionsManager permissionsManager;
private LocationEngine locationEngine;
private LocationLayerPlugin locationLayerPlugin;
private Location originLocation;
private GoogleApiClient googleApiClient;
private MapboxDirections directionsApiClient;
private DirectionsRoute currentRoute;
final static int REQUEST_LOCATION = 199;
private static final int CAMERA_MOVEMENT_SPEED_IN_MILSECS = 1200;
private FeatureCollection featureCollection;
protected static final String TAG = "LocationOnOff";
private ArrayList<IndividualLocation> listOfIndividualLocations;
private LocationRecyclerViewAdapter styleRvAdapter;
private RecyclerView locationsRecyclerView;
public double lat,lng;
public ConstraintLayout constraintLayout;
double userLat,userLng;
private LatLng USER_LOCATION;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Mapbox.getInstance(this, getString(R.string.access_token));
setContentView(R.layout.activity_display_store_locations_nearby);
mapView = findViewById(R.id.mapView);
constraintLayout = findViewById(R.id.constaintLayoutMap);
mapView.onCreate(savedInstanceState);
if(deviceHasInternetConnection()) {
getLocationPermission();
}
else
{
Toast.makeText(getApplicationContext(), R.string.no_internet_message, Toast.LENGTH_SHORT).show();
finish();
}
}
@Override
public void onMapReady(MapboxMap mapboxMap) {
map = mapboxMap;
enableLocation();
showBuildingExtrusions();
mapboxMap.setMinZoomPreference(12);
listOfIndividualLocations = new ArrayList<>();
try {
getFeatureCollectionFromJson();
Icon shopsIcon = IconFactory.getInstance(display_store_locations_nearby.this).fromResource(R.drawable.monitor);
List<Feature> featureList = featureCollection.features();
for (int x = 0; x < featureList.size(); x++) {
Feature singleLocation = featureList.get(x);
// Get the single location's String properties to place in its map marker
String singleLocationName = singleLocation.getStringProperty("Name");
String singleLocationAddress = singleLocation.getStringProperty("Address");
String singleLocationPhoneNum = singleLocation.getStringProperty("Number");
String singleLocationWorkHours = singleLocation.getStringProperty("Work Hours");
// Get the single location's LatLng coordinates
Double stringLong = ((Point) singleLocation.geometry()).coordinates().get(0);
Double stringLat = ((Point) singleLocation.geometry()).coordinates().get(1);
// Create a new LatLng object with the Position object created above
LatLng singleLocationLatLng = new LatLng(stringLat, stringLong);
listOfIndividualLocations.add(new IndividualLocation(
singleLocationName,
singleLocationAddress,
singleLocationPhoneNum,
singleLocationLatLng,
singleLocationWorkHours
));
map.addMarker(new MarkerOptions()
.position(singleLocationLatLng)
.title(singleLocationName)
.icon(shopsIcon));
}
setUpMarkerClickListener();
setUpRecyclerViewOfLocationCards();
} catch (Exception exception) {
// Log.e("MapActivity", "onCreate: " + exception);
Toast.makeText(this, R.string.failure_to_load_file, Toast.LENGTH_LONG).show();
}
}
public void getInformationFromDirectionsApi(double destinationLatCoordinate, double destinationLongCoordinate,
final boolean fromMarkerClick, @Nullable final Integer listIndex,double lt,double ln) {
boolean hasInternet = deviceHasInternetConnection();
if(hasInternet) {
// Set up origin and destination coordinates for the call to the Mapbox Directions API
Point mockCurrentLocation = Point.fromLngLat(ln, lt);
//Toast.makeText(getApplicationContext(), lt +"yes",Toast.LENGTH_SHORT).show();
Point destinationMarker = Point.fromLngLat(destinationLongCoordinate, destinationLatCoordinate);
// Initialize the directionsApiClient object for eventually drawing a navigation route on the map
directionsApiClient = MapboxDirections.builder()
.origin(mockCurrentLocation)
.destination(destinationMarker)
.overview(DirectionsCriteria.OVERVIEW_FULL)
.profile(DirectionsCriteria.PROFILE_DRIVING)
.accessToken(getString(R.string.access_token))
.build();
directionsApiClient.enqueueCall(new Callback<DirectionsResponse>() {
@Override
public void onResponse(Call<DirectionsResponse> call, Response<DirectionsResponse> response) {
// Check that the response isn't null and that the response has a route
if (response.body() == null) {
Log.e("MapActivity", "No routes found, make sure you set the right user and access token.");
//Toast.makeText(getApplicationContext(), "205", Toast.LENGTH_SHORT).show();
} else if (response.body().routes().size() < 1) {
Log.e("MapActivity", "No routes found");
//Toast.makeText(getApplicationContext(), "208", Toast.LENGTH_SHORT).show();
} else {
if (fromMarkerClick) {
// Retrieve and draw the navigation route on the map
currentRoute = response.body().routes().get(0);
drawNavigationPolylineRoute(currentRoute);
} else {
// Use Mapbox Turf helper method to convert meters to miles and then format the mileage number
DecimalFormat df = new DecimalFormat("#.#");
String finalConvertedFormattedDistance = String.valueOf(df.format(TurfConversion.convertLength(
response.body().routes().get(0).distance(), "meters", "miles")));
// Set the distance for each location object in the list of locations
if (listIndex != null) {
listOfIndividualLocations.get(listIndex).setDistance(finalConvertedFormattedDistance);
// Refresh the displayed recyclerview when the location's distance is set
styleRvAdapter.notifyDataSetChanged();
}
}
}
}
@Override
public void onFailure(Call<DirectionsResponse> call, Throwable throwable) {
Toast.makeText(display_store_locations_nearby.this, R.string.failure_to_retrieve, Toast.LENGTH_LONG).show();
}
});
}
else
{
Toast.makeText(display_store_locations_nearby.this, R.string.no_internet_message, Toast.LENGTH_LONG).show();
}
}
private void drawNavigationPolylineRoute(DirectionsRoute route) {
// Check for and remove a previously-drawn navigation route polyline before drawing the new one
if (map.getPolylines().size() > 0) {
map.removePolyline(map.getPolylines().get(0));
}
// Convert LineString coordinates into a LatLng[]
LineString lineString = LineString.fromPolyline(route.geometry(), PRECISION_6);
List<Point> coordinates = lineString.coordinates();
LatLng[] polylineDirectionsPoints = new LatLng[coordinates.size()];
for (int i = 0; i < coordinates.size(); i++) {
polylineDirectionsPoints[i] = new LatLng(
coordinates.get(i).latitude(),
coordinates.get(i).longitude());
}
// Draw the navigation route polyline on to the map
map.addPolyline(new PolylineOptions()
.add(polylineDirectionsPoints)
.color(R.color.navigationLine)
.width(9));
}
private void getFeatureCollectionFromJson() throws IOException {
try {
// Use fromJson() method to convert the GeoJSON file into a usable FeatureCollection object
featureCollection = FeatureCollection.fromJson(loadGeoJsonFromAsset("ComputerStores.geojson"));
} catch (Exception exception) {
Log.e("MapActivity", "getFeatureCollectionFromJson: " + exception);
}
}
private void setUpRecyclerViewOfLocationCards() {
// Initialize the recyclerview of location cards and a custom class for automatic card scrolling
locationsRecyclerView = findViewById(R.id.map_recycler_view);
locationsRecyclerView.setHasFixedSize(true);
locationsRecyclerView.setLayoutManager(new LinearLayoutManagerWithSmoothScroller(this));
styleRvAdapter = new LocationRecyclerViewAdapter(listOfIndividualLocations,
getApplicationContext(), this);
locationsRecyclerView.setAdapter(styleRvAdapter);
SnapHelper snapHelper = new LinearSnapHelper();
snapHelper.attachToRecyclerView(locationsRecyclerView);
}
private void setUpMarkerClickListener() {
map.setOnMarkerClickListener(new MapboxMap.OnMarkerClickListener() {
@Override
public boolean onMarkerClick(@NonNull Marker marker) {
// Get the position of the selected marker
LatLng positionOfSelectedMarker = marker.getPosition();
// Check that the selected marker isn't the mock device location marker
if (!marker.getPosition().equals(USER_LOCATION)) {
for (int x = 0; x < map.getMarkers().size(); x++) {
if (map.getMarkers().get(x).getPosition() == positionOfSelectedMarker) {
// Scroll the recyclerview to the selected marker's card. It's "x-1" below because
// the mock device location marker is part of the marker list but doesn't have its own card
// in the actual recyclerview.
//Toast.makeText(getApplicationContext(), ""+USER_LOCATION, Toast.LENGTH_SHORT).show();
locationsRecyclerView.smoothScrollToPosition(x);
}
}
adjustMarkerSelectStateIcons(marker);
}
// Return true so that the selected marker's info window doesn't pop up
return true;
}
});
}
@SuppressWarnings("MissingPermission")
private void initLocationEngine() {
locationEngine = new LocationEngineProvider(this).obtainBestLocationEngineAvailable();
locationEngine.setPriority(LocationEnginePriority.HIGH_ACCURACY);
locationEngine.activate();
Location lastLocation = locationEngine.getLastLocation();
if (lastLocation != null) {
originLocation = lastLocation;
setCameraPosition(lastLocation);
} else {
locationEngine.addLocationEngineListener(this);
}
}
@SuppressWarnings("MissingPermission")
private void initLocationLayer() {
locationLayerPlugin = new LocationLayerPlugin(mapView, map, locationEngine);
locationLayerPlugin.setLocationLayerEnabled(true);
locationLayerPlugin.setCameraMode(CameraMode.TRACKING);
locationLayerPlugin.setRenderMode(RenderMode.NORMAL);
}
@Override
@SuppressWarnings("MissingPermission")
public void onConnected() {
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return;
}
locationEngine.requestLocationUpdates();
}
public void setCameraPosition(Location location) {
map.animateCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(location.getLatitude(), location.getLongitude()), 15.0));
lat = location.getLatitude();
lng = location.getLongitude();
USER_LOCATION = new LatLng(lat,lng);
// Call getInformationFromDirectionsApi() to eventually display the location's
// distance from mocked device location
List<Feature> featureList2 = featureCollection.features();
for (int x = 0; x < featureList2.size(); x++) {
Feature singleLocation2 = featureList2.get(x);
Double stringLong2 = ((Point) singleLocation2.geometry()).coordinates().get(0);
Double stringLat2 = ((Point) singleLocation2.geometry()).coordinates().get(1);
// Create a new LatLng object with the Position object created above
LatLng singleLocationLatLng = new LatLng(stringLat2, stringLong2);
getInformationFromDirectionsApi(singleLocationLatLng.getLatitude(),
singleLocationLatLng.getLongitude(), false, x,lat,lng);
}
setLat(lat);
setLng(lng);
//Toast.makeText(getApplicationContext(), deviceLocation.getLat()+"YES"+latlng[0], Toast.LENGTH_LONG).show();
/*Icon userIcon = IconFactory.getInstance(display_store_locations_nearby.this).fromResource(R.drawable.figureperson);
map.addMarker(new MarkerOptions()
.position(USER_LOCATION)
.title(getString(R.string.mock_location_title))
.icon(userIcon));*/
}
@Override
public void onLocationChanged(Location location) {
if (location != null) {
originLocation = location;
setCameraPosition(location);
}
}
@Override
public void onExplanationNeeded(List<String> permissionsToExplain) {
}
@Override
public void onPermissionResult(boolean granted) {
if (granted) {
enableLocation();
}
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
permissionsManager.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
@SuppressWarnings("MissingPermission")
@Override
public void onStart() {
super.onStart();
if (locationEngine != null) {
locationEngine.requestLocationUpdates();
}
mapView.onStart();
}
@Override
public void onResume() {
if(!deviceHasInternetConnection())
{
Toast.makeText(getApplicationContext(), R.string.no_internet_message, Toast.LENGTH_SHORT).show();
finish();
}
else {
super.onResume();
mapView.onResume();
}
}
@Override
public void onPause() {
super.onPause();
mapView.onPause();
}
@Override
public void onStop() {
super.onStop();
mapView.onStop();
}
@Override
public void onLowMemory() {
super.onLowMemory();
if (mapView != null && !mapView.isDestroyed()) {
mapView.onLowMemory();
}
}
@Override
public void onDestroy() {
super.onDestroy();
if (locationEngine!=null)
{
locationEngine.removeLocationUpdates();
locationEngine.deactivate();
}
mapView.onDestroy();
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
mapView.onSaveInstanceState(outState);
}
private String loadGeoJsonFromAsset(String filename) {
try {
// Load the GeoJSON file from the local asset folder
InputStream is = getAssets().open(filename);
int size = is.available();
byte[] buffer = new byte[size];
is.read(buffer);
is.close();
return new String(buffer, "UTF-8");
} catch (Exception exception) {
Log.e("MapActivity", "Exception Loading GeoJSON: " + exception.toString());
exception.printStackTrace();
return null;
}
}
private void showBuildingExtrusions() {
final String BUILDING_EXTRUSION_COLOR = "#c4dbed";
final float BUILDING_EXTRUSION_OPACITY = .2f;
// Use the Mapbox building plugin to display and customize the opacity/color of building extrusions
BuildingPlugin buildingPlugin = new BuildingPlugin(mapView, map);
buildingPlugin.setVisibility(true);
buildingPlugin.setOpacity(BUILDING_EXTRUSION_OPACITY);
buildingPlugin.setColor(Color.parseColor(BUILDING_EXTRUSION_COLOR));
}
private void enableLocation() {
//Requesting location services from the user, if granted already proceed to if condition else ask user to grant for permission to access
// current location
if (PermissionsManager.areLocationPermissionsGranted(this)) {
initLocationEngine();
initLocationLayer();
} else {
permissionsManager = new PermissionsManager(this);
permissionsManager.requestLocationPermissions(this);
}
}
private void getLocationPermission() {
this.setFinishOnTouchOutside(true);
// Todo Location Already on ...start
final LocationManager manager = (LocationManager) display_store_locations_nearby.this.getSystemService(Context.LOCATION_SERVICE);
if (manager.isProviderEnabled(LocationManager.GPS_PROVIDER) && hasGPSDevice(display_store_locations_nearby.this)) {
//Toast.makeText(display_store_locations_nearby.this,"Gps already enabled",Toast.LENGTH_SHORT).show();
mapView.getMapAsync(this);
}
// Todo Location Already on ...end
if (!hasGPSDevice(display_store_locations_nearby.this)) {
// Toast.makeText(display_store_locations_nearby.this,"Gps not Supported",Toast.LENGTH_SHORT).show();
}
if (!manager.isProviderEnabled(LocationManager.GPS_PROVIDER) && hasGPSDevice(display_store_locations_nearby.this)) {
// Log.e("keshav","Gps already enabled");
Toast.makeText(display_store_locations_nearby.this, "GPS not enabled", Toast.LENGTH_SHORT).show();
enableLoc();
} else {
// Log.e("keshav","Gps already enabled");
//Toast.makeText(display_store_locations_nearby.this,"Gps already enabled",Toast.LENGTH_SHORT).show();
}
}
private boolean deviceHasInternetConnection() {
ConnectivityManager connectivityManager = (ConnectivityManager)
getApplicationContext().getApplicationContext().getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo activeNetwork = connectivityManager.getActiveNetworkInfo();
return activeNetwork != null && activeNetwork.isConnected();
}
private boolean hasGPSDevice(Context context) {
final LocationManager mgr = (LocationManager) context
.getSystemService(Context.LOCATION_SERVICE);
if (mgr == null)
return false;
final List<String> providers = mgr.getAllProviders();
if (providers == null)
return false;
return providers.contains(LocationManager.GPS_PROVIDER);
}
private void enableLoc() {
if (googleApiClient == null) {
googleApiClient = new GoogleApiClient.Builder(display_store_locations_nearby.this)
.addApi(LocationServices.API)
.addConnectionCallbacks(new GoogleApiClient.ConnectionCallbacks() {
@Override
public void onConnected(Bundle bundle) {
}
@Override
public void onConnectionSuspended(int i) {
googleApiClient.connect();
}
})
.addOnConnectionFailedListener(new GoogleApiClient.OnConnectionFailedListener() {
@Override
public void onConnectionFailed(ConnectionResult connectionResult) {
// Log.d("Location error","Location error " + connectionResult.getErrorCode());
}
}).build();
googleApiClient.connect();
LocationRequest locationRequest = LocationRequest.create();
locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
locationRequest.setInterval(30 * 1000);
locationRequest.setFastestInterval(5 * 1000);
LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder()
.addLocationRequest(locationRequest);
builder.setAlwaysShow(true);
PendingResult<LocationSettingsResult> result =
LocationServices.SettingsApi.checkLocationSettings(googleApiClient, builder.build());
result.setResultCallback(new ResultCallback<LocationSettingsResult>() {
@Override
public void onResult(LocationSettingsResult result) {
final Status status = result.getStatus();
switch (status.getStatusCode()) {
case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:
try {
// Show the dialog by calling startResolutionForResult(),
// and check the result in onActivityResult().
status.startResolutionForResult(display_store_locations_nearby.this, REQUEST_LOCATION);
finish();
} catch (IntentSender.SendIntentException e) {
// Ignore the error.
}
break;
}
}
});
}
}
private void repositionMapCamera(LatLng newTarget) {
CameraPosition newCameraPosition = new CameraPosition.Builder()
.zoom(16.0)
.target(newTarget)
.build();
map.animateCamera(CameraUpdateFactory.newCameraPosition(newCameraPosition), CAMERA_MOVEMENT_SPEED_IN_MILSECS);
}
private void adjustMarkerSelectStateIcons(Marker marker) {
double tempLat = getLat();
double tempLng = getLng();
// Set all of the markers' icons to the unselected marker icon
Icon compShopsIcon = IconFactory.getInstance(display_store_locations_nearby.this).fromResource(R.drawable.monitor);
for (Marker singleMarker : map.getMarkers()) {
if (!singleMarker.getTitle().equals(getString(R.string.mock_location_title))) {
singleMarker.setIcon(compShopsIcon);
}
}
Icon tempUserIcon = IconFactory.getInstance(display_store_locations_nearby.this).fromResource(R.drawable.figureperson);
Icon selectedMode_icon = IconFactory.getInstance(display_store_locations_nearby.this).fromResource(R.drawable.monitor_selected);
// Change the selected marker's icon to a selected state marker except if the mock device location marker is selected
if (!marker.getIcon().equals(tempUserIcon)) {
marker.setIcon(selectedMode_icon);
}
// Get the directionsApiClient route to the selected marker except if the mock device location marker is selected
if (!marker.getIcon().equals(tempUserIcon)) {
// Check for an internet connection before making the call to Mapbox Directions API
if (deviceHasInternetConnection()) {
// Start the call to the Mapbox Directions API
getInformationFromDirectionsApi(marker.getPosition().getLatitude(),
marker.getPosition().getLongitude(), true, null,tempLat,tempLng);
} else {
Toast.makeText(this, R.string.no_internet_message, Toast.LENGTH_LONG).show();
}
}
}
@Override
public void onDestroyView() {
}
@Override
public void onItemClick(int position) {
double newLat = getLat();
double newLng = getLng();
IndividualLocation selectedLocation = listOfIndividualLocations.get(position);
// Retrieve and change the selected card's marker to the selected marker icon
Marker markerTiedToSelectedCard = map.getMarkers().get(position);
adjustMarkerSelectStateIcons(markerTiedToSelectedCard);
//Toast.makeText(getApplicationContext(), newLat+"", Toast.LENGTH_SHORT).show();
// Reposition the map camera target to the selected marker
LatLng selectedLocationLatLng = selectedLocation.getLocation();
repositionMapCamera(selectedLocationLatLng);
// Check for an internet connection before making the call to Mapbox Directions API
if (deviceHasInternetConnection()) {
// Start call to the Mapbox Directions API
getInformationFromDirectionsApi(selectedLocationLatLng.getLatitude(),
selectedLocationLatLng.getLongitude(), true, null,newLat,newLng);
} else {
Toast.makeText(this, R.string.no_internet_message, Toast.LENGTH_LONG).show();
}
}
@Override
public void OnBackPressed() {
finish();
}
public void setLat(double lat)
{
userLat = lat;
}
public void setLng(double lng)
{
userLng = lng;
}
public double getLat()
{
return userLat;
}
public double getLng()
{
return userLng;
}
}