public class FusedLocationProvider implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, com.google.android.gms.location.LocationListener, ArchitectViewHolderInterface.ILocationProvider {
public FusedLocationProvider(Context ctx, LocationListener locationListener){
mGoogleApiClient = new GoogleApiClient.Builder(ctx) .addApi(LocationServices.API) .addConnectionCallbacks(this) .addOnConnectionFailedListener(this) .build();
mGoogleApiClient.connect();
Log.i(TAG, "Connecting...");
this.listener = locationListener; }
@Override public void onConnected(Bundle bundle) {
Log.i(TAG, "onConnected");
mLocationRequest = LocationRequest.create(); mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY); mLocationRequest.setInterval(1000); // Update location every second
// set distance slider to 100% $("#panel-distance-range").val(100); $("#panel-distance-range").slider("refresh"); },
// sets/updates distances of all makers so they are available way faster than calling (time-consuming) distanceToUser() method all the time updateDistanceToUserValues: function updateDistanceToUserValuesFn() { for (var i = 0; i < World.markerList.length; i++) { World.markerList.distanceToUser = World.markerList.markerObject.locations.distanceToUser(); } },
// updates status message shon in small "i"-button aligned bottom center updateStatusMessage: function updateStatusMessageFn(message, isWarning) {
var themeToUse = isWarning ? "e" : "c"; var iconToUse = isWarning ? "alert" : "info";
// location updates, fired every time you call architectView.setLocation() in native environment locationChanged: function locationChangedFn(lat, lon, alt, acc) {
// store user's current location in World.userLocation, so you always know where user is World.userLocation = { 'latitude': lat, 'longitude': lon, 'altitude': alt, 'accuracy': acc };
// request data if not already present if (!World.initiallyLoadedData) { World.requestDataFromServer(lat, lon); World.initiallyLoadedData = true; } else if (World.locationUpdateCounter === 0) { // update placemark distance information frequently, you max also update distances only every 10m with some more effort World.updateDistanceToUserValues(); }
// helper used to update placemark information every now and then (e.g. every 10 location upadtes fired) World.locationUpdateCounter = (++World.locationUpdateCounter % World.updatePlacemarkDistancesEveryXLocationUpdates); },
// fired when user pressed maker in cam onMarkerSelected: function onMarkerSelectedFn(marker) { World.currentMarker = marker;
// screen was clicked but no geo-object was hit onScreenClick: function onScreenClickFn() { // you may handle clicks on empty AR space too },
// returns distance in meters of placemark with maxdistance * 1.1 getMaxDistance: function getMaxDistanceFn() {
// sort palces by distance so the first entry is the one with the maximum distance World.markerList.sort(World.sortByDistanceSortingDescending);
// use distanceToUser to get max-distance var maxDistanceMeters = World.markerList.distanceToUser;
// return maximum distance times some factor >1.0 so ther is some room left and small movements of user don't cause places far away to disappear return maxDistanceMeters * 1.1; },
// udpates values show in "range panel" updateRangeValues: function updateRangeValuesFn() {
// get current slider value (0..100); var slider_value = $("#panel-distance-range").val();
// max range relative to the maximum distance of all visible places var maxRangeMeters = Math.round(World.getMaxDistance() * (slider_value / 100));
// range in meters including metric m/km var maxRangeValue = (maxRangeMeters > 999) ? ((maxRangeMeters / 1000).toFixed(2) + " km") : (Math.round(maxRangeMeters) + " m");
// number of places within max-range var placesInRange = World.getNumberOfVisiblePlacesInRange(maxRangeMeters);
// update culling distance, so only palces within given range are rendered AR.context.scene.cullingDistance = Math.max(maxRangeMeters, 1);
// update radar's maxDistance so radius of radar is updated too PoiRadar.setMaxDistance(Math.max(maxRangeMeters, 1)); },
// returns number of places with same or lower distance than given range getNumberOfVisiblePlacesInRange: function getNumberOfVisiblePlacesInRangeFn(maxRangeMeters) {
// sort markers by distance World.markerList.sort(World.sortByDistanceSorting);
// loop through list and stop once a placemark is out of range ( -> very basic implementation ) for (var i = 0; i < World.markerList.length; i++) { if (World.markerList.distanceToUser > maxRangeMeters) { return i; } };
// in case no placemark is out of range -> all are visible return World.markerList.length; },
handlePanelMovements: function handlePanelMovementsFn() {
// helper to sort places by distance sortByDistanceSorting: function(a, b) { return a.distanceToUser - b.distanceToUser; },
// helper to sort places by distance, descending sortByDistanceSortingDescending: function(a, b) { return b.distanceToUser - a.distanceToUser; }
};
/* forward locationChanges to custom function */ AR.context.onLocationChanged = World.locationChanged;
/* forward clicks in empty area to World */ AR.context.onScreenClick = World.onScreenClick;
var localData = ;
I will upload the complete project in sometime.
A
Andreas Fötschl
said
over 7 years ago
Hi there!
Using Google's LocationService is definitely a good idea. It is way more accurate than what one could achieve in writing a LocationProvider manually.
Please note that the AR-View uses whatever you pass in its setLocation method as lat/lon/alt values. Even the SDK Sample app does nothing but using params it gets from the "primitive LocationProvider.java implementation".
Assuming you get proper lat/lon values using the LocationProvider, you can just pass them to the architectView. OnLocationChanged event will then be fire in JS so you can double check.
Please debug in JS and Android code to understand why the POIs are not located where you expect them to be. My assumption is that your location is accurate but updated quite frequently, so that the new POI is created slightly next to the current user location.
Also note that the altitude is a crucial thing. I'd rather recommend using an unknown altitude value when setting it in Android code than setting an inaccurate altitude which may then cause creation of POIs off in altitude.
Searock Ruzario