Crea un'app di navigazione

Questa pagina descrive le diverse funzionalità della raccolta di app per auto che puoi utilizzare per implementare la funzionalità della tua app di navigazione passo passo.

Dichiarare il supporto della navigazione nel file manifest

L'app di navigazione deve dichiarare la androidx.car.app.category.NAVIGATION categoria di app per auto nel filtro per intent del suo CarAppService:

<application>
    ...
   <service
       ...
        android:name=".MyNavigationCarAppService"
        android:exported="true">
      <intent-filter>
        <action android:name="androidx.car.app.CarAppService" />
        <category android:name="androidx.car.app.category.NAVIGATION"/>
      </intent-filter>
    </service>
    ...
</application>

Supporta gli intent di navigazione

Per supportare le intent di navigazione per la tua app, incluse quelle provenienti dall'Assistente Google tramite una query vocale, la tua app deve gestire l'intent CarContext.ACTION_NAVIGATE nel suo Session.onCreateScreen e Session.onNewIntent.

Per informazioni dettagliate sul formato dell'intent, consulta la documentazione relativa a CarContext.startCarApp.

Accedere ai modelli di navigazione

Le app di navigazione possono accedere ai seguenti modelli, che mostrano una superficie in background con la mappa e, durante la navigazione attiva, le indicazioni stradali passo passo.

  • NavigationTemplate: visualizza anche un messaggio informativo facoltativo e le stime di viaggio durante la navigazione attiva.
  • MapWithContentTemplate: un modello che consente a un'app di visualizzare riquadri della mappa con alcuni tipi di contenuti (ad es. un elenco). I contenuti vengono solitamente visualizzati come overlay sopra i riquadri della mappa, con le aree stabili e visibili della mappa che si adattano ai contenuti.

Per ulteriori dettagli su come progettare l'interfaccia utente dell'app di navigazione utilizzando questi modelli, consulta App di navigazione.

Per accedere ai modelli di navigazione, l'app deve dichiarare l'autorizzazione androidx.car.app.NAVIGATION_TEMPLATES nel file AndroidManifest.xml:

<manifest ...>
  ...
  <uses-permission android:name="androidx.car.app.NAVIGATION_TEMPLATES"/>
  ...
</manifest>

Per disegnare mappe è necessaria un'autorizzazione aggiuntiva.

Esegui la migrazione a MapWithContentTemplate

A partire dal livello 7 dell'API Car App, i valori MapTemplate, PlaceListNavigationTemplate e RoutePreviewNavigationTemplate sono ritirati. I modelli ritirati continueranno a essere supportati, ma è vivamente consigliata la migrazione a MapWithContentTemplate.

La funzionalità fornita da questi modelli può essere implementata utilizzando MapWithContentTemplate. Di seguito sono riportati alcuni esempi di snippet:

MapTemplate

Kotlin

// MapTemplate (deprecated)
val template = MapTemplate.Builder()
    .setPane(paneBuilder.build())
    .setActionStrip(actionStrip)
    .setHeader(header)
    .setMapController(mapController)
    .build()

// MapWithContentTemplate
val template = MapWithContentTemplate.Builder()
    .setContentTemplate(
        PaneTemplate.Builder(paneBuilder.build())
            .setHeader(header)
            .build())
    .setActionStrip(actionStrip)
    .setMapController(mapController)
    .build()

Java

// MapTemplate (deprecated)
MapTemplate template = new MapTemplate.Builder()
    .setPane(paneBuilder.build())
    .setActionStrip(actionStrip)
    .setHeader(header)
    .setMapController(mapController)
    .build();

// MapWithContentTemplate
MapWithContentTemplate template = new MapWithContentTemplate.Builder()
    .setContentTemplate(new PaneTemplate.Builder(paneBuilder.build())
        .setHeader(header)
        build())
    .setActionStrip(actionStrip)
    .setMapController(mapController)
    .build();

PlaceListNavigationTemplate

Kotlin

// PlaceListNavigationTemplate (deprecated)
val template = PlaceListNavigationTemplate.Builder()
    .setItemList(itemListBuilder.build())
    .setHeader(header)
    .setActionStrip(actionStrip)
    .setMapActionStrip(mapActionStrip)
    .build()

