Start a new topic

Send POI data from Android Studio to JavaScript marker.js

 Hi there, How could I pass poi data from java(Android Studio) to marker.js ? I find this doc

http://www.wikitude.com/external/doc/documentation/6.1/android/retrievingpoidata.html#local


Those only in javascript, not in java.



Because i have got data from web api using java, my search in java is dynamic.


Thanks


Hi Nicola, thanks for the documentation. I get error when I use architectView.callJavascript().

  

public class MainActivity extends AppCompatActivity {

    private ArchitectView architectView;
    private String json;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate ( savedInstanceState );
        setContentView ( R.layout.activity_main );

        this.architectView = (ArchitectView) this.findViewById ( R.id.architectView );
        final ArchitectStartupConfiguration config = new ArchitectStartupConfiguration ();
        config.setLicenseKey ( "kxVnyyNrfxwqXQhq45qR6dNCd/Edpcnmk27K8H3YMnHG6VtzhJZkT3NgCoONQEnBLN/UH/7LHwuBM9DsSKlet2n+Vs5RH4LFSL28Y/lDAWx0HOJSuwkISxrLA5auHNG3QqkgcYZvfECDZ3d4eap/ZEGZpcdqZY2Hv7AmVqk9vbVTYWx0ZWRfX0LOfmOLK0eM1UDkGGaiXC+6cW5gHTEOuvrhzr19fy0ezWXwgd1BIHLw4PVW2lL8Jv+emmNdizqUjLWcwCXqmI625QPm7UqG4sr1LwYnLDPpgkxdrqW2SMMWNHWsxCrryUGtm9+vYwLIIhC6AIBdJMvs0HW9wV2vjHzDWCloIZsstVvSj1lie+4gHjUW43IuNqEEHS1ELEWcNnZplT/x1KEQoq+6cZF+LceK2j0BXF/X461/ehY37bUq2PhNYsvCL2165K1TonXKp7JCVph3iZm7deNnUMFxRm1GyId4PPZVzwmfNrthVRw16P+Zeapah9SngD5vcms6CeFd0I0pW/nampjxwHJNjkktv06y9sAmI2TvUFHXCCTJole6fISBe5WNsyRsSQgcIaRaEERD/vCJ5/pmhlG/cohAA47pdHjkrctj3oSmVR2UziEYEcS/Zuc7voN+kuOKzu1pwvXd5qbXoW2BEhSvyTLJKzOsDJRoqKNbS1XtMqo=" );
        this.architectView.onCreate ( config );
    }

    @Override
    protected void onPostCreate(@Nullable Bundle savedInstanceState) {
        super.onPostCreate ( savedInstanceState );
        this.architectView.onPostCreate ();
        FusedLocationProviderClient fusedLocationProviderClient =
                LocationServices.getFusedLocationProviderClient ( this );

        try {
            if (ActivityCompat.checkSelfPermission ( this, Manifest.permission.ACCESS_FINE_LOCATION ) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission ( this, Manifest.permission.ACCESS_COARSE_LOCATION ) != PackageManager.PERMISSION_GRANTED) {
                // TODO: Consider calling
                //    ActivityCompat#requestPermissions
                // here to request the missing permissions, and then overriding
                //   public void onRequestPermissionsResult(int requestCode, String[] permissions,
                //                                          int[] grantResults)
                // to handle the case where the user grants the permission. See the documentation
                // for ActivityCompat#requestPermissions for more details.
                return;
            }

            fusedLocationProviderClient.getLastLocation ().addOnSuccessListener ( this, new OnSuccessListener<Location> () {
                @Override
                public void onSuccess(Location location) {
                    architectView.setLocation ( location.getLatitude (), location.getLongitude (), location.getAltitude (), (float) 0.3 );
                    Log.d ( "Location", "Lat : " + location.getLatitude () + "Long : " + location.getLongitude () + "Alt : " + location.getAltitude () );
                }
            } );
            this.architectView.load( "08_Browsing_Pois_3_Limiting_Range/index.html");
            json = "[{\"id\":\"1\"," +
                    "\"longitude\":\"0.057\"," +
                    "\"latitude\":\"0.095\"," +
                    "\"description\":\"This is the description of POI#1\"," +
                    "\"name\":\"POI#1\"}]";

            architectView.callJavascript("World.getDataFromNative('"+json+"');");

        } catch (IOException e) {
            e.printStackTrace ();
        }
    }

    @Override
    protected void onPause() {
        super.onPause ();
        this.architectView.onPause ();
    }

    @Override
    protected void onPostResume() {
        super.onPostResume ();
        this.architectView.onResume ();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy ();
        this.architectView.onDestroy ();
    }
}

 and this is my JavaScript:

 

