Share via


Guida How-To: Integrazione con le notifiche di Graph (Android)

Con Graph Notifications la tua app può inviare e gestire notifiche destinate agli utenti tra più dispositivi.

Con Project Rome SDK sul lato client in Android la tua app Android può registrarsi per ricevere le notifiche pubblicate dal server applicazioni destinate a un utente connesso. L'SDK consente al client dell'app di ricevere i payload delle nuove notifiche in ingresso, gestire lo stato di quelle esistenti e recuperare la cronologia delle notifiche. Per altre informazioni su Notifications e su come consente il recapito delle notifiche incentrato sull'utente, vedi la panoramica su Microsoft Graph Notifications.

Tutte le funzionalità di Project Rome SDK, tra cui Graph Notifications e molto altro, si basano su una piattaforma sottostante chiamata piattaforma dispositivi connessi. Questa guida è pensata come supporto durante l'esecuzione dei passaggi necessari per iniziare a usare la piattaforma dispositivi connessi e illustra come usare le API nell'SDK per implementare le funzionalità specifiche di Graph Notifications.

Visita la pagina Riferimento API per collegamenti alla documentazione di riferimento pertinente per gli scenari di notifica.

La procedura seguente farà riferimento a codice dell'app di esempio per Android di Project Rome.

Per tutte le funzionalità di dispositivi connessi sarà necessario un IDE di sviluppo di app per Android e un dispositivo Android con una delle architetture supportate (armeabi-v7a, arm64-v8a, x86 o x86_64) o un emulatore. Il sistema deve eseguire Android 4.4.2 o versioni successive.

Configurazione preliminare per la piattaforma dispositivi connessi e le notifiche

Prima di implementare la connettività remota, dovrai eseguire alcune operazioni per implementare nell'app Android la funzionalità per la connessione ai dispositivi remoti, oltre all'invio e alla ricezione delle notifiche.

Registrare l'app

È richiesta l'autenticazione con account Microsoft (MSA) o di Azure Active Directory (AAD) per quasi tutte le funzionalità di Project Rome SDK, ad eccezione delle API di condivisione in prossimità. Se non hai già un account Microsoft e vuoi usarne uno, registrati in account.microsoft.com.

Nota

Gli account Azure Active Directory (AAD) non sono supportati con le API Device Relay.

Usando il metodo di autenticazione scelto, devi registrare l'app in Microsoft seguendo le istruzioni nel portale di registrazione delle applicazioni. Se non hai un account per sviluppatore Microsoft, dovrai crearne uno.

Quando registri un'app usando un account Microsoft, dovresti ricevere una stringa di ID client. Salvala per usarla in seguito. Ciò consentirà alla tua app di accedere alle risorse della piattaforma dispositivi connessi di Microsoft. Se usi AAD, vedi Librerie di autenticazione di Azure Active Directory per istruzioni su come ottenere la stringa di ID client.

Aggiungere l'SDK

Inserisci i riferimenti al repository seguenti nel file build.gradle nella radice del progetto.

allprojects {
    repositories {
        jcenter()
    }
}

Inserisci quindi la dipendenza seguente nel file build.gradle nella tua cartella del progetto.

dependencies { 
    ...
    implementation 'com.microsoft.connecteddevices:connecteddevices-sdk:+'
}

Nel file AndroidManifest.xml del progetto aggiungi le autorizzazioni seguenti all'interno dell'elemento <manifest> (se non sono già presenti). In questo modo l'app viene autorizzata a connettersi a Internet e ad abilitare l'individuabilità Bluetooth nel dispositivo.

Nota che le autorizzazioni correlate a Bluetooth sono necessarie solo per usare l'individuabilità Bluetooth e non sono richieste per le altre funzionalità nella piattaforma dispositivi connessi. Inoltre, ACCESS_COARSE_LOCATION è richiesto solo per Android SDK 21 e versioni successive. Per Android SDK 23 e versioni successive, lo sviluppatore deve anche richiedere all'utente di concedere l'accesso alla posizione in fase di esecuzione.

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

Passa quindi alle classi di attività in cui vuoi che risieda la funzionalità dispositivi connessi. Importa i pacchetti seguenti.

import com.microsoft.connecteddevices;
import com.microsoft.connecteddevices.remotesystems;
import com.microsoft.connecteddevices.remotesystems.commanding;

