Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WorldScaleSceneView: Handle permissions and implement world tracking #709

Merged
Show file tree
Hide file tree
Changes from 38 commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
067a58a
add tracking modes
hud10837 Jan 14, 2025
9a2ea2c
update WorldScaleSceneView to use LocationDataSource from TrackingMode
hud10837 Jan 14, 2025
96c49ac
add todos
hud10837 Jan 14, 2025
bac047a
rm tracking mode
hud10837 Jan 15, 2025
2190ccc
make initialization of LDS and Camera Feed sequential
hud10837 Jan 15, 2025
252338c
add permission state backup
hud10837 Jan 17, 2025
1395f78
fix permission state
hud10837 Jan 17, 2025
12c9a13
add doc
hud10837 Jan 17, 2025
717b0d9
fix usage of PermissionState in WSSV
hud10837 Jan 17, 2025
d997122
remove permissionstate from wssv
hud10837 Jan 17, 2025
c99b940
handle automatic permission request for wssv
hud10837 Jan 20, 2025
c06edcb
revert tabletop code
hud10837 Jan 20, 2025
7c42932
filter locations for world tracking
hud10837 Jan 21, 2025
b1ecc58
use nan for accuracy filtering and test
hud10837 Jan 21, 2025
80d8e71
eof newline
hud10837 Jan 21, 2025
0721ff1
add doc to TrackLocations fun and rm initialHeading
hud10837 Jan 21, 2025
97258fd
add doc to lds wrapper and copyrights
hud10837 Jan 21, 2025
5ed0dc6
Merge branch 'feature-branches/world-scale-scene-view' of https://git…
hud10837 Jan 21, 2025
79ccd2c
update api
hud10837 Jan 21, 2025
75a423a
use correct lifecycle
hud10837 Jan 21, 2025
e7f68b1
fix formatting
hud10837 Jan 22, 2025
a6708dd
use dleegated state
hud10837 Jan 22, 2025
d5ef304
use truth asserts
hud10837 Jan 23, 2025
57beacc
rename TrackLocationWithLocationDataSource -> LocationTracker
hud10837 Jan 23, 2025
b21ab92
centralize default values
hud10837 Jan 23, 2025
55851f9
hasSetOriginCamera and hasLaunchedRequest to non State
hud10837 Jan 23, 2025
d2f1dcb
rework permission request code to return state of permissions
hud10837 Jan 23, 2025
00a923c
start lds in onresume
hud10837 Jan 23, 2025
3224082
convert rememberPermissionsGranted to return State
hud10837 Jan 23, 2025
12e83bb
rm requestPermissionsAutomatically params
hud10837 Jan 23, 2025
00093f3
update comments on LocationDataSourceWrapper
hud10837 Jan 23, 2025
7eaccd8
update permission doc
hud10837 Jan 23, 2025
5c56467
reorder onDispose
hud10837 Jan 23, 2025
a57a634
simplify flow of code with early exits and make lds starting parallel…
hud10837 Jan 23, 2025
472bd42
subscribe to lifecycle for ArSessionWrapper inside remember function
hud10837 Jan 23, 2025
af811ed
move ArCore installed check to function
hud10837 Jan 24, 2025
4d0ec01
mv funs to ArHelpers
hud10837 Jan 24, 2025
9bba4d9
mv lds to LocationTracker
hud10837 Jan 24, 2025
70c3bb1
format
hud10837 Jan 27, 2025
57e3bce
refactor LDS wrapper creation
hud10837 Jan 27, 2025
b960c01
refactor LDS wrapper creation
hud10837 Jan 27, 2025
04a4af7
Update toolkit/ar/src/main/java/com/arcgismaps/toolkit/ar/WorldScaleS…
hud10837 Jan 27, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@ fun MainScreen() {
}
WorldScaleSceneView(
arcGISScene = arcGISScene,
locationDataSource = SystemLocationDataSource(),
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will no longer be passed in by the user

modifier = Modifier.fillMaxSize(),
onInitializationStatusChanged = {
Log.d("ArWorldScaleApp", "Initialization status changed: $it")
Expand Down
2 changes: 1 addition & 1 deletion toolkit/ar/api/ar.api
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ public final class com/arcgismaps/toolkit/ar/TableTopSceneViewStatusKt {
}

public final class com/arcgismaps/toolkit/ar/WorldScaleSceneViewKt {
public static final fun WorldScaleSceneView--aEHHIo (Lcom/arcgismaps/mapping/ArcGISScene;Lcom/arcgismaps/location/LocationDataSource;Landroidx/compose/ui/Modifier;Lkotlin/jvm/functions/Function1;ZLkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Ljava/util/List;Lcom/arcgismaps/toolkit/ar/WorldScaleSceneViewProxy;Lcom/arcgismaps/mapping/view/ViewLabelProperties;Lcom/arcgismaps/mapping/view/SelectionProperties;ZLkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Ljava/util/List;Ljava/util/List;Lcom/arcgismaps/mapping/TimeExtent;Lkotlin/jvm/functions/Function1;Ljava/time/Instant;Lcom/arcgismaps/mapping/view/LightingMode;JLkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function3;Landroidx/compose/runtime/Composer;IIIIII)V
public static final fun WorldScaleSceneView--aEHHIo (Lcom/arcgismaps/mapping/ArcGISScene;Landroidx/compose/ui/Modifier;Lkotlin/jvm/functions/Function1;ZZLkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Ljava/util/List;Lcom/arcgismaps/toolkit/ar/WorldScaleSceneViewProxy;Lcom/arcgismaps/mapping/view/ViewLabelProperties;Lcom/arcgismaps/mapping/view/SelectionProperties;ZLkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Ljava/util/List;Ljava/util/List;Lcom/arcgismaps/mapping/TimeExtent;Lkotlin/jvm/functions/Function1;Ljava/time/Instant;Lcom/arcgismaps/mapping/view/LightingMode;JLkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function3;Landroidx/compose/runtime/Composer;IIIIII)V
}

public final class com/arcgismaps/toolkit/ar/WorldScaleSceneViewProxy {
Expand Down
1 change: 1 addition & 0 deletions toolkit/ar/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ dependencies {
implementation(libs.androidx.lifecycle.runtime.ktx)
implementation(libs.androidx.activity.compose)
testImplementation(libs.bundles.unitTest)
androidTestImplementation(libs.truth)
androidTestImplementation(libs.bundles.composeTest)
debugImplementation(libs.bundles.debug)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
/*
*
* Copyright 2025 Esri
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/

package com.arcgismaps.toolkit.ar

import com.arcgismaps.geometry.Point
import com.arcgismaps.geometry.SpatialReference
import com.arcgismaps.location.Location
import com.arcgismaps.mapping.view.Camera
import com.google.common.truth.Truth.assertThat
import org.junit.Test
import java.time.Instant

/**
* Tests for the location filtering logic of the [WorldScaleSceneView]
*/
class LocationFilteringTests {

/**
* Given a location and a current camera,
* When the location is old, close to the camera, or inaccurate,
* Then the camera should not be updated
*
* When the location is recent and far away from the camera,
* Then the camera should be updated
*
* @since 200.7.0
*/
@Test
fun testLocationFilter() {
val nullIsland = Point(0.0, 0.0, SpatialReference.wgs84())
val farFarAway = Point(10.0, 10.0, SpatialReference.wgs84())

val cameraAtNullIsland = Camera(nullIsland, 0.0, 0.0, 0.0)

val recentLocationAtNullIsland =
Location.create(nullIsland, 1.0, 1.0, 0.0, 0.0, true, Instant.now().minusMillis(50))
val oldLocationAtNullIsland =
Location.create(nullIsland, 1.0, 1.0, 0.0, 0.0, true, Instant.now().minusMillis(30000))
val recentLocationFarFarAway =
Location.create(farFarAway, 1.0, 1.0, 0.0, 0.0, true, Instant.now().minusMillis(50))
val oldLocationFarFarAway =
Location.create(farFarAway, 1.0, 1.0, 0.0, 0.0, true, Instant.now().minusMillis(30000))
val recentLocationWithNoAccuracy = Location.create(
nullIsland,
Double.NaN,
Double.NaN,
0.0,
0.0,
false,
Instant.now().minusMillis(50)
)

assertThat(shouldUpdateCamera(recentLocationAtNullIsland, cameraAtNullIsland)).isFalse()
assertThat(shouldUpdateCamera(oldLocationAtNullIsland, cameraAtNullIsland)).isFalse()
assertThat(shouldUpdateCamera(oldLocationFarFarAway, cameraAtNullIsland)).isFalse()
assertThat(shouldUpdateCamera(recentLocationWithNoAccuracy, cameraAtNullIsland)).isFalse()

assertThat(shouldUpdateCamera(recentLocationFarFarAway, cameraAtNullIsland)).isTrue()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,11 @@

package com.arcgismaps.toolkit.ar

import android.Manifest
import android.content.Context
import android.content.pm.PackageManager
import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unused import

import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.SideEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
Expand All @@ -38,7 +32,6 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalLifecycleOwner
import androidx.core.content.ContextCompat
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.arcgismaps.geometry.Point
import com.arcgismaps.geometry.SpatialReference
Expand All @@ -50,7 +43,6 @@ import com.arcgismaps.mapping.view.AnalysisOverlay
import com.arcgismaps.mapping.view.AtmosphereEffect
import com.arcgismaps.mapping.view.AttributionBarLayoutChangeEvent
import com.arcgismaps.mapping.view.Camera
import com.arcgismaps.mapping.view.DeviceOrientation
import com.arcgismaps.mapping.view.DoubleTapEvent
import com.arcgismaps.mapping.view.DownEvent
import com.arcgismaps.mapping.view.GeoView
Expand Down Expand Up @@ -81,10 +73,7 @@ import com.arcgismaps.toolkit.geoviewcompose.SceneView
import com.arcgismaps.toolkit.geoviewcompose.SceneViewDefaults
import com.google.ar.core.Anchor
import com.google.ar.core.ArCoreApk
import com.google.ar.core.Pose
import kotlinx.coroutines.suspendCancellableCoroutine
import java.time.Instant
import kotlin.coroutines.resume

/**
* A scene view that provides an augmented reality table top experience.
Expand Down Expand Up @@ -227,17 +216,11 @@ public fun TableTopSceneView(
if (cameraPermissionGranted && arCoreInstalled) {
val arSessionWrapper =
rememberArSessionWrapper(applicationContext = context.applicationContext)
DisposableEffect(Unit) {
// We call this from inside DisposableEffect so that we invoke the callback in a side effect
SideEffect {
initializationStatus.update(
TableTopSceneViewStatus.DetectingPlanes,
onInitializationStatusChanged
)
lifecycleOwner.lifecycle.addObserver(arSessionWrapper)
onDispose {
lifecycleOwner.lifecycle.removeObserver(arSessionWrapper)
arSessionWrapper.onDestroy(lifecycleOwner)
}
}
val identityMatrix = remember { TransformationMatrix.createIdentityMatrix() }
val session = arSessionWrapper.session.collectAsStateWithLifecycle()
Expand Down
Loading