Start a new topic

POIs not loading in Fragment(Android)

POIs not loading in Fragment(Android)
1 Comment


Hi Team,

I'm developing an Android application where I need to load POIs in Architect view in a fragment using Javascript SDK. I have followed all the steps while creating it. But I'm able to see only blank camera screen with blank radar.None of the POIs are loading on screen but the status message at the bottom shows "20 places loaded". 

I'm attaching Fragment code below, please have a look:
 

public class WikitudeFragment extends Fragment implements ArchitectViewHolderInterface.ILocationProvider {

/**
* holds the Wikitude SDK AR-View, this is where camera, markers, compass, 3D models etc. are rendered
*/
private ArchitectView architectView;

/**
* sensor accuracy listener in case you want to display calibration hints
*/
private ArchitectView.SensorAccuracyChangeListener sensorAccuracyListener;

/**
* last known location of the user, used internally for content-loading after user location was fetched
*/
private Location lastKnownLocaton;

/**
* sample location strategy, you may implement a more sophisticated approach too
*/
public ArchitectViewHolderInterface.ILocationProvider locationProvider;

/**
* location listener receives location updates and must forward them to the architectView
*/
protected LocationListener locationListener;


private long lastCalibrationToastShownTimeMillis = System.currentTimeMillis();

private ArchitectView.ArchitectUrlListener urlListener;

private JSONArray poiData;

private boolean isLoading = false;
public static final int CULLING_DISTANCE_DEFAULT_METERS = 50 * 1000;
private static final int WIKITUDE_PERMISSIONS_REQUEST_CAMERA = 1;
private static final int WIKITUDE_PERMISSIONS_REQUEST_GPS = 2;
private static final int WIKITUDE_PERMISSIONS_REQUEST_EXTERNAL_STORAGE = 3;
private static final int WIKITUDE_PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION = 4;
protected Bitmap screenCapture = null;
String permissions = {"android.permission.WRITE_EXTERNAL_STORAGE", "android.permission.CAMERA" , "android.permission.ACCESS_GPS" ,"android.permission.ACCESS_FINE_LOCATION"};
int permsRequestCode = 200;

public static final String WIKITUDE_SDK_KEY = "EKZPG8BYCNzlt07uwSftel6fJJW2MM8UV+KsQff1G1UsVU6tN0fpjUaXo5YGsxxqUfSbM5tAdd1hK/J0bzF5ZaMGPKng4mUcaNsbgZWFMvTj2v9J8K4Wh14WhEhobYHXBg7+7++dfxEgERPTQjKYwZ8dD9Q3CNNHPeQNuH5qgIFTYWx0ZWRfXy2B7agUsZSUDGch/uargutzvX18ojzwKkVFqSRn/aXp//mAFflOJD+vyZSsdX7hvImbpUQpgxfTJ/5jnJoEkN0jcTWb11TkzaIuqPFlYesDy1QUuFCBhEEyYaEEwB4cyIygsfP9SV3rBGGshWEcUw5PsCE3GilmLb49iqn/wfTXbiUy15+sJtycd+ybGgrohESXQMkhe6jsiaIqYhOx/nmMjSnMtDy6LYVcasp+OMQROYZUoC7I9WriaqFUVfj0PuyRSF+zY/YaQmL10YLPsFy4ifA1sXLDSfzInMgmu1woe46B2f66kyifeBp9h/AVwKdeIXZeUg8MIi1Be9Fhmx4oHE3Gr4vfEKmcSZuiOkqWpB1RCpfQcvzhmOSg+Ylw+WPfzjlXKXLlzKiwZeHDeosY/7crORSyR9v/vqMK7uFw7u+Lgjgk5omjWATWRN1v9xtt9v8ysPlqo4ZjL5RTmtDbFgYKl3R3FUFEoYCxxvHlQsbnwYECbT4=";
private MainActivity mainAct;


@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_wikitude, container, false);

mainAct = (MainActivity) getActivity();
/* set AR-view for life-cycle notifications etc. */
architectView = (ArchitectView)view.findViewById(R.id.architectView);
return view;
}