Configurazione dell'autenticazione e della gestione degli account

La piattaforma dispositivi connessi richiede un token OAuth valido da usare durante il processo di registrazione. Puoi usare il tuo metodo preferito per generare e gestire i token OAuth. Tuttavia, per consentire agli sviluppatori di iniziare a usare la piattaforma, è stato incluso un provider di autenticazione come parte dell'app di esempio per Android, che genera e gestisce i token di aggiornamento per maggiore comodità.

Se preferisci implementare l'interfaccia ConnectedDevicesAccountManager manualmente, prendi nota delle informazioni seguenti:

Se usi un account Microsoft, dovrai includere gli ambiti seguenti nella richiesta di accesso: "wl.offline_access", "ccs.ReadWrite", "dds.read", "dds.register", "wns.connect", "asimovrome.telemetry" e "https://activity.windows.com/UserActivity.ReadWrite.CreatedByApp".

Se usi un account AAD, sarà necessario richiedere i seguenti destinatari: "https://cdpcs.access.microsoft.com", "https://cs.dds.microsoft.com", "https://wns.windows.com/" e "https://activity.microsoft.com".

Nota

Gli account Azure Active Directory (AAD) non sono supportati con le API Device Relay.

Se si usa o meno l'implementazione ConnectedDevicesAccountManager fornita, se si usa AAD è necessario specificare le autorizzazioni seguenti nella registrazione dell'app nel portale di Azure (portal.azure.com > Azure Active Directory > Registrazioni app):

  • Microsoft Activity Feed Service
    • Distribuire e modificare le notifiche utente per questa app
    • Leggere e scrivere attività dell'app nel feed attività degli utenti
  • Servizio di notifica Windows
    • Connettere il dispositivo al servizio di notifica Windows
  • Microsoft Device Directory Service
    • Visualizzare l'elenco dei dispositivi
    • Essere aggiunto all'elenco di app e dispositivi
  • Microsoft Command Service
    • Comunicare con i dispositivi utente
    • Leggere i dispositivi utente

Registrare l'app per le notifiche push

Registra l'applicazione in Google per il supporto di Firebase Cloud Messaging. Assicurati di prendere nota dell'ID del mittente e della chiave del server ricevuti perché ti serviranno in seguito.

Dopo aver completato la registrazione, devi associare la funzionalità di notifica push alla piattaforma dispositivi connessi nell'app.

mNotificationRegistration = new ConnectedDevicesNotificationRegistration();
mNotificationRegistration.setType(ConnectedDevicesNotificationType.FCM);
mNotificationRegistration.setToken(token);
mNotificationRegistration.setAppId(Secrets.FCM_SENDER_ID);
mNotificationRegistration.setAppDisplayName("SampleApp");

Registrare l'app in Microsoft Windows Dev Center per le esperienze tra dispositivi

Importante

Questo passaggio è obbligatorio solo se vuoi usare le funzionalità di Project Rome per accedere ai dati da o inviare richieste di dispositivi non Windows. Se si usano solo dispositivi Windows come destinazione, non devi completare questo passaggio.

Vai al dashboard di Dev Center, passa a Esperienze tra dispositivi dal riquadro di spostamento a sinistra e seleziona la configurazione di una nuova app per più dispositivi, come indicato di seguito. Dashboard di Dev Center - Esperienze tra dispositivi

