Orientate the map to fit the current orientation.

This commit is contained in:
Geoffrey POUZET 2018-08-02 16:43:13 +02:00
parent 05f03941da
commit 645f21b4b3
2 changed files with 163 additions and 32 deletions

View File

@ -2,17 +2,19 @@ package fr.chteufleur.mytrackingdog;
import android.Manifest;
import android.content.Context;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
import android.hardware.GeomagneticField;
import android.location.Location;
import android.location.LocationManager;
import android.os.Build;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.support.annotation.RequiresApi;
import android.support.v7.app.AppCompatActivity;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.Surface;
import android.view.WindowManager;
import android.widget.Toast;
@ -21,21 +23,32 @@ import org.osmdroid.config.Configuration;
import org.osmdroid.tileprovider.tilesource.TileSourceFactory;
import org.osmdroid.util.GeoPoint;
import org.osmdroid.views.MapView;
import org.osmdroid.views.overlay.compass.IOrientationConsumer;
import org.osmdroid.views.overlay.compass.IOrientationProvider;
import org.osmdroid.views.overlay.compass.InternalCompassOrientationProvider;
import org.osmdroid.views.overlay.mylocation.GpsMyLocationProvider;
import org.osmdroid.views.overlay.mylocation.MyLocationNewOverlay;
import java.util.Observable;
import java.util.Observer;
import fr.chteufleur.mytrackingdog.services.IServiceGps;
import fr.chteufleur.mytrackingdog.services.ServiceGps;
public class MainActivity extends AppCompatActivity {
public class MainActivity extends AppCompatActivity implements IOrientationConsumer, Observer {
public static final String TAG = "MainActivity";
private MyLocationNewOverlay mLocationOverlay;
private IOrientationProvider compass = null;
private IServiceGps serviceGps = null;
Context ctx = null;
MapView map = null;
private Context ctx = null;
private MapView map = null;
private Float trueNorth = 0f;
private int deviceOrientation = 0;
private boolean zoomed = false;
private final int REQUEST_CODE_ASK_PERMISSION = 123;
@ -70,20 +83,9 @@ public class MainActivity extends AppCompatActivity {
checkPermissions();
}
if (serviceGps == null) {
serviceGps = new ServiceGps();
}
//load/initialize the osmdroid configuration, this can be done
ctx = getApplicationContext();
Configuration.getInstance().load(ctx, PreferenceManager.getDefaultSharedPreferences(ctx));
//setting this before the layout is inflated is a good idea
//it 'should' ensure that the map has a writable location for the map cache, even without permissions
//if no tiles are displayed, you can try overriding the cache path using Configuration.getInstance().setCachePath
//see also StorageUtils
//note, the load method also sets the HTTP User Agent to your application's package name, abusing osm's tile servers will get you banned based on this string
//inflate and create the map
setContentView(R.layout.main);
// Keep screen ON
@ -102,50 +104,92 @@ public class MainActivity extends AppCompatActivity {
GeoPoint startPoint = new GeoPoint(45.0000, 5.0000);
mapController.setCenter(startPoint);
final DisplayMetrics dm = ctx.getResources().getDisplayMetrics();
// Current position on the map
this.mLocationOverlay = new MyLocationNewOverlay(new GpsMyLocationProvider(ctx), map);
map.getOverlays().add(this.mLocationOverlay);
mLocationOverlay.enableMyLocation();
mLocationOverlay.enableFollowLocation();
mLocationOverlay.setOptionsMenuEnabled(true);
if (serviceGps == null) {
serviceGps = new ServiceGps();
((Observable) serviceGps).addObserver(this);
}
}
@Override
public void onResume(){
super.onResume();
//hack for x86
if (!"Android-x86".equalsIgnoreCase(Build.BRAND)) {
//lock the device in current screen orientation
int orientation;
int rotation = ((WindowManager) 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;
}
setRequestedOrientation(orientation);
}
((ServiceGps) serviceGps).setLocationManager((LocationManager) getSystemService(ctx.LOCATION_SERVICE));
serviceGps.start();
mLocationOverlay.enableFollowLocation();
mLocationOverlay.enableMyLocation();
//this will refresh the osmdroid configuration on resuming.
//if you make changes to the configuration, use
//SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
//Configuration.getInstance().load(this, PreferenceManager.getDefaultSharedPreferences(this));
if (compass == null) {
compass = new InternalCompassOrientationProvider(this);
}
compass.startOrientationProvider(this);
if (map != null) {
map.onResume(); //needed for compass, my location overlays, v6.0.0 and up
map.onResume();
}
}
@Override
public void onPause(){
super.onPause();
pause();
}
mLocationOverlay.disableFollowLocation();
mLocationOverlay.disableMyLocation();
//this will refresh the osmdroid configuration on resuming.
//if you make changes to the configuration, use
//SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
//Configuration.getInstance().save(this, prefs);
private void pause() {
if (compass != null) {
compass.stopOrientationProvider();
compass.destroy();
compass = null;
}
if (mLocationOverlay != null) {
mLocationOverlay.disableFollowLocation();
mLocationOverlay.disableMyLocation();
}
if (map != null) {
map.onPause(); //needed for compass, my location overlays, v6.0.0 and up
map.onPause();
}
}
@Override
public void onBackPressed() {
super.onBackPressed();
pause();
if (serviceGps != null) {
serviceGps.stop();
}
@ -187,4 +231,67 @@ public class MainActivity extends AppCompatActivity {
break;
}
}
@Override
public void onOrientationChanged(float orientationToMagneticNorth, IOrientationProvider source) {
//note, on devices without a compass this never fires...
Location location = ((ServiceGps) serviceGps).getCurrentLocation();
if (location == null) {
return ;
}
float gpsspeed = location.getSpeed();
float lat = (float) location.getLatitude();
float lon = (float) location.getLongitude();
float alt = (float) location.getAltitude();
long timeOfFix = location.getTime();
//only use the compass bit if we aren't moving, since gps is more accurate when we are moving
if (gpsspeed < 0.01) {
GeomagneticField gf = new GeomagneticField(lat, lon, alt, timeOfFix);
trueNorth = orientationToMagneticNorth + gf.getDeclination();
gf = null;
synchronized (trueNorth) {
if (trueNorth > 360.0f) {
trueNorth = trueNorth - 360.0f;
}
float actualHeading = 0f;
//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;
}
actualHeading = t;
//help smooth everything out
t = (int) t;
t = t / 5;
t = (int) t;
t = t * 5;
map.setMapOrientation(t);
if (!zoomed) {
IMapController mapController = map.getController();
mapController.setZoom(20.0);
zoomed = true;
}
}
}
}
@Override
public void update(Observable observable, Object o) {
if (observable == serviceGps) {
if (o instanceof String && (String) o == ServiceGps.NOTIF_NEW_LOCATION) {
float orientation = ((ServiceGps) serviceGps).getOrientation(deviceOrientation);
if (orientation >= 0) {
map.setMapOrientation(orientation);
}
}
}
}
}

