Come creare e individuare ancoraggi usando Ancoraggi nello spazio di Azure in Java
Ancoraggi nello spazio di Azure è un servizio che consente di condividere ancoraggi nel mondo tra dispositivi diversi. Supporta vari ambienti di sviluppo differenti. Questo articolo esaminerà come usare l'SDK degli Ancoraggi nello spazio di Azure, in Java, per:
- Configurare e gestire in modo corretto una sessione di Ancoraggi nello spazio di Azure.
- Creare e impostare le proprietà sugli ancoraggi locali.
- Caricarli nel cloud.
- Trovare ed eliminare gli ancoraggi nello spazio nel cloud.
Prerequisiti
Per completare le procedure contenute in questa guida, verificare che siano soddisfatti i requisti seguenti:
- Letto la Panoramica di ancoraggi nello spazio di Azure.
- Completato uno degli argomenti di avvio rapido di 5 minuti.
- Conoscenze di base di Java.
- Conoscenze di base di ARCore.
Inizializzare la sessione
Il punto di ingresso principale dell'SDK è la classe che rappresenta la sessione. In genere nella classe si dichiara un campo che gestisce la visualizzazione e la sessione AR nativa.
Altre informazioni sulla classe CloudSpatialAnchorSession.
private CloudSpatialAnchorSession mCloudSession;
// In your view handler
mCloudSession = new CloudSpatialAnchorSession();
Configurazione dell'autenticazione
Per accedere al servizio, è necessario fornire una chiave dell'account, un token di accesso o un token di autenticazione di Microsoft Entra. Per altre informazioni, vedere la pagina relativa al concetto di autenticazione.
Chiavi dell'account
Le chiavi dell'account sono credenziali che consentono all'applicazione di eseguire l'autenticazione con il servizio degli ancoraggi nello spazio di Azure. Le chiavi dell'account consentono di essere subito operativi, soprattutto durante la fase di sviluppo dell'integrazione dell'applicazione con gli ancoraggi nello spazio di Azure. Di conseguenza, è possibile usare le chiavi dell'account incorporandole nelle applicazioni client durante lo sviluppo. Man mano che si procede oltre lo sviluppo, è consigliabile passare a un meccanismo di autenticazione a livello di produzione, supportato dai token di accesso o dall'autenticazione utente di Microsoft Entra. Per ottenere una chiave dell'account per lo sviluppo, visitare l'account ancoraggi nello spazio di Azure e passare alla scheda "Chiavi".
Altre informazioni sulla classe SessionConfiguration.
mCloudSession.getConfiguration().setAccountKey("MyAccountKey");
Token di accesso
I token di accesso sono un metodo più affidabile per l'autenticazione con gli ancoraggi nello spazio di Azure, soprattutto quando si prepara l'applicazione per una distribuzione di produzione. Il riepilogo di questo approccio consiste nel configurare un servizio back-end con cui l'applicazione client può eseguire l'autenticazione in modo sicuro. Il servizio back-end si interfaccia con AAD in fase di esecuzione e con il servizio token sicuro degli ancoraggi nello spazio di Azure per richiedere un token di accesso. Questo token viene quindi distribuito all'applicazione client e usato nell'SDK per eseguire l'autenticazione con gli ancoraggi nello spazio di Azure.
mCloudSession.getConfiguration().setAccessToken("MyAccessToken");
Se non è impostato alcun token di accesso, è necessario gestire l'evento TokenRequired
oppure implementare il metodo tokenRequired
per il protocollo delegato.
È possibile gestire l'evento in modo sincrono impostando la proprietà sugli argomenti dell'evento.
Altre informazioni sull'interfaccia TokenRequiredListener.
mCloudSession.addTokenRequiredListener(args -> {
args.setAccessToken("MyAccessToken");
});
Se è necessario eseguire operazioni asincrone nel gestore, è possibile rinviare l'impostazione del token richiedendo un oggetto deferral
e quindi completarlo, come nell'esempio seguente.
mCloudSession.addTokenRequiredListener(args -> {
CloudSpatialAnchorSessionDeferral deferral = args.getDeferral();
MyGetTokenAsync(myToken -> {
if (myToken != null) args.setAccessToken(myToken);
deferral.complete();
});
});
Autenticazione Microsoft Entra
Ancoraggi nello spazio di Azure consente anche alle applicazioni di eseguire l'autenticazione con token microsoft Entra ID (Active Directory). Ad esempio, è possibile usare i token Microsoft Entra per l'integrazione con Ancoraggi nello spazio di Azure. Se un'azienda gestisce gli utenti in Microsoft Entra ID, è possibile fornire un token Microsoft Entra utente in Azure Spatial Anchors SDK. In questo modo è possibile eseguire l'autenticazione direttamente nel servizio Ancoraggi nello spazio di Azure per un account che fa parte dello stesso tenant di Microsoft Entra.
mCloudSession.getConfiguration().setAuthenticationToken("MyAuthenticationToken");
Analogamente ai token di accesso, se non è impostato un token Microsoft Entra, è necessario gestire l'evento TokenRequired o implementare il metodo tokenRequired nel protocollo delegato.
È possibile gestire l'evento in modo sincrono impostando la proprietà sugli argomenti dell'evento.
mCloudSession.addTokenRequiredListener(args -> {
args.setAuthenticationToken("MyAuthenticationToken");
});
Se è necessario eseguire operazioni asincrone nel gestore, è possibile rinviare l'impostazione del token richiedendo un oggetto deferral
e quindi completarlo, come nell'esempio seguente.
mCloudSession.addTokenRequiredListener(args -> {
CloudSpatialAnchorSessionDeferral deferral = args.getDeferral();
MyGetTokenAsync(myToken -> {
if (myToken != null) args.setAuthenticationToken(myToken);
deferral.complete();
});
});
Configurare la sessione
Richiamare Start()
per consentire alla sessione di elaborare i dati dell'ambiente.
Per gestire gli eventi generati dalla sessione, collegare un gestore eventi.
mCloudSession.setSession(mSession);
mCloudSession.start();
Fornire fotogrammi alla sessione
Durante la sessione di ancoraggio nello spazio viene eseguito il mapping dello spazio intorno all'utente. Questa operazione consente di determinare dove si trovano gli ancoraggi. Le piattaforme per dispositivi mobili (iOS e Android) richiedono una chiamata nativa al feed della fotocamera per ottenere i fotogrammi dalla libreria AR della piattaforma. Al contrario, HoloLens analizza continuamente l'ambiente e, di conseguenza, non è necessario eseguire una chiamata specifica come avviene nelle piattaforme per dispositivi mobili.
mCloudSession.processFrame(mSession.update());
Fornire feedback all'utente
È possibile scrivere codice per gestire l'evento di aggiornamento della sessione. Questo evento viene generato ogni volta che la sessione migliora il riconoscimento dell'ambiente circostante. In questo modo è possibile:
- Usare la classe
UserFeedback
per fornire feedback all'utente quando il dispositivo viene spostato e la sessione aggiorna il riconoscimento dell'ambiente. A tale scopo, seguire questa procedura: - Determinare in quale punto sono disponibili dati spaziali rilevati sufficienti per creare ancoraggi nello spazio. Per questa operazione si usa
ReadyForCreateProgress
oRecommendedForCreateProgress
. Quando il valore diReadyForCreateProgress
è maggiore di 1, i dati disponibili sono sufficienti per salvare un ancoraggio nello spazio cloud, anche se è consigliabile attendere fino a quando il valore diRecommendedForCreateProgress
non diventa maggiore di 1.
Altre informazioni sull'interfaccia SessionUpdatedListener.
mCloudSession.addSessionUpdatedListener(args -> {
auto status = args->Status();
if (status->UserFeedback() == SessionUserFeedback::None) return;
NumberFormat percentFormat = NumberFormat.getPercentInstance();
percentFormat.setMaximumFractionDigits(1);
mFeedback = String.format("Feedback: %s - Recommend Create=%s",
FeedbackToString(status.getUserFeedback()),
percentFormat.format(status.getRecommendedForCreateProgress()));
});
Creare un ancoraggio nello spazio cloud
Per creare un ancoraggio nello spazio cloud, creare prima un ancoraggio nel sistema AR della piattaforma e quindi una controparte cloud. A questo scopo, usare il metodo CreateAnchorAsync()
.
Altre informazioni sulla classe CloudSpatialAnchor.
// Create a local anchor, perhaps by hit-testing and creating an ARAnchor
Anchor localAnchor = null;
List<HitResult> hitResults = mSession.update().hitTest(0.5f, 0.5f);
for (HitResult hit : hitResults) {
Trackable trackable = hit.getTrackable();
if (trackable instanceof Plane) {
if (((Plane) trackable).isPoseInPolygon(hit.getHitPose())) {
localAnchor = hit.createAnchor();
break;
}
}
}
// If the user is placing some application content in their environment,
// you might show content at this anchor for a while, then save when
// the user confirms placement.
CloudSpatialAnchor cloudAnchor = new CloudSpatialAnchor();
cloudAnchor.setLocalAnchor(localAnchor);
Future createAnchorFuture = mCloudSession.createAnchorAsync(cloudAnchor);
CheckForCompletion(createAnchorFuture, cloudAnchor);
// ...
private void CheckForCompletion(Future createAnchorFuture, CloudSpatialAnchor cloudAnchor) {
new android.os.Handler().postDelayed(() -> {
if (createAnchorFuture.isDone()) {
try {
createAnchorFuture.get();
mFeedback = String.format("Created a cloud anchor with ID=%s", cloudAnchor.getIdentifier());
}
catch(InterruptedException e) {
mFeedback = String.format("Save Failed:%s", e.getMessage());
}
catch(ExecutionException e) {
mFeedback = String.format("Save Failed:%s", e.getMessage());
}
}
else {
CheckForCompletion(createAnchorFuture, cloudAnchor);
}
}, 500);
}
Come descritto in precedenza, è necessario acquisire dati di ambiente sufficienti prima di provare a creare un nuovo ancoraggio nello spazio cloud. Questo significa che il valore di ReadyForCreateProgress
deve essere maggiore di 1, anche se è consigliabile attendere fino a quando il valore di RecommendedForCreateProgress
non diventa maggiore di 1.
Future<SessionStatus> sessionStatusFuture = mCloudSession.getSessionStatusAsync();
CheckForCompletion(sessionStatusFuture);
// ...
private void CheckForCompletion(Future<SessionStatus> sessionStatusFuture) {
new android.os.Handler().postDelayed(() -> {
if (sessionStatusFuture.isDone()) {
try {
SessionStatus value = sessionStatusFuture.get();
if (value.getRecommendedForCreateProgress() < 1.0f) return;
// Issue the creation request...
}
catch(InterruptedException e) {
mFeedback = String.format("Session status error:%s", e.getMessage());
}
catch(ExecutionException e) {
mFeedback = String.format("Session status error:%s", e.getMessage());
}
}
else {
CheckForCompletion(sessionStatusFuture);
}
}, 500);
}
Impostare le proprietà
Quando si salvano gli ancoraggi nello spazio cloud, è possibile scegliere di aggiungere alcune proprietà, ad esempio il tipo di oggetto da salvare oppure proprietà di base relative all'abilitazione per l'interazione. Questa operazione può essere utile al momento dell'individuazione. È infatti possibile eseguire immediatamente il rendering dell'oggetto per l'utente, ad esempio un fotogramma immagine con contenuto vuoto. Con un download diverso in background si ottengono quindi altri dettagli sullo stato, ad esempio l'immagine da visualizzare nel fotogramma.
CloudSpatialAnchor cloudAnchor = new CloudSpatialAnchor();
cloudAnchor.setLocalAnchor(localAnchor);
Map<String,String> properties = cloudAnchor.getAppProperties();
properties.put("model-type", "frame");
properties.put("label", "my latest picture");
Future createAnchorFuture = mCloudSession.createAnchorAsync(cloudAnchor);
// ...
Aggiornare le proprietà
Per aggiornare le proprietà di un ancoraggio, si usa il metodo UpdateAnchorProperties()
. Se due o più dispositivi provano ad aggiornare le proprietà per lo stesso ancoraggio nello stesso momento, viene usato un modello di concorrenza ottimistica, in base al quale prevale la prima operazione di scrittura eseguita. Per tutte le altre operazioni di scrittura verrà restituito un errore di "concorrenza" e sarà necessario aggiornare le proprietà prima di riprovare.
CloudSpatialAnchor anchor = /* locate your anchor */;
anchor.getAppProperties().put("last-user-access", "just now");
Future updateAnchorPropertiesFuture = mCloudSession.updateAnchorPropertiesAsync(anchor);
CheckForCompletion(updateAnchorPropertiesFuture);
// ...
private void CheckForCompletion(Future updateAnchorPropertiesFuture) {
new android.os.Handler().postDelayed(() -> {
if (updateAnchorPropertiesFuture.isDone()) {
try {
updateAnchorPropertiesFuture.get();
}
catch(InterruptedException e) {
mFeedback = String.format("Updating Properties Failed:%s", e.getMessage());
}
catch(ExecutionException e) {
mFeedback = String.format("Updating Properties Failed:%s", e.getMessage());
}
}
else {
CheckForCompletion1(updateAnchorPropertiesFuture);
}
}, 500);
}
Non è possibile aggiornare la posizione di un ancoraggio dopo che è stata creato nel servizio, ma è necessario creare un nuovo ancoraggio ed eliminare quello precedente per tenere traccia di una nuova posizione.
Se non è necessario individuare un ancoraggio per aggiornarne le proprietà, è possibile usare il metodo GetAnchorPropertiesAsync()
, che restituisce un oggetto CloudSpatialAnchor
con le proprietà.
Future<CloudSpatialAnchor> getAnchorPropertiesFuture = mCloudSession.getAnchorPropertiesAsync("anchorId");
CheckForCompletion(getAnchorPropertiesFuture);
// ...
private void CheckForCompletion(Future<CloudSpatialAnchor> getAnchorPropertiesFuture) {
new android.os.Handler().postDelayed(() -> {
if (getAnchorPropertiesFuture.isDone()) {
try {
CloudSpatialAnchor anchor = getAnchorPropertiesFuture.get();
if (anchor != null) {
anchor.getAppProperties().put("last-user-access", "just now");
Future updateAnchorPropertiesFuture = mCloudSession.updateAnchorPropertiesAsync(anchor);
// ...
}
} catch (InterruptedException e) {
mFeedback = String.format("Getting Properties Failed:%s", e.getMessage());
} catch (ExecutionException e) {
mFeedback = String.format("Getting Properties Failed:%s", e.getMessage());
}
} else {
CheckForCompletion(getAnchorPropertiesFuture);
}
}, 500);
}
Imposta scadenza
È anche possibile configurare l'ancoraggio in modo che scada automaticamente in una data specifica in futuro. Un ancoraggio scaduto non viene più individuato né aggiornato. La scadenza può essere impostata solo quando viene creato l'ancoraggio, prima di salvarlo nel cloud. e non può essere aggiornata in un secondo momento. Se non viene impostata alcuna scadenza durante la creazione dell'ancoraggio, l'ancoraggio scadrà solo quando viene eliminato manualmente.
Date now = new Date();
Calendar cal = Calendar.getInstance();
cal.setTime(now);
cal.add(Calendar.DATE, 7);
Date oneWeekFromNow = cal.getTime();
cloudAnchor.setExpiration(oneWeekFromNow);
Individuare un ancoraggio nello spazio cloud
La possibilità di individuare un ancoraggio nello spazio cloud salvato in precedenza è uno dei motivi principali per usare gli ancoraggi nello spazio di Azure. Per questo motivo, usiamo "Watchers". È possibile usare un solo Watcher alla volta; più watcher non sono supportati. Esistono diversi modi (noti anche come strategie di individuazione ancoraggio) che un Watcher può individuare un ancoraggio nello spazio cloud. È possibile usare una strategia in un watcher alla volta.
- Individuare gli ancoraggi in base all'identificatore.
- Individuare gli ancoraggi connessi a un ancoraggio individuato in precedenza. Per altre informazioni sulle relazioni tra ancoraggi, vedere qui.
- Individuare un ancoraggio tramite la rilocalizzazione grossolana.
Nota
Ogni volta che si individua un ancoraggio, Ancoraggi nello spazio di Azure proverà a usare i dati dell'ambiente raccolti per incrementare le informazioni che visualizza. Se si verificano problemi durante l'individuazione di un ancoraggio, può essere utile creare un ancoraggio, quindi individuarlo più volte da varie angolazioni e con condizioni di illuminazione diverse.
Se si individuano ancoraggi nello spazio cloud in base all'identificatore, è possibile archiviare l'identificatore di ancoraggio nello spazio cloud nel servizio back-end dell'applicazione e renderlo accessibile a tutti i dispositivi che possono eseguire correttamente l'autenticazione. Per un esempio, vedere Esercitazione: Condividere ancoraggi nello spazio tra dispositivi.
Creare un'istanza dell'oggetto AnchorLocateCriteria
, impostare gli identificatori da cercare e richiamare il metodo CreateWatcher
nella sessione specificando AnchorLocateCriteria
.
AnchorLocateCriteria criteria = new AnchorLocateCriteria();
criteria.setIdentifiers(new String[] { "id1", "id2", "id3" });
mCloudSession.createWatcher(criteria);
Dopo la creazione del Watcher, l'evento AnchorLocated
viene attivato per ogni ancoraggio richiesto. Questo evento viene generato quando viene individuato un ancoraggio o se non è possibile individuarlo. Se si verifica questa situazione, il motivo verrà indicato nello stato. Dopo che tutti gli ancoraggi per un Watcher vengono elaborati, che siano stati trovati o no, viene generato l'evento LocateAnchorsCompleted
. È previsto un limite di 35 identificatori per Watcher.
Altre informazioni sull'interfaccia AnchorLocatedListener.
mCloudSession.addAnchorLocatedListener(args -> {
switch (args.getStatus()) {
case Located:
CloudSpatialAnchor foundAnchor = args.getAnchor();
// Go add your anchor to the scene...
break;
case AlreadyTracked:
// This anchor has already been reported and is being tracked
break;
case NotLocatedAnchorDoesNotExist:
// The anchor was deleted or never existed in the first place
// Drop it, or show UI to ask user to anchor the content anew
break;
case NotLocated:
// The anchor hasn't been found given the location data
// The user might in the wrong location, or maybe more data will help
// Show UI to tell user to keep looking around
break;
}
});
Eliminare gli ancoraggi
L'eliminazione di ancoraggi quando non sono più in uso è una prassi valida da includere nelle prime fasi del processo e delle procedure di sviluppo, per mantenere pulite le risorse di Azure.
Future deleteAnchorFuture = mCloudSession.deleteAnchorAsync(cloudAnchor);
// Perform any processing you may want when delete finishes (deleteAnchorFuture is done)
Sospendere, reimpostare o arrestare la sessione
Per arrestare temporaneamente la sessione, è possibile richiamare Stop()
. In questo modo verranno arrestati tutti i watcher oltre all'elaborazione dell'ambiente, anche se si richiama ProcessFrame()
. È quindi possibile richiamare Start()
per riprendere l'elaborazione. Quando si riprende l'elaborazione, i dati dell'ambiente già acquisiti nella sessione vengono mantenuti.
mCloudSession.stop();
Per reimpostare i dati dell'ambiente acquisiti nella sessione, è possibile richiamare Reset()
.
mCloudSession.reset();
Per eseguire correttamente la pulizia dopo una sessione, richiamare close()
.
mCloudSession.close();
Passaggi successivi
In questa guida si è appreso come creare e individuare ancoraggi usando Azure Spatial Anchors SDK. Per altre informazioni sulle relazioni tra ancoraggi, passare alla guida successiva.