Il processo di onboarding di Dev Center richiede la procedura seguente:

  • Seleziona le piattaforme supportate: seleziona le piattaforme in cui la tua app sarà presente e sarà abilitata per le esperienze tra dispositivi. Nel caso dell'integrazione con Graph Notifications, puoi selezionare Windows, Android e/o iOS. Esperienze tra dispositivi - Piattaforme supportate

  • Fornisci gli ID app: fornisci gli ID app per ogni piattaforma in cui la tua app è presente. Per le app Android, questo è il nome del pacchetto assegnato all'app quando hai creato il progetto. Il nome del pacchetto è disponibile nella console firebase in Panoramica del progetto -> Generale. Puoi aggiungere ID diversi (fino a dieci) per ogni piattaforma, ad esempio nel caso in cui ci siano più versioni della stessa app o addirittura app differenti, che devono essere in grado di ricevere le stesse notifiche inviate dal server applicazioni destinate allo stesso utente. Esperienze tra dispositivi - ID app

  • Specifica o seleziona gli ID app dalle registrazioni delle app per MSA e/o AAD. Questi ID client corrispondenti alla registrazione dell'app in MSA o AAD sono stati ottenuti nei passaggi precedenti di registrazione delle app per MSA/AAD. Esperienze tra dispositivi - Registrazioni delle app per MSA e AAD

  • Le funzionalità di Graph Notifications e le altre funzionalità della piattaforma dispositivi connessi sfruttano tutte le piattaforme di notifica native sulle piattaforme principali per inviare notifiche agli endpoint dei client dell'app, nello specifico WNS (per la piattaforma UWP di Windows), FCM (per Android) e il servizio APN (per iOS). Specifica le credenziali per queste piattaforme di notifica per abilitare Graph Notifications per il recapito delle notifiche per il tuo server applicazioni, al momento della pubblicazione di notifiche mirate agli utenti. Per Android l'abilitazione del servizio di messaggistica cloud è un prerequisito per l'uso di Microsoft Graph Notifications. Nota inoltre che l'ID mittente richiesto corrisponde all'ID mittente di Firebase Cloud Messaging e la chiave API corrisponde alla chiave server legacy. Entrambi sono disponibili in Firebase Console -> Progetto -> Impostazioni, nella scheda Messaggistica cloud, come illustrato nello screenshot. Esperienze tra dispositivi - Credenziali di push

  • L'ultimo passaggio consiste nel verificare il dominio dell'app tra dispositivi, che funge da processo di verifica per confermare che l'app abbia la proprietà di questo dominio che agisce come identità di app tra dispositivi per l'app registrata. Esperienze tra dispositivi - Verifica del dominio

Inizializzare un canale di Graph Notifications

Project Rome SDK consente alla tua app di sottoscrivere diversi canali per ricevere e gestire vari tipi di dati utente, incluse notifiche di Graph Notifications, attività utente e altro ancora. Tutti questi dati sono archiviati e sincronizzati in UserDataFeed. UserNotification costituisce la classe e il tipo di dati corrispondenti a una notifica mirata all'utente inviata tramite Graph Notifications. Per consentire l'integrazione con Graph Notifications e iniziare a ricevere notifiche di tipo UserNotification pubblicate dal server applicazioni, per prima cosa dovrai inizializzare il feed dei dati utente creando uno UserNotificationChannel. Questa operazione deve essere gestita come il passaggio di inizializzazione della piattaforma descritto in precedenza: deve essere verificata e possibilmente rieseguita ogni volta che l'app passa in primo piano (ma non prima dell'inizializzazione della piattaforma).

I metodi seguenti consentono di inizializzare uno UserNotificationChannel.

private UserNotificationChannel mNotificationChannel;
private UserDataFeed mUserDataFeed;

// ...

/**
 * Initializes the UserNotificationFeed.
 */
public void initializeUserNotificationFeed() {

    // define what scope of data this app needs
    SyncScope[] scopes = { UserNotificationChannel.getSyncScope() };

    // Get a reference to the UserDataFeed. This method is defined below
    mUserDataFeed = getUserDataFeed(scopes, new EventListener<UserDataFeed, Void>() {
        @Override
        public void onEvent(UserDataFeed userDataFeed, Void aVoid) {
            if (userDataFeed.getSyncStatus() == UserDataSyncStatus.SYNCHRONIZED) {
                // log synchronized.
            } else {
                // log synchronization not completed.
            }
        }
    });

    // this method is defined below
    mNotificationChannel = getUserNotificationChannel();
}

// instantiate the UserDataFeed
private UserDataFeed getUserDataFeed(SyncScope[] scopes, EventListener<UserDataFeed, Void> listener) {
    UserAccount[] accounts = AccountProviderBroker.getSignInHelper().getUserAccounts();
    if (accounts.length <= 0) {
        // notify the user that sign-in is required
        return null;
    }

    // use the initialized Platform instance, along with the cross-device app ID.
    UserDataFeed feed = UserDataFeed.getForAccount(accounts[0], PlatformBroker.getPlatform(), Secrets.APP_HOST_NAME);
    feed.addSyncStatusChangedListener(listener);
    feed.addSyncScopes(scopes);
    // sync data with the server
    feed.startSync();
    return feed;
}

