If you need some sourcecode, here's are the relevant parts (assume premissions to Location and Camera have already been given in a previous SplashScreenActivity).
@ConfigPersistent
public class ARPresenter extends BasePresenter<ARView> {
private final GetPoisByCollectionId getPoisByCollectionId;
private final LoginManager loginManager;
private CompositeSubscription mapSubscriptions = Subscriptions.from();
private ArchitectView architectView;
private Subscription poisSubscription;
private List<Poi> pois;
private AtomicBoolean lockCamera = new AtomicBoolean(true);
private Subscription timerSubscription;
private AtomicBoolean architectViewLoadedSuccessfully = new AtomicBoolean(false);
@Inject
public ARPresenter(GetPoisByCollectionId getPoisByCollectionId, LoginManager loginManager, RxEventBus eventBus) {
super(eventBus, loginManager);
this.getPoisByCollectionId = getPoisByCollectionId;
this.loginManager = loginManager;
}
@Override
public void attachView(ARView view) {
super.attachView(view);
}
public void setupMaps(Integer poiCollectionId) {
getView().showInSnackbar("setting up Google-Maps™");
SupportMapFragment mapsFragment = getView().getMapsFragment();
new Handler(getView().getContext().getMainLooper()).post(() -> {
MapObservableProvider mapObservableProvider = new MapObservableProvider(mapsFragment);
mapSubscriptions
.add(mapObservableProvider
.getMapReadyObservable()
.subscribe(googleMap -> {
if (poiCollectionId != null) {
googleMap.setMyLocationEnabled(true);
googleMap.getUiSettings().setMyLocationButtonEnabled(true);
loadPois(poiCollectionId);
}
}, onError("error setting up Google Maps")));
mapSubscriptions
.add(mapObservableProvider.getMapLongClickObservable()
.subscribe(
onMapInteraction(),
onError("error setting up Google Maps")));
mapSubscriptions
.add(mapObservableProvider.getMapClickObservable()
.subscribe(
onMapInteraction(),
onError("error setting up Google Maps")));
mapSubscriptions
.add(mapObservableProvider.getCameraMoveObservable()
.throttleFirst(500, TimeUnit.MILLISECONDS)
.subscribe(
onMapInteraction(),
onError("error setting up Google Maps")));
mapSubscriptions
.add(mapObservableProvider.getMarkerClickObservable()
.subscribe(marker -> {
try {
Integer poiId = (Integer) marker.getTag();
getView().onPoiClicked(poiId);
} catch (Exception e) {
Timber.e(e, "Marker has no POI attached");
}
}));
});
}
@NonNull
private <T> Action1<T> onMapInteraction() {
return t -> {
lockCamera.set(false);
Timber.d("camera unlocked");
unsubscribe(timerSubscription);
timerSubscription = Observable.timer(8, TimeUnit.SECONDS).subscribe(aLong -> lockCamera.set(true));
};
}
public void setupWikitude() {
getView().showInSnackbar("setting up Wikitude™");
if (BuildConfig.DEBUG) {
if ((getView().getContext().getApplicationInfo().flags &= ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
WebView.setWebContentsDebuggingEnabled(true);
}
}
ArchitectStartupConfiguration startupConfiguration = new ArchitectStartupConfiguration();
startupConfiguration.setLicenseKey(BuildConfig.WIKITUDE_SDK_KEY);
startupConfiguration.setFeatures(ArchitectView.getSupportedFeaturesForDevice(getView().getContext()));
startupConfiguration.setCameraResolution(CameraSettings.CameraResolution.SD_640x480);
if (architectView == null) {
architectView = getView().getArchitectView();
architectView.onCreate(startupConfiguration);
RxArchitectView
.urlChange(architectView)
.subscribeOn(AndroidSchedulers.mainThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(
this::parseWikitudeUrl,
onError("Error reading Wikitude WebView URL"));
}
}
public void onPostCreate(Integer poiCollectionId) {
if (architectView != null && !architectViewLoadedSuccessfully.get()) {
architectView.onPostCreate();
RxArchitectView
.load(architectView)
.subscribeOn(AndroidSchedulers.mainThread())
.observeOn(AndroidSchedulers.mainThread())
.debounce(2, TimeUnit.SECONDS)
.subscribe(
successMessage -> {
setupMaps(poiCollectionId);
architectView.setCullingDistance(BuildConfig.CULLING_DISTANCE_METER);
architectView.addArchitectJavaScriptInterfaceListener(jsonObject -> {
Timber.d(jsonObject.toString());
});
architectViewLoadedSuccessfully.set(true);
},
onError("Error loading ArchitectView"));
}
}
public void resumeWikitude() {
if (this.architectView != null) {
this.architectView.onResume();
}
}
public void pauseWikitude() {
if (this.architectView != null && architectViewLoadedSuccessfully.get()) {
this.architectView.onPause();
}
architectViewLoadedSuccessfully.set(false);
}
private void parseWikitudeUrl(String url) {
Uri uri = Uri.parse(url);
if ("markerselected".equalsIgnoreCase(uri.getHost())) {
Integer id = Integer.valueOf(uri.getQueryParameter("id"));
String title = uri.getQueryParameter("title");
String description = uri.getQueryParameter("description");
String text = String.format("Poi '%s' with id %s clicked", title, id);
getView().onPoiClicked(id);
}
}
private void showPoisInArchitectView(List<Poi> pois) {
String ATTR_ID = "id";
String ATTR_NAME = "title";
String ATTR_DESCRIPTION = "description";
String ATTR_LATITUDE = "latitude";
String ATTR_LONGITUDE = "longitude";
String ATTR_ALTITUDE = "altitude";
JSONArray poiArray = new JSONArray();
for (int i = 0; i < pois.size(); i++) {
final HashMap<String, String> poiInformation = new HashMap<>();
poiInformation.put(ATTR_ID, String.valueOf(pois.get(i).getId()));
poiInformation.put(ATTR_NAME, pois.get(i).getName());
poiInformation.put(ATTR_DESCRIPTION, "");
double[] poiLocationLatLon = getRandomLatLonNearby(52.1784615, 7.0343582);
float latitude = pois.get(i).getLatitude();
float longitude = pois.get(i).getLongitude();
poiInformation.put(ATTR_LATITUDE, String.valueOf(latitude));
poiInformation.put(ATTR_LONGITUDE, String.valueOf(longitude));
final float UNKNOWN_ALTITUDE = -32768f; // equals "AR.CONST.UNKNOWN_ALTITUDE" in JavaScript (compare AR.GeoLocation specification)
poiInformation.put(ATTR_ALTITUDE, String.valueOf(UNKNOWN_ALTITUDE));
poiArray.put(new JSONObject(poiInformation));
}
callJavaScript("World.loadPoisFromJsonData", new String[]{poiArray.toString()});
}
private static double[] getRandomLatLonNearby(final double lat, final double lon) {
return new double[]{lat + Math.random() / 10 - 0.05, lon + Math.random() / 10 - 0.05};
}
public void callJavaScript(final String methodName, final String[] arguments) {
StringBuilder argumentsString = new StringBuilder("");
for (int i = 0; i < arguments.length; i++) {
argumentsString.append(arguments[i]);
if (i < arguments.length - 1) {
argumentsString.append(", ");
}
}
if (getView().getArchitectView() != null) {
String js = (methodName + "( " + argumentsString.toString() + " );");
getView().getArchitectView().callJavascript(js);
}
}
public void loadPois(int poiCollectionId) {
getView().showInSnackbar("loading POI's");
getPoisByCollectionId.setPoiCollectionId(poiCollectionId);
unsubscribe(poisSubscription);
poisSubscription = getPoisByCollectionId
.fetch()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(pois -> {
getView().showProgress(false);
this.pois = pois;
showPoisOnMap(pois);
showPoisInArchitectView(pois);
}, onError("error loading PoiCollections"));
}
private void showPoisOnMap(List<Poi> pois) {
stream(pois).forEach(poi -> getView().getMapsFragment().getMapAsync(googleMap -> {
LatLng latLng = new LatLng(poi.getLatitude(), poi.getLongitude());
MarkerOptions marker = new MarkerOptions()
.title(poi.getName())
.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_BLUE))
.position(latLng);
Marker m = googleMap.addMarker(marker);
m.setTag(poi.getId());
}));
}
@Override
public void detachView() {
super.detachView();
if (architectView != null) {
architectView.clearCache();
architectView.onDestroy();
}
unsubscribe(poisSubscription);
unsubscribe(timerSubscription);
}
@Override
protected void onLocationUpdated(Location location) {
super.onLocationUpdated(location);
GeomagneticField field = new GeomagneticField(
(float) location.getLatitude(),
(float) location.getLongitude(),
(float) location.getAltitude(),
System.currentTimeMillis()
);
// getDeclination returns degrees
if (getView() != null) {
SupportMapFragment mapsFragment = getView().getMapsFragment();
if (null != mapsFragment) {
mapsFragment.getMapAsync(googleMap -> {
if (lockCamera.get()) {
Timber.d("camera locked");
CameraPosition camPos = CameraPosition
.builder(googleMap.getCameraPosition())
.target(new LatLng(location.getLatitude(), location.getLongitude()))
.zoom(15.0f)
.tilt(30.0f)
.build();
googleMap.animateCamera(CameraUpdateFactory.newCameraPosition(camPos));
}
});
if (architectView == null || !architectViewLoadedSuccessfully.get()) {
return;
}
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);
}
}
}
}
public void onUserPhoto(File file) throws IOException {
Bitmap bitmap = BitmapUtils.fromMediaStorage(getView().getContext(), Uri.fromFile(file));
UserImage userImage = new UserImage();
userImage.setTitle(loginManager.getCachedUsername() + "_" + new Date().toString());
// TODO: send to remote
//getBitmap(getView().getContext().getContentResolver(), file);
}
public List<Poi> getPois() {
return pois;
}
public void deselectCurrentMarker() {
callJavaScript("World.deselectCurrentMarker", new String[0]);
}
public void onUserPhoto(Bitmap imageBitmap) {
System.out.println("geil atze");
}
public void onUserPhotos(List<File> imageFiles) {
getView().showInSnackbar("Saving your image...");
}
public void onUserText(String message) {
getView().showInSnackbar("Saving your note...");
}
}
setupWikitude() is being invoked in onCreate() and onPostCreate() thus in onPostCreate() of the ARActivity. Further, this is the Rx code for RxArchitectView and ArchitectViewLoadedOnSubscribed()
public class RxArchitectView {
public static Observable<String> load(ArchitectView architectView) {
try {
Observable<String> stringObservable = Observable.create(new ArchitectViewLoadedOnSubscribe(architectView));
architectView.load(Constants.Wikitude.ARCHITECT_WORLD_URL);
return stringObservable;
} catch (IOException e) {
String name = Thread.currentThread().getName();
Timber.d(name);
return Observable.error(e);
}
}
public static Observable<String> urlChange(ArchitectView architectView) {
return Observable.create(new ArchitectViewUrlChangeOnSubscribe(architectView));
}
}
public class ArchitectViewLoadedOnSubscribe implements Observable.OnSubscribe<String> {
final ArchitectView architectView;
public ArchitectViewLoadedOnSubscribe(ArchitectView architectView) {
this.architectView = architectView;
}
@Override
public void call(Subscriber<? super String> subscriber) {
ArchitectView.ArchitectWorldLoadedListener listener = new ArchitectView.ArchitectWorldLoadedListener() {
@Override
public void worldWasLoaded(String message) {
if (!TextUtils.isEmpty(message) && !subscriber.isUnsubscribed()) {
subscriber.onNext(message);
}
}
@Override
public void worldLoadFailed(int i, String s, String s1) {
subscriber.onError(new ArchitectView.ArchitectInitializeException(s + " - " + s1 + " - " + i) {
@Override
public String getMessage() {
return super.getMessage();
}
});
}
};
subscriber.add(new MainThreadSubscription() {
@Override
protected void onUnsubscribe() {
architectView.registerWorldLoadedListener(null);
}
});
architectView.registerWorldLoadedListener(listener);
}
}
Hi.
I attached the regarding source code underneath my initial post. The inital post took 15 minutes to 'check'. The sources were posted 5 hours ago. Found any spam in it?
Hi Simon!
So you also tried the SDK samples and see the same logs? Samples using location are based on same LocationProvider implementation. I assume that the samples work as expected, right? If that's the case and you still see the log, you can gracefully ignore it and I will create a ticket to get rid of this entry in an upcoming release.
Please also try very latest SDK Samples from download section.
Best regards,
Andi
I am having the same issue , It was working for one day then started getting the same error.
Thanks and Regards,
Simon Cordt
Hi there. Though I am sure I was doing everything as I shoud with regards to livecycle handling, I am getting setLocation: LocationService is not initialized all over the place. So, I fired up the provided SDK examples and guess what!
E/ArchitectView: setLocation: LocationService is not initialized.
E/ArchitectView: setLocation: LocationService is not initialized.
E/ArchitectView: setLocation: LocationService is not initialized.
..
Samsung Galaxy S7 on Android 7
How to overcome this?
Best regards
2 people have this problem