// MapWithContentTemplate
val template = MapWithContentTemplate.Builder()
    .setContentTemplate(
        ListTemplate.Builder()
            .setSingleList(itemListBuilder.build())
            .setHeader(header)
            .build())
    .setActionStrip(actionStrip)
    .setMapController(
        MapController.Builder()
            .setMapActionStrip(mapActionStrip)
            .build())
    .build()

Java

// PlaceListNavigationTemplate (deprecated)
PlaceListNavigationTemplate template = new PlaceListNavigationTemplate.Builder()
    .setItemList(itemListBuilder.build())
    .setHeader(header)
    .setActionStrip(actionStrip)
    .setMapActionStrip(mapActionStrip)
    .build();

// MapWithContentTemplate
MapWithContentTemplate template = new MapWithContentTemplate.Builder()
    .setContentTemplate(new ListTemplate.Builder()
        .setSingleList(itemListBuilder.build())
        .setHeader(header)
        .build())
    .setActionStrip(actionStrip)
    .setMapController(new MapController.Builder()
        .setMapActionStrip(mapActionStrip)
        .build())
    .build();

RoutePreviewNavigationTemplate

Kotlin

// RoutePreviewNavigationTemplate (deprecated)
val template = RoutePreviewNavigationTemplate.Builder()
    .setItemList(
        ItemList.Builder()
            .addItem(
                Row.Builder()
                    .setTitle(title)
                    .build())
            .build())
    .setHeader(header)
    .setNavigateAction(
        Action.Builder()
            .setTitle(actionTitle)
            .setOnClickListener { ... }
            .build())
    .setActionStrip(actionStrip)
    .setMapActionStrip(mapActionStrip)
    .build()

// MapWithContentTemplate
val template = MapWithContentTemplate.Builder()
    .setContentTemplate(
        ListTemplate.Builder()
            .setSingleList(
                ItemList.Builder()
                    .addItem(
                        Row.Builder()
                            .setTitle(title)
                            .addAction(
                                Action.Builder()
                                    .setTitle(actionTitle)
                                    .setOnClickListener { ... }
                                    .build())
                            .build())
                    .build())
            .setHeader(header)
            .build())
    .setActionStrip(actionStrip)
    .setMapController(
        MapController.Builder()
            .setMapActionStrip(mapActionStrip)
            .build())
    .build()

Java

// RoutePreviewNavigationTemplate (deprecated)
RoutePreviewNavigationTemplate template = new RoutePreviewNavigationTemplate.Builder()
    .setItemList(new ItemList.Builder()
        .addItem(new Row.Builder()
            .setTitle(title))
            .build())
        .build())
    .setHeader(header)
    .setNavigateAction(new Action.Builder()
        .setTitle(actionTitle)
        .setOnClickListener(() -> { ... })
        .build())
    .setActionStrip(actionStrip)
    .setMapActionStrip(mapActionStrip)
    .build();

// MapWithContentTemplate
MapWithContentTemplate template = new MapWithContentTemplate.Builder()
    .setContentTemplate(new ListTemplate.Builder()
        .setSingleList(new ItemList.Builder()
            .addItem(new Row.Builder()
                  .setTitle(title))
                  .addAction(new Action.Builder()
                      .setTitle(actionTitle)
                      .setOnClickListener(() -> { ... })
                      .build())
                  .build())
            .build()))
        .setHeader(header)
        .build())
    .setActionStrip(actionStrip)
    .setMapController(new MapController.Builder()
        .setMapActionStrip(mapActionStrip)
        .build())
    .build();

Le app di navigazione devono comunicare metadati di navigazione aggiuntivi con l'host. L'host utilizza le informazioni per fornire informazioni all'unità principale del veicolo e per evitare conflitti tra le applicazioni di navigazione per le risorse condivise.

I metadati di navigazione vengono forniti tramite il servizio per auto NavigationManager accessibile da CarContext:

Kotlin

val navigationManager = carContext.getCarService(NavigationManager::class.java)

Java

NavigationManager navigationManager = carContext.getCarService(NavigationManager.class);

Avviare, terminare e interrompere la navigazione

Affinché l'host possa gestire più app di navigazione, notifiche relative al routing e dati dei cluster di veicoli, deve essere a conoscenza dello stato corrente della navigazione. Quando un utente avvia la navigazione, chiama NavigationManager.navigationStarted. Analogamente, quando la navigazione termina, ad esempio quando l'utente arriva a destinazione o annulla la navigazione, chiama NavigationManager.navigationEnded.