// use the UserDataFeed reference to create a UserActivityChannel
@Nullable
private UserNotificationChannel getUserNotificationChannel() {
    UserNotificationChannel channel = null;
    try {
        // create a UserNotificationChannel for the signed in account
        channel = new UserNotificationChannel(mUserDataFeed);
    } catch (Exception e) {
        e.printStackTrace();
        // handle exception
    }
    return channel;
}

A questo punto, dovrebbe essere presente un riferimento a UserNotificationChannel in mNotificationChannel.

Creare uno UserNotificationReader per ricevere notifiche di tipo UserNotification in ingresso e accedere alla cronologia di UserNotification

Come illustrato in precedenza, la notifica iniziale di Google Cloud Messaging in arrivo nel client dell'app è semplicemente un avviso e occorre passare questo payload alla piattaforma dispositivi connessi per attivare l'SDK per l'esecuzione di una sincronizzazione completa con il server dispositivi connessi, che contiene tutte le notifiche UserNotification pubblicate dal server applicazioni. In questo modo verrà scaricato il payload della notifica completa pubblicato dal server applicazioni corrispondente a questo avviso (e in caso di notifiche precedenti pubblicate ma non ricevute nel client dell'app a causa di problemi di connettività dei dispositivi o di altro tipo, anch'esse verranno scaricate). Con queste sincronizzazioni in tempo reale eseguite costantemente dall'SDK, il client dell'app è in grado di accedere a una cache locale del feed dei dati di tipo UserNotification dell'utente connesso. Uno UserNotificationReader in questo caso consente al client dell'app di accedere a questo feed di dati, per ricevere il payload della notifica più recente tramite il listener di eventi o per accedere alla raccolta UserNotification completa utilizzabile come modello di visualizzazione della cronologia delle notifiche dell'utente.

Ricezione di notifiche UserNotification

Per prima cosa dovrai creare un'istanza di UserNotificationReader e ottenere tutte le notifiche UserNotification esistenti già presenti nel lettore, se sei interessato a utilizzare queste informazioni per l'esperienza che intendi garantire. È opportuno partire sempre dal presupposto che il server applicazioni abbia già pubblicato le notifiche per l'utente connesso, dal momento che questo particolare endpoint del dispositivo potrebbe non essere l'unico o il primo endpoint in cui l'utente ha installato l'app.

private static UserNotificationReader mReader;
private static final ArrayList<UserNotification> mHistoricalNotifications = new ArrayList<>();
// Instantiate UserNotificationReader
UserNotificationReaderOptions options = new UserNotificationReaderOptions();
mReader = mNotificationChannel.createReaderWithOptions(options);
// Read any previously published UserNotifications that have not expired yet
mReader.readBatchAsync(Long.MAX_VALUE).thenAccept(new AsyncOperation.ResultConsumer<UserNotification[]>() {
    @Override
    public void accept(UserNotification[] userNotifications) throws Throwable {
        synchronized (mHistoricalNotifications) {
            for (UserNotification notification : userNotifications) {
                if (notification.getReadState() == UserNotificationReadState.UNREAD) {
                    mHistoricalNotifications.add(notification);
                }
            }
        }
 
        if (RunnableManager.getHistoryUpdated() != null) {
            activity.runOnUiThread(RunnableManager.getHistoryUpdated());
        }
    }
});

A questo punto, è il momento di aggiungere un listener di eventi che viene attivato quando la piattaforma dispositivi connessi completa una sincronizzazione e ha nuove modifiche da notificare. Nel caso di Graph Notifications, le nuove modifiche potrebbero essere nuove notifiche UserNotification in ingresso pubblicate dal server applicazioni o aggiornamenti, eliminazioni e scadenze di UserNotifcation provenienti dal server o da altri endpoint registrati a cui è connesso lo stesso utente.

Suggerimento

Questo listener di eventi è il punto dove puoi gestire la logica di business principale e "utilizzare" il contenuto del payload delle notifiche basato sugli scenari in uso. Se usi il messaggio dei dati di Google Cloud Messaging per costruire una notifica visiva nell'area di notifica a livello del sistema operativo o se usi il contenuto della notifica per aggiornare parte dell'interfaccia utente in-app, questo è il posto giusto per farlo.