public void verifyAccess() {
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP_MR1) {
requestPermissions(permissions, permsRequestCode);
}
}

private void initARView() {

verifyAccess();

/*pass SDK key if you have one, this one is only valid for this package identifier and must not be used somewhere else
*/
final StartupConfiguration config = new StartupConfiguration( WIKITUDE_SDK_KEY, 0 , StartupConfiguration.CameraPosition.DEFAULT );

try {
/*first mandatory life-cycle notification*/
this.architectView.onCreate( config );
} catch (RuntimeException rex) {
this.architectView = null;
Toast.makeText(mainAct.getApplicationContext(), "can't create Architect View", Toast.LENGTH_SHORT).show();
Log.e(this.getClass().getName(), "Exception in ArchitectView.onCreate()", rex);
}
}

public ArchitectView.SensorAccuracyChangeListener getSensorAccuracyListener() {
return new ArchitectView.SensorAccuracyChangeListener() {
@Override
public void onCompassAccuracyChanged( int accuracy ) {
/* UNRELIABLE = 0, LOW = 1, MEDIUM = 2, HIGH = 3 */
if ( accuracy < SensorManager.SENSOR_STATUS_ACCURACY_MEDIUM && mainAct.getApplicationContext() != null && !mainAct.isFinishing() && System.currentTimeMillis() - lastCalibrationToastShownTimeMillis > 5 * 1000) {
Toast.makeText( mainAct.getApplicationContext(), "Please re-calibrate compass by waving your device in a figure 8 motion.", Toast.LENGTH_LONG ).show();
lastCalibrationToastShownTimeMillis = System.currentTimeMillis();
}
}
};
}

public ArchitectViewHolderInterface.ILocationProvider getLocationProvider(final LocationListener locationListener) {
return new LocationProvider(mainAct.getApplicationContext(), locationListener);
}

public ArchitectView.ArchitectUrlListener getUrlListener() {
return new ArchitectView.ArchitectUrlListener() {

@Override
public boolean urlWasInvoked(String uriString) {
Uri invokedUri = Uri.parse(uriString);

Log.i("SampleCamActivity", String.valueOf(invokedUri));
Log.i("SampleCamActivity", invokedUri.getHost());
return true;
}
};
}

@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);

/*initialize AR View*/
initARView();

if ( this.architectView != null ) {

// call mandatory live-cycle method of architectView
this.architectView.onPostCreate();

try {
// load content via url in architectView, ensure '<script src="architect://architect.js"></script>' is part of this HTML file, have a look at wikitude.com's developer section for API references
this.architectView.load("samples/PointOfInterestMultiplePois/index.html");

if (this.getInitialCullingDistanceMeters() != CULLING_DISTANCE_DEFAULT_METERS) {
// set the culling distance - meaning: the maximum distance to render geo-content
this.architectView.setCullingDistance( this.getInitialCullingDistanceMeters() );
}

/*to inject data*/
injectData();

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

// set accuracy listener if implemented, you may e.g. show calibration prompt for compass using this listener
this.sensorAccuracyListener = this.getSensorAccuracyListener();

// set urlListener, any calls made in JS like "document.location = 'architectsdk://foo?bar=123'" is forwarded to this listener, use this to interact between JS and native Android activity/fragment
urlListener = getUrlListener();

// register valid urlListener in architectView, ensure this is set before content is loaded to not miss any event
if (this.urlListener != null && this.architectView != null) {
this.architectView.registerUrlListener( this.getUrlListener() );
}

// listener passed over to locationProvider, any location update is handled here
this.locationListener = new LocationListener() {

@Override
public void onStatusChanged( String provider, int status, Bundle extras ) {
}

@Override
public void onProviderEnabled( String provider ) {
}

@Override
public void onProviderDisabled( String provider ) {
}

@Override
public void onLocationChanged( final Location location ) {
// forward location updates fired by LocationProvider to architectView, you can set lat/lon from any location-strategy
if (location!=null) {
// sore last location as member, in case it is needed somewhere (in e.g. your adjusted project)
lastKnownLocaton = location;
if ( architectView != null ) {
// check if location has altitude at certain accuracy level & call right architect method (the one with altitude information)
if ( location.hasAltitude() && location.hasAccuracy() && location.getAccuracy()<7) {
architectView.setLocation( location.getLatitude(), location.getLongitude(), location.getAltitude(), location.getAccuracy() );
} else {
architectView.setLocation( location.getLatitude(), location.getLongitude(), location.hasAccuracy() ? location.getAccuracy() : 1000 );
}
}
}
}
};

// locationProvider used to fetch user position
locationProvider = getLocationProvider( this.locationListener );


}
}
/*public String getARchitectWorldPath() {
//Log.i("getARchitectWorldPath", getIntent().getExtras().getString(MainSamplesListActivity.EXTRAS_KEY_ACTIVITY_ARCHITECT_WORLD_URL));
return "samples/PointOfInterestMultiplePois/index.html";
}*/