View File

@ -6,11 +6,15 @@ import android.location.LocationManager;
import android.os.Bundle;
import android.util.Log;
import java.util.Observable;
import fr.chteufleur.mytrackingdog.MainActivity;
public class ServiceGps implements IServiceGps, LocationListener {
public class ServiceGps extends Observable implements IServiceGps, LocationListener {
private static final String TAG = "ServiceGps";
public static final String NOTIF_NEW_LOCATION = "fr.chteufleur.mytrackingdog.services.servicegps.newlocation";
private LocationManager locationManager;
private Location currentLocation = null;
@ -22,6 +26,24 @@ public class ServiceGps implements IServiceGps, LocationListener {
return currentLocation;
}
public float getOrientation(int deviceOrientation) {
float ret = -1;
if (currentLocation != null && currentLocation.getSpeed() >= 0.01) {
ret = (360 - currentLocation.getBearing() - deviceOrientation);
if (ret < 0) {
ret += 360;
}
if (ret > 360) {
ret -= 360;
}
//help smooth everything out
ret = (int) ret;
ret = ret / 5;
ret = (int) ret;
ret = ret * 5;
}
return ret;
}
@Override
public void start() {
@ -41,6 +63,8 @@ public class ServiceGps implements IServiceGps, LocationListener {
@Override
public void onLocationChanged(Location location) {
currentLocation = location;
setChanged();
notifyObservers(NOTIF_NEW_LOCATION);
}
@Override