mReader.addDataChangedListener(new EventListener<UserNotificationReader, Void>() {
    @Override
    public void onEvent(UserNotificationReader userNotificationReader, Void aVoid) {
        userNotificationReader.readBatchAsync(Long.MAX_VALUE).thenAccept(new AsyncOperation.ResultConsumer<UserNotification[]>() {
        @Override
        public void accept(UserNotification[] userNotifications) throws Throwable {
            boolean updatedNew = false;
            boolean updatedHistorical = false;
            synchronized (sHistoricalNotifications) {
                for (final UserNotification notification : userNotifications) {
                    if (notification.getStatus() == UserNotificationStatus.ACTIVE && notification.getReadState() == UserNotificationReadState.UNREAD) {
                        switch (notification.getUserActionState()) {
                            case NO_INTERACTION:
                                // Brand new notification
                                // Insert business logic to construct a new visual notification in Android notification tray for the user to see
                                // ...
                            case DISMISSED:
                                // Existing notification that is marked as dismissed
                                // An app client receive this type of changes because another app client logged in by the same user has marked the notification as dismissed and the change is fanned-out to everywhere
                                // This state sync across app clients on different devices enable universal dismiss of notifications and other scenarios across multiple devices owned by the same user
                                // Insert business logic to dismiss the corresponding visual notification inside Android system notification tray, to make sure users don’t have to deal with redundant information across devices, and potentially insert this notification in your app’s notification history view
                                // ...
                            default:
                                // Unexpected
                        }
                    } else {
                        // ...
                    }
                }
            }
        }
    });
}
});

Aggiornare lo stato di una notifica UserNotification esistente

Nella sezione precedente si è accennato al fatto che a volte una modifica di una notifica UserNotification ricevuta tramite il lettore potrebbe essere un aggiornamento dello stato di una notifica UserNotification esistente, indipendentemente dal fatto che sia contrassegnata come ignorata o come letta. In questo caso il client dell'app può scegliere come procedere, ad esempio abilitando Universal Dismiss tramite la rimozione della notifica visiva corrispondente in questo specifico dispositivo. Facciamo un passo indietro: il client dell'app spesso è quello che ha avviato questo aggiornamento della modifica di UserNotification, da un dispositivo diverso. Puoi scegliere quando aggiornare lo stato delle tue notifiche UserNotification, ma in genere vengono aggiornate quando la notifica visiva corrispondente viene gestita dall'utente in quel dispositivo o quando viene ulteriormente gestita dall'utente nel corso di un'esperienza in-app. Ecco un esempio di ciò che il flusso sarebbe simile: il server dell'app pubblica una notifica destinata all'utente A. L'utente A riceve questa notifica sul proprio PC e sul suo telefono in cui vengono installati i client dell'app. L'utente fa clic sulla notifica nel PC e passa all'app per la gestione dell'attività corrispondente. Il client dell'app in questo PC chiamerà quindi l'SDK della piattaforma dispositivi connessi per aggiornare lo stato della notifica UserNotification corrispondente, in modo da sincronizzare questo aggiornamento tra tutti i dispositivi dell'utente. Gli altri client dell'app, dopo aver ricevuto questo aggiornamento dello stato in tempo reale, rimuoveranno quindi il messaggio, la notifica di tipo avviso popup o l'avviso visivo corrispondente dal centro notifiche o dall'area di notifica del dispositivo. Ecco come le notifiche vengono universalmente ignorate tra i dispositivi di un utente.

Suggerimento

La classe UserNotification fornisce attualmente due tipi di aggiornamenti di stato: puoi modificare UserNotificationReadState o UserNotificationUserActionState e definire la tua logica personalizzata riguardo a cosa deve accadere quando le notifiche vengono aggiornate. Ad esempio, puoi contrassegnare UserActionState come Activated o Dismissed e basarti su questo valore per implementare Universal Dismiss. In alternativa, o contemporaneamente, puoi contrassegnare ReadState come Read o Unread e in base a ciò determinare quali notifiche dovranno comparire nella visualizzazione della cronologia delle notifiche in-app. Il frammento di codice seguente illustra come contrassegnare UserNotificationUserActionState come Dismissed per una notifica.

public void dismissNotification(int position) {
    final UserNotification notification = mNewNotifications.get(position);
          
    notification.setUserActionState(UserNotificationUserActionState.DISMISSED);
    notification.saveAsync();
}