public float getInitialCullingDistanceMeters() {
// you need to adjust this in case your POIs are more than 50km away from user here while loading or in JS code (compare 'AR.context.scene.cullingDistance')
return CULLING_DISTANCE_DEFAULT_METERS;
}

@Override
public void onResume() {
super.onResume();

// call mandatory live-cycle method of architectView
if ( this.architectView != null ) {
this.architectView.onResume();

// register accuracy listener in architectView, if set
if (this.sensorAccuracyListener!=null) {
this.architectView.registerSensorAccuracyChangeListener( this.sensorAccuracyListener );
}
}

// tell locationProvider to resume, usually location is then (again) fetched, so the GPS indicator appears in status bar
if ( this.locationProvider != null ) {
this.locationProvider.onResume();
}
}

@Override
public void onPause() {
super.onPause();
// call mandatory live-cycle method of architectView
if ( this.architectView != null ) {
this.architectView.onPause();

// unregister accuracy listener in architectView, if set
if ( this.sensorAccuracyListener != null ) {
this.architectView.unregisterSensorAccuracyChangeListener( this.sensorAccuracyListener );
}
}

// tell locationProvider to pause, usually location is then no longer fetched, so the GPS indicator disappears in status bar
if ( this.locationProvider != null ) {
this.locationProvider.onPause();
}
}



@Override
public void onDestroy() {
super.onDestroy();

// call mandatory live-cycle method of architectView
if ( this.architectView != null ) {
this.architectView.onDestroy();
}
}

@Override
public void onLowMemory() {
super.onLowMemory();

if ( this.architectView != null ) {
this.architectView.onLowMemory();
}
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String permissions, @NonNull int grantResults) {
//super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode) {
case WIKITUDE_PERMISSIONS_REQUEST_CAMERA: {
if ( grantResults.length > 0 && grantResults == PackageManager.PERMISSION_GRANTED ) {
if ( ContextCompat.checkSelfPermission(mainAct.getApplicationContext(), Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED ) {
ActivityCompat.requestPermissions(mainAct, new String{Manifest.permission.ACCESS_FINE_LOCATION}, WIKITUDE_PERMISSIONS_REQUEST_GPS);
}

} else {
Toast.makeText(mainAct.getApplicationContext(), "Sorry, augmented reality doesn't work without reality.n\nPlease grant camera permission.", Toast.LENGTH_LONG).show();
}
return;
}
case WIKITUDE_PERMISSIONS_REQUEST_GPS: {
if ( grantResults.length > 0 && grantResults == PackageManager.PERMISSION_GRANTED ) {
} else {
Toast.makeText(mainAct.getApplicationContext(), "Sorry, this example requires access to your location in order to work properly.\n\nPlease grant location permission.", Toast.LENGTH_SHORT).show();
}
return;
}

case WIKITUDE_PERMISSIONS_REQUEST_EXTERNAL_STORAGE: {
if ( grantResults.length > 0 && grantResults == PackageManager.PERMISSION_GRANTED ) {
/*this.saveScreenCaptureToExternalStorage(screenCapture);*/
} else {
Toast.makeText(mainAct.getApplicationContext(), "Please allow access to external storage, otherwise the screen capture can not be saved.", Toast.LENGTH_SHORT).show();
}
return;
}

case WIKITUDE_PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION: {
if ( grantResults.length > 0 && grantResults == PackageManager.PERMISSION_GRANTED ) {
} else {
Toast.makeText(mainAct.getApplicationContext(), "Sorry, this example requires access to your location in order to work properly.\n\nPlease grant location permission.", Toast.LENGTH_SHORT).show();
}
return;
}
}
}