Chiama NavigationManager.navigationEnded solo quando l'utente termina la navigazione. Ad esempio, se devi ricalcolare il percorso nel bel mezzo di un viaggio, utilizza Trip.Builder.setLoading(true).

A volte, l'host ha bisogno di un'app per interrompere la navigazione e le chiamateonStopNavigation in un oggetto NavigationManagerCallback fornito dalla tua app tramite NavigationManager.setNavigationManagerCallback. L'app deve quindi interrompere l'invio di informazioni sulla svolta successiva nel display del cluster, nelle notifiche di navigazione e nella guida vocale.

Aggiornare le informazioni sulla corsa

Durante la navigazione attiva, chiama NavigationManager.updateTrip. Le informazioni fornite in questa chiamata possono essere utilizzate dal quadro strumenti e dal display a sovrimpressione del veicolo. A seconda del veicolo guidato, non tutte le informazioni vengono mostrate all'utente. Ad esempio, la DHU (unità principale desktop) mostra Step aggiunto a Trip, ma non mostra le informazioni su Destination.

Disegno sul display del cluster

Per offrire un'esperienza utente più coinvolgente, ti consigliamo di andare oltre la visualizzazione dei metadati di base sul display del cruscotto del veicolo. A partire dal livello 6 dell'API Car App, le app di navigazione hanno la possibilità di eseguire il rendering degli propri contenuti direttamente sul display del cruscotto (nei veicoli supportati), con le seguenti limitazioni:

  • L'API di visualizzazione del cluster non supporta i controlli di immissione
  • Norme sulla qualità delle app per auto NF-9: Il display del cluster deve mostrare solo riquadri della mappa. Se vuoi, su questi riquadri puoi visualizzare un percorso di navigazione attivo.
  • L'API di visualizzazione del cluster supporta solo l'utilizzo del NavigationTemplate
    • A differenza dei display principali, i display cluster potrebbero non mostrare in modo coerente tutti gli elementi dell'interfaccia utente di NavigationTemplate, come le istruzioni stradali passo passo, le schede con l'orario di arrivo stimato e le azioni. I riquadri della mappa sono l'unico elemento della UI visualizzato in modo coerente.

Dichiarare il supporto del cluster

Per comunicare all'applicazione host che la tua app supporta il rendering su display di cluster, devi aggiungere un elemento androidx.car.app.category.FEATURE_CLUSTER <category> a <intent-filter> di CarAppService, come mostrato nel seguente snippet:

<application>
    ...
   <service
       ...
        android:name=".MyNavigationCarAppService"
        android:exported="true">
      <intent-filter>
        <action android:name="androidx.car.app.CarAppService" />
        <category android:name="androidx.car.app.category.NAVIGATION"/>
        <category android:name="androidx.car.app.category.FEATURE_CLUSTER"/>
      </intent-filter>
    </service>
    ...
</application>

Gestione del ciclo di vita e dello stato