// information about server communication. This sample webservice is provided by Wikitude and returns random dummy places near given location
var ServerInformation = {
	POIDATA_SERVER: "https://demo2164006.mockable.io/umkm",
	POIDATA_SERVER_ARG_LAT: "lat",
	POIDATA_SERVER_ARG_LON: "lon",
	POIDATA_SERVER_ARG_NR_POIS: "nrPois"
};

// implementation of AR-Experience (aka "World")
var World = {

	//  user's latest known location, accessible via userLocation.latitude, userLocation.longitude, userLocation.altitude
	userLocation: null,

	// you may request new data from server periodically, however: in this sample data is only requested once
	isRequestingData: false,

	// true once data was fetched
	initiallyLoadedData: false,

	// different POI-Marker assets
	markerDrawable_idle: null,
	markerDrawable_selected: null,
	markerDrawable_directionIndicator: null,

	// list of AR.GeoObjects that are currently shown in the scene / World
	markerList: [],

	// The last selected marker
	currentMarker: null,

	locationUpdateCounter: 0,
	updatePlacemarkDistancesEveryXLocationUpdates: 10,

	// called to inject new POI data
	loadPoisFromJsonData: function loadPoisFromJsonDataFn(poiData) {

		// show radar & set click-listener
		PoiRadar.show();
		$('#radarContainer').unbind('click');
		$("#radarContainer").click(PoiRadar.clickedRadar);

		// empty list of visible markers
		World.markerList = [];

		// start loading marker assets
		World.markerDrawable_idle = new AR.ImageResource("assets/marker_idle.png");
		World.markerDrawable_selected = new AR.ImageResource("assets/marker_selected.png");
		World.markerDrawable_directionIndicator = new AR.ImageResource("assets/indi.png");

		// loop through POI-information and create an AR.GeoObject (=Marker) per POI
		for (var currentPlaceNr = 0; currentPlaceNr < poiData.length; currentPlaceNr++) {
			var singlePoi = {
				"id": poiData[currentPlaceNr].id,
				"latitude": parseFloat(poiData[currentPlaceNr].latitude),
				"longitude": parseFloat(poiData[currentPlaceNr].longitude),
				"altitude": parseFloat(poiData[currentPlaceNr].altitude),
				"title": poiData[currentPlaceNr].name,
				"description": poiData[currentPlaceNr].description
			};

			World.markerList.push(new Marker(singlePoi));
		}

		// updates distance information of all placemarks
		World.updateDistanceToUserValues();

		World.updateStatusMessage(currentPlaceNr + ' places loaded');

		// 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[i].distanceToUser = World.markerList[i].markerObject.locations[0].distanceToUser();
		}
	},

	// updates status message shown in small "i"-button aligned bottom center
	updateStatusMessage: function updateStatusMessageFn(message, isWarning) {

		var themeToUse = isWarning ? "e" : "c";
		var iconToUse = isWarning ? "alert" : "info";

		$("#status-message").html(message);
		$("#popupInfoButton").buttonMarkup({
			theme: themeToUse
		});
		$("#popupInfoButton").buttonMarkup({
			icon: iconToUse
		});
	},

	// 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;

		// update panel values
		$("#poi-detail-title").html(marker.poiData.title);
		$("#poi-detail-description").html(marker.poiData.description);

		/* It's ok for AR.Location subclass objects to return a distance of `undefined`. In case such a distance was calculated when all distances were queried in `updateDistanceToUserValues`, we recalcualte this specific distance before we update the UI. */
		if( undefined == marker.distanceToUser ) {
			marker.distanceToUser = marker.markerObject.locations[0].distanceToUser();
		}
		var distanceToUserValue = (marker.distanceToUser > 999) ? ((marker.distanceToUser / 1000).toFixed(2) + " km") : (Math.round(marker.distanceToUser) + " m");

		$("#poi-detail-distance").html(distanceToUserValue);

		// show panel
		$("#panel-poidetail").panel("open", 123);
		
		$( ".ui-panel-dismiss" ).unbind("mousedown");

		$("#panel-poidetail").on("panelbeforeclose", function(event, ui) {
			World.currentMarker.setDeselected(World.currentMarker);
		});
	},

	// 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 places 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[0].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 UI labels accordingly
		$("#panel-distance-value").html(maxRangeValue);
		$("#panel-distance-places").html((placesInRange != 1) ? (placesInRange + " Places") : (placesInRange + " Place"));

		// update culling distance, so only places 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[i].distanceToUser > maxRangeMeters) {
				return i;
			}
		};

		// in case no placemark is out of range -> all are visible
		return World.markerList.length;
	},

	handlePanelMovements: function handlePanelMovementsFn() {

		$("#panel-distance").on("panelclose", function(event, ui) {
			$("#radarContainer").addClass("radarContainer_left");
			$("#radarContainer").removeClass("radarContainer_right");
			PoiRadar.updatePosition();
		});

		$("#panel-distance").on("panelopen", function(event, ui) {
			$("#radarContainer").removeClass("radarContainer_left");
			$("#radarContainer").addClass("radarContainer_right");
			PoiRadar.updatePosition();
		});
	},

	// display range slider
	showRange: function showRangeFn() {
		if (World.markerList.length > 0) {

			// update labels on every range movement
			$('#panel-distance-range').change(function() {
				World.updateRangeValues();
			});

			World.updateRangeValues();
			World.handlePanelMovements();

			// open panel
			$("#panel-distance").trigger("updatelayout");
			$("#panel-distance").panel("open", 1234);
		} else {

			// no places are visible, because the are not loaded yet
			World.updateStatusMessage('No places available yet', true);
		}
	},

	// request POI data
	/*requestDataFromServer: function requestDataFromServerFn(lat, lon) {

		// set helper var to avoid requesting places while loading
		//World.isRequestingData = true;
		// actual is true  up
		World.updateStatusMessage('Requesting places from web-service');

		// server-url to JSON content provider
		var serverUrl = ServerInformation.POIDATA_SERVER + "?" + ServerInformation.POIDATA_SERVER_ARG_LAT + "=" + lat + "&" + ServerInformation.POIDATA_SERVER_ARG_LON + "=" + lon + "&" + ServerInformation.POIDATA_SERVER_ARG_NR_POIS + "=10";

		var jqxhr = $.getJSON(serverUrl, function(data) {
			World.loadPoisFromJsonData(data);
		})
			.error(function(err) {
				World.updateStatusMessage("Invalid web-service response.", true);
				World.isRequestingData = false;
			})
			.complete(function() {
				World.isRequestingData = false;
			});
	},*/
	getDataFromNative: function getDataFromNativeFn(data){
    var url = data;
    World.loadPoisFromJsonData(data);
    },

	// 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;

 My error log is: E/ArchitectView: setLocation: LocationService is not initialized. When I remove architectView.callJavascript. The error has gone.

thanks

Did you check the forum for further details on the Native to JS communication:


https://support.wikitude.com/support/search/topics?term=Call+native+code+from+Javascript


Greetings

Nicola

I see that Ar.platform.sendJSONObject() is sending data from javascript to native, method onJSONObjectReceived for receiving from javascript. I still get confuse

 how to send data Poi From Java, not in javascript. Thanks

Hi,


Did you already check the details on the Native <> JS communication:


https://www.wikitude.com/external/doc/documentation/latest/android/browsingpois.html#displaying-native-detail-screen


With this sample and the respective documentation you should have a good starting point on how the Native <> JS communciation is working.


If you have further questions, it's also a good starting point to check other forum posts for further technical details.


Thx and greetings

Nicola 

Login or Signup to post a comment