private void injectData() {
if (!isLoading) {
final Thread t = new Thread(new Runnable() {

@Override
public void run() {

isLoading = true;

final int WAIT_FOR_LOCATION_STEP_MS = 2000;

while (lastKnownLocaton==null && !mainAct.isFinishing()) {

mainAct.runOnUiThread(new Runnable() {

@Override
public void run() {
Toast.makeText(mainAct.getApplicationContext(), R.string.location_fetching, Toast.LENGTH_SHORT).show();
}
});

try {
Thread.sleep(WAIT_FOR_LOCATION_STEP_MS);
} catch (InterruptedException e) {
break;
}
}

if (lastKnownLocaton!=null && !mainAct.isFinishing()) {
// TODO: you may replace this dummy implementation and instead load POI information e.g. from your database
poiData = getPoiInformation(lastKnownLocaton, 20);
callJavaScript("World.loadPoisFromJsonData", new String { poiData.toString() });
}

isLoading = false;
}
});
t.start();
}
}

/**
* call JacaScript in architectView
*/
private void callJavaScript(final String methodName, final String arguments) {
final StringBuilder argumentsString = new StringBuilder("");
for (int i= 0; i<arguments.length; i++) {
argumentsString.append(arguments);
if (i<arguments.length-1) {
argumentsString.append(", ");
}
}

if (this.architectView!=null) {
final String js = ( methodName + "( " + argumentsString.toString() + " );" );
this.architectView.callJavascript(js);
}
}

public static JSONArray getPoiInformation(final Location userLocation, final int numberOfPlaces) {

if (userLocation==null) {
return null;
}

final JSONArray pois = new JSONArray();

// ensure these attributes are also used in JavaScript when extracting POI data
final String ATTR_ID = "id";
final String ATTR_NAME = "name";
final String ATTR_DESCRIPTION = "description";
final String ATTR_LATITUDE = "latitude";
final String ATTR_LONGITUDE = "longitude";
final String ATTR_ALTITUDE = "altitude";

for (int i=1;i <= numberOfPlaces; i++) {
final HashMap<String, String> poiInformation = new HashMap<String, String>();
poiInformation.put(ATTR_ID, String.valueOf(i));
poiInformation.put(ATTR_NAME, "POI#" + i);
poiInformation.put(ATTR_DESCRIPTION, "This is the description of POI#" + i);
double poiLocationLatLon = getRandomLatLonNearby(userLocation.getLatitude(), userLocation.getLongitude());
poiInformation.put(ATTR_LATITUDE, String.valueOf(poiLocationLatLon));
poiInformation.put(ATTR_LONGITUDE, String.valueOf(poiLocationLatLon));
final float UNKNOWN_ALTITUDE = -32768f; // equals "AR.CONST.UNKNOWN_ALTITUDE" in JavaScript (compare AR.GeoLocation specification)
// Use "AR.CONST.UNKNOWN_ALTITUDE" to tell ARchitect that altitude of places should be on user level. Be aware to handle altitude properly in locationManager in case you use valid POI altitude value (e.g. pass altitude only if GPS accuracy is <7m).
poiInformation.put(ATTR_ALTITUDE, String.valueOf(UNKNOWN_ALTITUDE));
pois.put(new JSONObject(poiInformation));
}

return pois;
}

/**
* helper for creation of dummy places.
* @param lat center latitude
* @param lon center longitude
* @return lat/lon values in given position's vicinity
*/
private static double getRandomLatLonNearby(final double lat, final double lon) {
return new double { lat + Math.random()/5-0.1 , lon + Math.random()/5-0.1};
}
}





Thanks,
Babita

 

 
Login or Signup to post a comment