A partire dal livello 6 dell'API, il flusso di vita dell'app per auto rimane invariato, ma ora CarAppService::onCreateSession accetta un parametro di tipo SessionInfo che fornisce informazioni aggiuntive sul Session in fase di creazione (ovvero il tipo di visualizzazione e l'insieme di modelli supportati).

Le app hanno la possibilità di utilizzare la stessa classe Session per gestire sia il cluster sia il display principale oppure di creare Sessions specifici per il display per personalizzare il comportamento su ogni display (come mostrato nello snippet seguente).

Kotlin

override fun onCreateSession(sessionInfo: SessionInfo): Session {
  return if (sessionInfo.displayType == SessionInfo.DISPLAY_TYPE_CLUSTER) {
    ClusterSession()
  } else {
    MainDisplaySession()
  }
}

Java

@Override
@NonNull
public Session onCreateSession(@NonNull SessionInfo sessionInfo) {
  if (sessionInfo.getDisplayType() == SessionInfo.DISPLAY_TYPE_CLUSTER) {
    return new ClusterSession();
  } else {
    return new MainDisplaySession();
  }
}

Non ci sono garanzie su quando o se viene fornito il display del cluster ed è anche possibile che il cluster Session sia l'unico Session (ad esempio, l'utente ha scambiato il display principale con un'altra app mentre la tua app è in navigazione attiva). Il contratto "standard" prevede che l'app acquisisca il controllo della visualizzazione del cluster solo dopo che è stata invocata NavigationManager::navigationStarted. Tuttavia, è possibile che all'app venga fornito il display del cluster quando non è in corso alcuna navigazione attiva o che non venga mai fornito il display del cluster. Spetta all'app gestire questi scenari eseguendo il rendering dello stato inattivo delle schede della mappa.

L'host crea istanze di binder e CarContext separate per Session. Ciò significa che, quando utilizzi metodi come ScreenManager::push o Screen::invalidate, viene interessato solo il Session da cui vengono chiamati. Le app devono creare i propri canali di comunicazione tra queste istanze se è necessaria la comunicazione tra più Session (ad esempio, utilizzando trasmissioni, un singleton condiviso o altro).

Assistenza per i cluster di test

Puoi testare l'implementazione sia su Android Auto che su Android Automotive OS. Per Android Auto, questo viene fatto configurando l'unità principale del computer per emulare un display del cruscotto secondario. Per Android Automotive OS, le immagini di sistema generiche per il livello API 30 e versioni successive simulano un display del cluster.

Personalizzare la stima dei tempi di percorrenza con testo o icona

Per personalizzare la stima del viaggio con testo, un'icona o entrambi, utilizza i metodi della classe setTripIcon o setTripText.TravelEstimate.Builder NavigationTemplate utilizza TravelEstimate per impostare facoltativamente testo e icone accanto o al posto dell'orario di arrivo stimato, del tempo rimanente e della distanza rimanente.

Figura 1. Stima del viaggio con icona e testo personalizzati.

Lo snippet seguente utilizza setTripIcon e setTripText per personalizzare la stima del viaggio:

Kotlin

TravelEstimate.Builder(Distance.create(...), DateTimeWithZone.create(...))
      ...
      .setTripIcon(CarIcon.Builder(...).build())
      .setTripText(CarText.create(...))
      .build()

Java

new TravelEstimate.Builder(Distance.create(...), DateTimeWithZone.create(...))
      ...
      .setTripIcon(CarIcon.Builder(...).build())
      .setTripText(CarText.create(...))
      .build();

Fornire notifiche passo passo

Fornire istruzioni di navigazione passo passo (TBT) utilizzando una notifica di navigazione aggiornata di frequente. Per essere considerata una notifica di navigazione sullo schermo dell'auto, il creator della notifica deve:

  1. Contrassegna la notifica come in corso con il metodo NotificationCompat.Builder.setOngoing.
  2. Imposta la categoria della notifica su Notification.CATEGORY_NAVIGATION.
  3. Espandi la notifica con un CarAppExtender.

Una notifica di navigazione viene visualizzata nel widget della barra nella parte inferiore dello schermo dell'auto. Se il livello di importanza della notifica è impostato su IMPORTANCE_HIGH, viene visualizzata anche come notifica in primo piano (HUN). Se l'importanza non è impostata con il metodo CarAppExtender.Builder.setImportance viene utilizzata l'importanza del canale di notifica.

L'app può impostare un PendingIntent nel CarAppExtender che viene inviato all'app quando l'utente tocca l'HUN o il widget della barra laterale.

Se NotificationCompat.Builder.setOnlyAlertOnce viene chiamato con un valore di true, una notifica di alta importanza viene inviata solo una volta nell'HUN.

Lo snippet seguente mostra come creare una notifica di navigazione:

Kotlin

NotificationCompat.Builder(context, NOTIFICATION_CHANNEL_ID)
    ...
    .setOnlyAlertOnce(true)
    .setOngoing(true)
    .setCategory(NotificationCompat.CATEGORY_NAVIGATION)
    .extend(
        CarAppExtender.Builder()
            .setContentTitle(carScreenTitle)
            ...
            .setContentIntent(
                PendingIntent.getBroadcast(
                    context,
                    ACTION_OPEN_APP.hashCode(),
                    Intent(ACTION_OPEN_APP).setComponent(
                        ComponentName(context, MyNotificationReceiver::class.java)),
                        0))
            .setImportance(NotificationManagerCompat.IMPORTANCE_HIGH)
            .build())
    .build()

Java

new NotificationCompat.Builder(context, NOTIFICATION_CHANNEL_ID)
    ...
    .setOnlyAlertOnce(true)
    .setOngoing(true)
    .setCategory(NotificationCompat.CATEGORY_NAVIGATION)
    .extend(
        new CarAppExtender.Builder()
            .setContentTitle(carScreenTitle)
            ...
            .setContentIntent(
                PendingIntent.getBroadcast(
                    context,
                    ACTION_OPEN_APP.hashCode(),
                    new Intent(ACTION_OPEN_APP).setComponent(
                        new ComponentName(context, MyNotificationReceiver.class)),
                        0))
            .setImportance(NotificationManagerCompat.IMPORTANCE_HIGH)
            .build())
    .build();

Aggiorna regolarmente la notifica TBT per le modifiche della distanza, che aggiorna il widget della metropolitana e mostra la notifica solo come HUN. Puoi controllare il comportamento di HUN impostando l'importanza della notifica con CarAppExtender.Builder.setImportance. Se imposti l'importanza su IMPORTANCE_HIGH, viene visualizzato un HUN. Se lo imposti su un altro valore, viene aggiornato solo il widget della barra laterale.

Aggiornare i contenuti di PlaceListNavigationTemplate

Puoi consentire ai conducenti di aggiornare i contenuti con un semplice tocco mentre sfogliano gli elenchi di luoghi creati con PlaceListNavigationTemplate. Per attivare l'aggiornamento dell'elenco, implementa il metodo onContentRefreshRequested dell'interfaccia OnContentRefreshListener e utilizza PlaceListNavigationTemplate.Builder.setOnContentRefreshListener per impostare l'ascoltatore nel modello.

Lo snippet seguente mostra come impostare l'ascoltatore nel modello:

Kotlin

PlaceListNavigationTemplate.Builder()
    ...
    .setOnContentRefreshListener {
        // Execute any desired logic
        ...
        // Then call invalidate() so onGetTemplate() is called again
        invalidate()
    }
    .build()

Java

new PlaceListNavigationTemplate.Builder()
        ...
        .setOnContentRefreshListener(() -> {
            // Execute any desired logic
            ...
            // Then call invalidate() so onGetTemplate() is called again
            invalidate();
        })
        .build();

Il pulsante di aggiornamento viene visualizzato nell'intestazione del PlaceListNavigationTemplate solo se l'ascoltatore ha un valore.

Quando l'utente fa clic sul pulsante di aggiornamento, viene chiamato il metodo onContentRefreshRequested della tua implementazione OnContentRefreshListener. All'interno di onContentRefreshRequested, chiama il metodo Screen.invalidate. L'host richiama quindi il metodo Screen.onGetTemplate dell'app per recuperare il modello con i contenuti aggiornati. Per maggiori informazioni sull'aggiornamento dei modelli, consulta Aggiornare i contenuti di un modello. Se il successivo modello ristituito da onGetTemplate è dello stesso tipo, viene conteggiato come aggiornamento e non viene conteggiato ai fini della quota di modelli.

Fornire indicazioni audio

Per riprodurre le indicazioni stradali tramite gli altoparlanti dell'auto, l'app deve richiedere il focus audio. Nell'ambito del tuo AudioFocusRequest, imposta l'utilizzo su AudioAttributes.USAGE_ASSISTANCE_NAVIGATION_GUIDANCE. Inoltre, imposta il guadagno della messa a fuoco su AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK.

Simula la navigazione

Per verificare la funzionalità di navigazione dell'app quando la invii al Google Play Store, l'app deve implementare il callback NavigationManagerCallback.onAutoDriveEnabled. Quando viene chiamato questo callback, l'app deve simulare la navigazione fino alla destinazione scelta quando l'utente inizia a navigare. L'app può uscire da questa modalità ogni volta che il ciclo di vita dell'Session corrente raggiunge lo stato Lifecycle.Event.ON_DESTROY.

Puoi verificare che l'implementazione di onAutoDriveEnabled venga chiamata eseguendo quanto segue da una riga di comando:

adb shell dumpsys activity service CAR_APP_SERVICE_NAME AUTO_DRIVE

Ciò è mostrato nell'esempio seguente:

adb shell dumpsys activity service androidx.car.app.samples.navigation.car.NavigationCarAppService AUTO_DRIVE

App di navigazione auto predefinita

In Android Auto, l'app di navigazione predefinita per l'auto corrisponde all'ultima app di navigazione avviata dall'utente. L'app predefinita riceve intent di navigazione quando l'utente invoca i comandi di navigazione tramite l'assistente o quando un'altra app invia un intent per avviare la navigazione.

Mostrare avvisi di navigazione contestuali

Alert mostra informazioni importanti al conducente con azioni facoltative e un riepilogo, senza uscire dal contesto della schermata di navigazione. Per offrire la migliore esperienza al conducente, Alert lavora all'interno di NavigationTemplate per evitare di bloccare il percorso di navigazione e ridurre al minimo le distrazioni del conducente.

Alert è disponibile solo all'interno di NavigationTemplate. Per avvisare l'utente al di fuori del NavigationTemplate, valuta la possibilità di utilizzare una notifica in primo piano (HUN), come spiegato in Mostrare le notifiche.

Ad esempio, utilizza Alert per:

  • Informare il conducente di un aggiornamento pertinente alla navigazione in corso, ad esempio un cambiamento delle condizioni del traffico.
  • Chiedi al conducente un aggiornamento relativo alla navigazione corrente, ad esempio l'esistenza di un posto di blocco.
  • Proponi un'attività imminente e chiedi se il conducente la accetta, ad esempio se è disposto a prendere qualcuno lungo il percorso.

Nella sua forma di base, un Alert è composto da un titolo e dalla durata Alert. La durata è rappresentata da una barra di avanzamento. Se vuoi, puoi aggiungere un sottotitolo, un'icona e fino a due oggetti Action.

Figura 2. Avviso di navigazione contestuale.

Una volta visualizzato un Alert, questo non viene trasferito a un altro modello se l'interazione del conducente comporta l'uscita dal Alert.NavigationTemplate Rimane nella NavigationTemplate originale finché Alert non scade, l'utente compie un'azione o l'app chiude la Alert.

Creare un avviso

Utilizza Alert.Builder per creare un'istanza Alert:

Kotlin

Alert.Builder(
        /*alertId*/ 1,
        /*title*/ CarText.create("Hello"),
        /*durationMillis*/ 5000
    )
    // The fields below are optional
    .addAction(firstAction)
    .addAction(secondAction)
    .setSubtitle(CarText.create(...))
    .setIcon(CarIcon.APP_ICON)
    .setCallback(...)
    .build()

Java

new Alert.Builder(
        /*alertId*/ 1,
        /*title*/ CarText.create("Hello"),
        /*durationMillis*/ 5000
    )
    // The fields below are optional
    .addAction(firstAction)
    .addAction(secondAction)
    .setSubtitle(CarText.create(...))
    .setIcon(CarIcon.APP_ICON)
    .setCallback(...)
    .build();

Se vuoi ascoltare l'annullamento o la chiusura di Alert, crea un'implementazione dell'interfaccia AlertCallback. I percorsi di chiamata AlertCallback sono:

Configura la durata dell'avviso

Scegli una durata di Alert che sia adatta alle esigenze della tua app. La durata consigliata per un menu di navigazioneAlert è di 10 secondi. Per ulteriori informazioni, consulta la sezione Avvisi di navigazione.

Mostrare un avviso

Per mostrare un Alert, chiama il metodo AppManager.showAlert disponibile tramite il CarContext della tua app.

// Show an alert
carContext.getCarService(AppManager.class).showAlert(alert)
  • La chiamata a showAlert con un Alert che ha un alertId uguale all'ID del Alert attualmente visualizzato non fa nulla. Alert non si aggiorna. Per aggiornare un Alert, devi ricrearlo con un nuovo alertId.
  • Se chiami showAlert con un Alert che ha un alertId diverso rispetto a quello visualizzato al momento, il Alert visualizzato al momento viene ignorato.Alert

Ignorare un avviso

Sebbene un Alert venga chiuso automaticamente per timeout o interazione del conducente, puoi anche chiuderlo manualmente, ad esempio se le relative informazioni diventano obsolete.Alert Per ignorare un Alert, chiama il metodo dismissAlert con il alertId del Alert.

// Dismiss the same alert
carContext.getCarService(AppManager.class).dismissAlert(alert.getId())

Se chiami dismissAlert con un alertId che non corrisponde al Alert visualizzato al momento, non succede nulla. Non genera un'eccezione.