问题
I am using a plasio turbo x to test my osmdroid sample. I am also testing using a moto g. In moto g the map rotation which is according to the compass head up is working fine, but in plasio one the compass starts to spin and map also spins, they don't get stable. You can see the logcat here(it is very big, stackoverflow not letting me add it here).
Following is my class in which I have used compass:
public class MainActivity extends FragmentActivity implements LocationListener, IOrientationConsumer,MapEventsReceiver {
private CompassOverlay mCompassOverlay = null;
private MyLocationNewOverlay mLocationOverlay;
IOrientationProvider compass = null;
int deviceOrientation = 0;
MapView mMapView;
float gpsspeed;
float gpsbearing;
float lat = 0;
float lon = 0;
float alt = 0;
long timeOfFix = 0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Intent intent = getIntent();
final double lat1 = Double.parseDouble(intent.getStringExtra("lat1"));
final double long1 = Double.parseDouble(intent.getStringExtra("long1"));
final double lat2 = 25.633;
final double long2 = 71.094;
//important! set your user agent to prevent getting banned from the osm servers
org.osmdroid.tileprovider.constants.OpenStreetMapTileProviderConstants.setUserAgentValue(BuildConfig.APPLICATION_ID);
mMapView = (MapView) findViewById(R.id.map);
mMapView.setTileSource(TileSourceFactory.MAPNIK);
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
mCompassOverlay = new CompassOverlay(this, new InternalCompassOrientationProvider(this),
mMapView);
mCompassOverlay.enableCompass();
mMapView.getOverlays().add(this.mCompassOverlay);
addOverlays();
GeoPoint startPoint = new GeoPoint(lat1, long1);
IMapController mapController = mMapView.getController();
mapController.setZoom(9);
mapController.setCenter(startPoint);
Marker startMarker = new Marker(mMapView);
startMarker.setPosition(startPoint);
startMarker.setAnchor(Marker.ANCHOR_CENTER, Marker.ANCHOR_BOTTOM);
mMapView.getOverlays().add(startMarker);
RoadManager roadManager = new OSRMRoadManager(this);
ArrayList<GeoPoint> waypoints = new ArrayList<GeoPoint>();
waypoints.add(startPoint);
GeoPoint endPoint = new GeoPoint(lat2, long2);
Marker endMarker = new Marker(mMapView);
endMarker.setAnchor(Marker.ANCHOR_CENTER, Marker.ANCHOR_BOTTOM);
mMapView.getOverlays().add(endMarker);
waypoints.add(endPoint);
Road road = roadManager.getRoad(waypoints);
Polyline roadOverlay = RoadManager.buildRoadOverlay(road);
mMapView.getOverlays().add(roadOverlay);
mMapView.invalidate();
}
public void addOverlays() {
mLocationOverlay = new MyLocationNewOverlay(mMapView);
mLocationOverlay.setEnableAutoStop(false);
mLocationOverlay.enableFollowLocation();
mLocationOverlay.enableMyLocation();
this.mMapView.getOverlayManager().add(mLocationOverlay);
mMapView.setBuiltInZoomControls(true);
mMapView.setMultiTouchControls(true);
mMapView.setTilesScaledToDpi(true);
}
@Override
protected void onResume() {
super.onResume();
//lock the device in current screen orientation
int orientation;
int rotation = ((WindowManager) this.getSystemService(
Context.WINDOW_SERVICE)).getDefaultDisplay().getRotation();
switch (rotation) {
case Surface.ROTATION_0:
orientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
this.deviceOrientation = 0;
break;
case Surface.ROTATION_90:
this.deviceOrientation = 90;
orientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
break;
case Surface.ROTATION_180:
this.deviceOrientation = 180;
orientation = ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT;
break;
default:
this.deviceOrientation = 270;
orientation = ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE;
break;
}
this.setRequestedOrientation(orientation);
LocationManager lm = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
try {
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return;
}
lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, (LocationListener) this);
lm.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, (LocationListener) this);
} catch (Exception ex) {
}
compass = new InternalCompassOrientationProvider(this);
compass.startOrientationProvider(this);
mMapView.getController().zoomTo(14);
}
@Override
public void onLocationChanged(Location location) {
if (mMapView == null)
return;
//after the first fix, schedule the task to change the icon
//mMapView.getController().setCenter(new GeoPoint(location.getLatitude(), location.getLongitude()));
mMapView.invalidate();
gpsbearing = location.getBearing();
gpsspeed = location.getSpeed();
lat = (float) location.getLatitude();
lon = (float) location.getLongitude();
alt = (float) location.getAltitude(); //meters
timeOfFix = location.getTime();
}
@Override
public void onStatusChanged(String s, int i, Bundle bundle) {
}
@Override
public void onProviderEnabled(String s) {
}
@Override
public void onProviderDisabled(String s) {
}
@Override
protected void onPause() {
super.onPause();
compass.stopOrientationProvider();
LocationManager lm = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
try {
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return;
}
lm.removeUpdates(this);
} catch (Exception ex) {
}
//unlock the orientation
this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
}
Float trueNorth = 0f;
@Override
public void onOrientationChanged(final float orientationToMagneticNorth, IOrientationProvider source) {
GeomagneticField gf = new GeomagneticField(lat, lon, alt, timeOfFix);
trueNorth = orientationToMagneticNorth + gf.getDeclination();
gf=null;
synchronized (trueNorth) {
if (trueNorth > 360.0f) {
trueNorth = trueNorth - 360.0f;
}
//use gps bearing instead of the compass
if (gpsspeed > 0.01f) {
float t = (360 - gpsbearing - this.deviceOrientation);
if (t < 0) {
t += 360;
}
if (t > 360) {
t -= 360;
}
mMapView.setMapOrientation(t);
} else {
//this part adjusts the desired map rotation based on device orientation and compass heading
float t = (360 - trueNorth - this.deviceOrientation);
if (t < 0) {
t += 360;
}
if (t > 360) {
t -= 360;
}
mMapView.setMapOrientation(t);
}
this.runOnUiThread(new Runnable() {
@Override
public void run() {
if (this!=null ) {
Toast.makeText(MainActivity.this, "GPS Speed: " + gpsspeed + "m/s GPS Bearing: " + gpsbearing +
"\nDevice Orientation: " + (int) deviceOrientation + " Compass heading: " + (int) orientationToMagneticNorth + "\n" +
"True north: " + trueNorth.intValue() + " Map Orientation: " + (int) mMapView.getMapOrientation() + "\n", Toast.LENGTH_SHORT).show();
}
}
});
}
}
@Override
public boolean singleTapConfirmedHelper(GeoPoint geoPoint) {
return false;
}
@Override
public boolean longPressHelper(GeoPoint geoPoint) {
return false;
}
}
来源:https://stackoverflow.com/questions/40112165/compass-not-working-properly-in-osmdroid