Esercitazione: Inviare notifiche push a app Android specifiche con Hub di notifica di Azure
Nota
Per informazioni sui passaggi di deprecazione e migrazione di Firebase Cloud Messaging, vedere Migrazione di Google Firebase Cloud Messaging.
In questa esercitazione viene illustrato come usare Hub di notifica di Azure per inviare notifiche push a un utente specifico dell'app su un dispositivo specifico. Per autenticare i client e generare le notifiche viene usato un back-end di API Web ASP.NET, come illustrato nell'articolo Registering from your app backend (Registrazione dal back-end dell'app). Questa esercitazione si basa sull'hub di notifica creato nell'esercitazione : Eseguire il push di notifiche ai dispositivi Android usando Hub di notifica di Azure e Firebase Cloud Messaging.
In questa esercitazione vengono completati i passaggi seguenti:
- Creare il progetto API Web di back-end che autentica gli utenti.
- Aggiornare un'applicazione Android.
- Testare l'app
Prerequisiti
Completare l'esercitazione: Eseguire il push delle notifiche ai dispositivi Android usando Hub di notifica di Azure e Firebase Cloud Messaging prima di eseguire questa esercitazione.
Creare il progetto WebAPI
Le sezioni seguenti illustrano la creazione di un nuovo back-end WebAPI ASP.NET. Questo processo ha tre obiettivi principali:
- Autenticare i client: si aggiunge un gestore di messaggi per autenticare le richieste client e associare l'utente alla richiesta.
- Eseguire la registrazione per le notifiche usando il back-end WebAPI: si aggiunge un controller per gestire le nuove registrazioni e consentire a un dispositivo client di ricevere le notifiche. Il nome utente autenticato verrà aggiunto automaticamente alla registrazione come tag.
- Inviare notifiche ai client: si aggiunge un controller per consentire agli utenti di attivare un push sicuro per i dispositivi e i client associati al tag.
Creare il nuovo back-end dell'API Web ASP.NET Core 6.0 eseguendo le azioni seguenti:
A questo scopo, avviare Visual Studio. Scegliere Estensioni e aggiornamenti dal menu Strumenti. Cercare Gestione pacchetti NuGet nella versione di Visual Studio e verificare che sia installata la versione più recente. Se la versione installata non è la più recente, disinstallarla e reinstallare Gestione pacchetti NuGet.
Nota
Assicurarsi che sia installato Visual Studio Azure SDK per la distribuzione del sito Web.
Avviare Visual Studio o Visual Studio Express.
Selezionare Esplora server e accedere all'account Azure. Per creare le risorse del sito Web nell'account è necessario eseguire l'accesso.
Nel menu File di Visual Studio selezionare Nuovo>progetto.
Immettere l'API Web nella casella di ricerca.
Selezionare il modello di progetto api Web core ASP.NET e selezionare Avanti.
Nella finestra di dialogo Configura il nuovo progetto assegnare al progetto il nome AppBackend e selezionare Avanti.
Nella finestra di dialogo Informazioni aggiuntive:
- Verificare che Framework sia .NET 6.0 (supporto a lungo termine).
- Verificare che la casella di controllo Usa controller (deselezionare per usare le API minime) sia selezionata.
- Deselezionare Abilita supporto OpenAPI.
- Seleziona Crea.
Rimuovere i file del modello WeatherForecast
- Rimuovere i file di esempio WeatherForecast.cs e Controllers/WeatherForecastController.cs dal nuovo progetto AppBackend .
- Aprire Properties\launchSettings.json.
- Modificare le proprietà launchUrl da weatherforcast a appbackend.
Selezionare una sottoscrizione nella finestra Configura app Web di Microsoft Azure e nell'elenco Piano di Servizio app eseguire una delle azioni seguenti:
- Selezionare un piano di servizio app Azure già creato.
- Selezionare Crea un nuovo piano di servizio app e quindi creare un piano.
Per questa esercitazione non è necessario disporre di un database. Dopo aver selezionato il piano di servizio app, fare clic su OK per creare il progetto.
Se questa pagina per la configurazione del piano di servizio app non viene visualizzata, continuare con l'esercitazione. È possibile completare la configurazione in seguito durante la pubblicazione dell'app.
Autenticare client con il back-end WebAPI
In questa sezione si crea una nuova classe del gestore di messaggi denominata AuthenticationTestHandler per il nuovo back-end. Questa classe deriva da DelegatingHandler e viene aggiunta come gestore di messaggi per poter elaborare tutte le richieste in arrivo nel back-end.
In Esplora soluzioni fare clic con il pulsante destro del mouse sul progetto AppBackend, scegliere Aggiungi e quindi selezionare Classe.
Assegnare alla nuova classe il nome AuthenticationTestHandler.cs e fare clic su Aggiungi per generarla. Questa classe autentica gli utenti tramite l'autenticazione di base. L'app può usare qualsiasi schema di autenticazione.
In AuthenticationTestHandler.cs aggiungere le istruzioni
using
seguenti:using System.Net.Http; using System.Threading; using System.Security.Principal; using System.Net; using System.Text; using System.Threading.Tasks;
In AuthenticationTestHandler.cs sostituire la definizione di classe
AuthenticationTestHandler
con il codice seguente:Questo gestore autorizza la richiesta quando le tre condizioni seguenti sono vere:
- La richiesta include un'intestazione di autorizzazione.
- La richiesta usa l'autenticazione di base .
- La stringa del nome utente corrisponde alla stringa della password.
In caso contrario, la richiesta viene rifiutata. Non si tratta di un vero approccio di autenticazione e autorizzazione. È solo un esempio semplice per questa esercitazione.
Se il messaggio di richiesta viene autenticato e autorizzato da
AuthenticationTestHandler
, l'utente dell'autenticazione di base viene associato alla richiesta corrente in HttpContext. Le informazioni utente in HttpContext verranno usate da un altro controller (RegisterController) in un secondo momento per aggiungere un tag alla richiesta di registrazione per le notifiche.public class AuthenticationTestHandler : DelegatingHandler { protected override Task<HttpResponseMessage> SendAsync( HttpRequestMessage request, CancellationToken cancellationToken) { var authorizationHeader = request.Headers.GetValues("Authorization").First(); if (authorizationHeader != null && authorizationHeader .StartsWith("Basic ", StringComparison.InvariantCultureIgnoreCase)) { string authorizationUserAndPwdBase64 = authorizationHeader.Substring("Basic ".Length); string authorizationUserAndPwd = Encoding.Default .GetString(Convert.FromBase64String(authorizationUserAndPwdBase64)); string user = authorizationUserAndPwd.Split(':')[0]; string password = authorizationUserAndPwd.Split(':')[1]; if (VerifyUserAndPwd(user, password)) { // Attach the new principal object to the current HttpContext object HttpContext.Current.User = new GenericPrincipal(new GenericIdentity(user), new string[0]); System.Threading.Thread.CurrentPrincipal = System.Web.HttpContext.Current.User; } else return Unauthorized(); } else return Unauthorized(); return base.SendAsync(request, cancellationToken); } private bool VerifyUserAndPwd(string user, string password) { // This is not a real authentication scheme. return user == password; } private Task<HttpResponseMessage> Unauthorized() { var response = new HttpResponseMessage(HttpStatusCode.Forbidden); var tsc = new TaskCompletionSource<HttpResponseMessage>(); tsc.SetResult(response); return tsc.Task; } }
Nota
Nota sulla sicurezza: la classe
AuthenticationTestHandler
non fornisce un'effettiva autenticazione. Viene usata solo per imitare l'autenticazione di base e non è sicura. È necessario implementare un meccanismo di autenticazione sicuro nelle applicazioni e nei servizi di produzione.Per registrare il gestore messaggi, aggiungere il codice seguente alla fine del
Register
metodo nel file Program.cs :config.MessageHandlers.Add(new AuthenticationTestHandler());
Salva le modifiche.
Eseguire la registrazione per le notifiche tramite il back-end WebAPI
In questa sezione si aggiunge un nuovo controller al back-end WebAPI per gestire le richieste di registrazione di un utente e un dispositivo per le notifiche tramite la libreria client per gli hub di notifica. Il controller aggiunge un tag user per l'utente che è stato autenticato e collegato a HttpContext da AuthenticationTestHandler
. Il tag ha il formato stringa, "username:<actual username>"
.
In Esplora soluzioni fare clic con il pulsante destro del mouse sul progetto AppBackend e quindi scegliere Gestisci pacchetti NuGet.
Nel riquadro sinistro selezionare Online e nella casella Cerca digitare Microsoft.Azure.NotificationHubs.
Nell'elenco dei risultati fare clic su Hub di notifica di Microsoft Azure e quindi selezionare Installa. Completare l'installazione e quindi chiudere la finestra di Gestione pacchetti NuGet.
Questa azione aggiunge un riferimento ad Azure Notification Hubs SDK usando il pacchetto NuGet Microsoft.Azure.NotificationHubs.
Creare un nuovo file di classe che rappresenta la connessione con l'hub di notifica usato per inviare le notifiche. In Esplora soluzioni fare clic con il pulsante destro del mouse sulla cartella Modelli, scegliere Aggiungi e quindi fare clic su Classe. Assegnare alla nuova classe il nome Notifications.cs e quindi selezionare Aggiungi per generarla.
In Notifications.cs aggiungere l'istruzione
using
seguente all'inizio del file:using Microsoft.Azure.NotificationHubs;
Sostituire la definizione di classe
Notifications
con il codice seguente e sostituire i due segnaposto con la stringa di connessione (con accesso completo) per l'hub di notifica e con il nome dell'hub, disponibile nel portale di Azure:public class Notifications { public static Notifications Instance = new Notifications(); public NotificationHubClient Hub { get; set; } private Notifications() { Hub = NotificationHubClient.CreateClientFromConnectionString("<your hub's DefaultFullSharedAccessSignature>", "<hub name>"); } }
Importante
Immettere il nome e il valore DefaultFullSharedAccessSignature dell'hub prima di continuare.
Creare quindi un nuovo controller denominato RegisterController. In Esplora soluzioni fare clic con il pulsante destro del mouse sulla cartella Controller, scegliere Aggiungi e quindi fare clic su Controller.
Selezionare Controller API - Vuoto e quindi selezionare Aggiungi.
Nella casella Nome controller digitare RegisterController per assegnare un nome alla nuova classe, quindi selezionare Aggiungi.
In RegisterController.cs aggiungere le istruzioni
using
seguenti:using Microsoft.Azure.NotificationHubs; using Microsoft.Azure.NotificationHubs.Messaging; using AppBackend.Models; using System.Threading.Tasks; using System.Web;
Aggiungere il codice seguente all'interno della definizione di classe
RegisterController
. In questo codice viene aggiunto un tag user per l'utente associato a HttpContext. L'utente è stato autenticato e associato a HttpContext dal filtro messaggi aggiunto,AuthenticationTestHandler
. È anche possibile aggiungere controlli facoltativi per verificare che l'utente disponga dei diritti per la registrazione per i tag richiesti.private NotificationHubClient hub; public RegisterController() { hub = Notifications.Instance.Hub; } public class DeviceRegistration { public string Platform { get; set; } public string Handle { get; set; } public string[] Tags { get; set; } } // POST api/register // This creates a registration id public async Task<string> Post(string handle = null) { string newRegistrationId = null; // make sure there are no existing registrations for this push handle (used for iOS and Android) if (handle != null) { var registrations = await hub.GetRegistrationsByChannelAsync(handle, 100); foreach (RegistrationDescription registration in registrations) { if (newRegistrationId == null) { newRegistrationId = registration.RegistrationId; } else { await hub.DeleteRegistrationAsync(registration); } } } if (newRegistrationId == null) newRegistrationId = await hub.CreateRegistrationIdAsync(); return newRegistrationId; } // PUT api/register/5 // This creates or updates a registration (with provided channelURI) at the specified id public async Task<HttpResponseMessage> Put(string id, DeviceRegistration deviceUpdate) { RegistrationDescription registration = null; switch (deviceUpdate.Platform) { case "mpns": registration = new MpnsRegistrationDescription(deviceUpdate.Handle); break; case "wns": registration = new WindowsRegistrationDescription(deviceUpdate.Handle); break; case "apns": registration = new AppleRegistrationDescription(deviceUpdate.Handle); break; case "fcm": registration = new FcmRegistrationDescription(deviceUpdate.Handle); break; default: throw new HttpResponseException(HttpStatusCode.BadRequest); } registration.RegistrationId = id; var username = HttpContext.Current.User.Identity.Name; // add check if user is allowed to add these tags registration.Tags = new HashSet<string>(deviceUpdate.Tags); registration.Tags.Add("username:" + username); try { await hub.CreateOrUpdateRegistrationAsync(registration); } catch (MessagingException e) { ReturnGoneIfHubResponseIsGone(e); } return Request.CreateResponse(HttpStatusCode.OK); } // DELETE api/register/5 public async Task<HttpResponseMessage> Delete(string id) { await hub.DeleteRegistrationAsync(id); return Request.CreateResponse(HttpStatusCode.OK); } private static void ReturnGoneIfHubResponseIsGone(MessagingException e) { var webex = e.InnerException as WebException; if (webex.Status == WebExceptionStatus.ProtocolError) { var response = (HttpWebResponse)webex.Response; if (response.StatusCode == HttpStatusCode.Gone) throw new HttpRequestException(HttpStatusCode.Gone.ToString()); } }
Salva le modifiche.
Inviare notifiche dal back-end WebAPI
In questa sezione si aggiunge un nuovo controller che consente ai dispositivi client di inviare una notifica. La notifica si basa sul tag username che usa la libreria .NET di Hub di notifica di Azure nel back-end WebAPI ASP.NET.
Creare un altro nuovo controller denominato NotificationsController seguendo la stessa procedura usata per creare RegisterController nella sezione precedente.
In NotificationsController.cs aggiungere le istruzioni
using
seguenti:using AppBackend.Models; using System.Threading.Tasks; using System.Web;
Aggiungere il metodo seguente alla classe NotificationsController:
Questo codice invia un tipo di notifica basato sul parametro
pns
del servizio di notifica della piattaforma (PNS). Il valoreto_tag
viene usato per impostare il tag username nel messaggio. Questo tag deve corrispondere a un tag username di una registrazione dell'hub di notifica attiva. Il messaggio di notifica viene estratto dal corpo della richiesta POST ed è formattato per il PNS di destinazione.A seconda del servizio di notifica della piattaforma (PNS) usato dai dispositivi supportati per ricevere le notifiche, sono supportate notifiche in una serie di formati. Nei dispositivi Windows è ad esempio possibile usare una notifica di tipo avviso popup con WNS che non è supportata direttamente da un altro PNS. In tal caso, il back-end deve formattare la notifica come notifica supportata per il PNS dei dispositivi che si intende supportare. Usare quindi l'API di invio appropriata per la classe NotificationHubClient.
public async Task<HttpResponseMessage> Post(string pns, [FromBody]string message, string to_tag) { var user = HttpContext.Current.User.Identity.Name; string[] userTag = new string[2]; userTag[0] = "username:" + to_tag; userTag[1] = "from:" + user; Microsoft.Azure.NotificationHubs.NotificationOutcome outcome = null; HttpStatusCode ret = HttpStatusCode.InternalServerError; switch (pns.ToLower()) { case "wns": // Windows 8.1 / Windows Phone 8.1 var toast = @"<toast><visual><binding template=""ToastText01""><text id=""1"">" + "From " + user + ": " + message + "</text></binding></visual></toast>"; outcome = await Notifications.Instance.Hub.SendWindowsNativeNotificationAsync(toast, userTag); break; case "apns": // iOS var alert = "{\"aps\":{\"alert\":\"" + "From " + user + ": " + message + "\"}}"; outcome = await Notifications.Instance.Hub.SendAppleNativeNotificationAsync(alert, userTag); break; case "fcm": // Android var notif = "{ \"data\" : {\"message\":\"" + "From " + user + ": " + message + "\"}}"; outcome = await Notifications.Instance.Hub.SendFcmNativeNotificationAsync(notif, userTag); break; } if (outcome != null) { if (!((outcome.State == Microsoft.Azure.NotificationHubs.NotificationOutcomeState.Abandoned) || (outcome.State == Microsoft.Azure.NotificationHubs.NotificationOutcomeState.Unknown))) { ret = HttpStatusCode.OK; } } return Request.CreateResponse(ret); }
Premere F5 per eseguire l'applicazione e verificare l'accuratezza del lavoro svolto sinora. L'app apre un Web browser e viene visualizzata nella home page di ASP.NET.
Pubblicare il nuovo back-end WebAPI
L'app verrà ora distribuita in un sito Web Azure per renderla accessibile da tutti i dispositivi.
Fare clic con il pulsante destro del mouse sul progetto AppBackend e scegliere Pubblica.
Selezionare Servizio app di Microsoft Azure come destinazione di pubblicazione e quindi selezionare **Pubblica. Verrà visualizzata la finestra Crea servizio app, Qui è possibile creare tutte le risorse di Azure necessarie per eseguire l'app Web ASP.NET in Azure.
Nella finestra Crea servizio app selezionare l'account Azure. Selezionare Modifica tipo>App Web. Mantenere il valore di Nome app Web predefinito e selezionare la sottoscrizione, il gruppo di risorse e il piano di servizio app.
Seleziona Crea.
Prendere nota della proprietà URL sito nella scheda Riepilogo. Questo URL sarà l'endpoint back-end più avanti nell'esercitazione.
Seleziona Pubblica.
Al termine della procedura guidata, l'app Web ASP.NET viene pubblicata in Azure e aperta nel browser predefinito. L'applicazione sarà visibile in Servizi app di Azure.
L'URL usa il nome dell'app Web specificato in precedenza, con il formato http://< app_name.azurewebsites.net>.
Creare il progetto Android
Il passaggio successivo consiste nell'aggiornare l'applicazione Android creata nell'esercitazione : Eseguire il push delle notifiche ai dispositivi Android usando Hub di notifica di Azure e Firebase Cloud Messaging.
Aprire il file
res/layout/activity_main.xml
e sostituire le definizioni di contenuto seguenti:Verranno aggiunti nuovi controlli EditText per l'accesso come utente. Viene aggiunto anche un campo per un tag username che farà parte delle notifiche inviate:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <EditText android:id="@+id/usernameText" android:layout_width="match_parent" android:layout_height="wrap_content" android:ems="10" android:hint="@string/usernameHint" android:layout_above="@+id/passwordText" android:layout_alignParentEnd="true" /> <EditText android:id="@+id/passwordText" android:layout_width="match_parent" android:layout_height="wrap_content" android:ems="10" android:hint="@string/passwordHint" android:inputType="textPassword" android:layout_above="@+id/buttonLogin" android:layout_alignParentEnd="true" /> <Button android:id="@+id/buttonLogin" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/loginButton" android:onClick="login" android:layout_above="@+id/toggleButtonFCM" android:layout_centerHorizontal="true" android:layout_marginBottom="24dp" /> <ToggleButton android:layout_width="wrap_content" android:layout_height="wrap_content" android:textOn="WNS on" android:textOff="WNS off" android:id="@+id/toggleButtonWNS" android:layout_toLeftOf="@id/toggleButtonFCM" android:layout_centerVertical="true" /> <ToggleButton android:layout_width="wrap_content" android:layout_height="wrap_content" android:textOn="FCM on" android:textOff="FCM off" android:id="@+id/toggleButtonFCM" android:checked="true" android:layout_centerHorizontal="true" android:layout_centerVertical="true" /> <ToggleButton android:layout_width="wrap_content" android:layout_height="wrap_content" android:textOn="APNS on" android:textOff="APNS off" android:id="@+id/toggleButtonAPNS" android:layout_toRightOf="@id/toggleButtonFCM" android:layout_centerVertical="true" /> <EditText android:layout_width="match_parent" android:layout_height="wrap_content" android:id="@+id/editTextNotificationMessageTag" android:layout_below="@id/toggleButtonFCM" android:layout_centerHorizontal="true" android:hint="@string/notification_message_tag_hint" /> <EditText android:layout_width="match_parent" android:layout_height="wrap_content" android:id="@+id/editTextNotificationMessage" android:layout_below="@+id/editTextNotificationMessageTag" android:layout_centerHorizontal="true" android:hint="@string/notification_message_hint" /> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/send_button" android:id="@+id/sendbutton" android:onClick="sendNotificationButtonOnClick" android:layout_below="@+id/editTextNotificationMessage" android:layout_centerHorizontal="true" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Hello World!" android:id="@+id/text_hello" /> </RelativeLayout>
Aprire il file
res/values/strings.xml
e sostituire la definizionesend_button
con le righe seguenti per ridefinire la stringa persend_button
e aggiungere stringhe per gli altri controlli:<string name="usernameHint">Username</string> <string name="passwordHint">Password</string> <string name="loginButton">1. Sign in</string> <string name="send_button">2. Send Notification</string> <string name="notification_message_hint">Notification message</string> <string name="notification_message_tag_hint">Recipient username</string>
Il layout grafico del file
main_activity.xml
dovrà essere simile a quello nell'immagine seguente:Creare una nuova classe denominata
RegisterClient
nello stesso pacchetto della classeMainActivity
. Usare il codice seguente per il nuovo file di classe.import java.io.IOException; import java.io.UnsupportedEncodingException; import java.util.Set; import org.apache.http.HttpResponse; import org.apache.http.HttpStatus; import org.apache.http.client.ClientProtocolException; import org.apache.http.client.HttpClient; import org.apache.http.client.methods.HttpPost; import org.apache.http.client.methods.HttpPut; import org.apache.http.client.methods.HttpUriRequest; import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.util.EntityUtils; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import android.content.Context; import android.content.SharedPreferences; import android.util.Log; public class RegisterClient { private static final String PREFS_NAME = "ANHSettings"; private static final String REGID_SETTING_NAME = "ANHRegistrationId"; private String Backend_Endpoint; SharedPreferences settings; protected HttpClient httpClient; private String authorizationHeader; public RegisterClient(Context context, String backendEndpoint) { super(); this.settings = context.getSharedPreferences(PREFS_NAME, 0); httpClient = new DefaultHttpClient(); Backend_Endpoint = backendEndpoint + "/api/register"; } public String getAuthorizationHeader() { return authorizationHeader; } public void setAuthorizationHeader(String authorizationHeader) { this.authorizationHeader = authorizationHeader; } public void register(String handle, Set<String> tags) throws ClientProtocolException, IOException, JSONException { String registrationId = retrieveRegistrationIdOrRequestNewOne(handle); JSONObject deviceInfo = new JSONObject(); deviceInfo.put("Platform", "fcm"); deviceInfo.put("Handle", handle); deviceInfo.put("Tags", new JSONArray(tags)); int statusCode = upsertRegistration(registrationId, deviceInfo); if (statusCode == HttpStatus.SC_OK) { return; } else if (statusCode == HttpStatus.SC_GONE){ settings.edit().remove(REGID_SETTING_NAME).commit(); registrationId = retrieveRegistrationIdOrRequestNewOne(handle); statusCode = upsertRegistration(registrationId, deviceInfo); if (statusCode != HttpStatus.SC_OK) { Log.e("RegisterClient", "Error upserting registration: " + statusCode); throw new RuntimeException("Error upserting registration"); } } else { Log.e("RegisterClient", "Error upserting registration: " + statusCode); throw new RuntimeException("Error upserting registration"); } } private int upsertRegistration(String registrationId, JSONObject deviceInfo) throws UnsupportedEncodingException, IOException, ClientProtocolException { HttpPut request = new HttpPut(Backend_Endpoint+"/"+registrationId); request.setEntity(new StringEntity(deviceInfo.toString())); request.addHeader("Authorization", "Basic "+authorizationHeader); request.addHeader("Content-Type", "application/json"); HttpResponse response = httpClient.execute(request); int statusCode = response.getStatusLine().getStatusCode(); return statusCode; } private String retrieveRegistrationIdOrRequestNewOne(String handle) throws ClientProtocolException, IOException { if (settings.contains(REGID_SETTING_NAME)) return settings.getString(REGID_SETTING_NAME, null); HttpUriRequest request = new HttpPost(Backend_Endpoint+"?handle="+handle); request.addHeader("Authorization", "Basic "+authorizationHeader); HttpResponse response = httpClient.execute(request); if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) { Log.e("RegisterClient", "Error creating registrationId: " + response.getStatusLine().getStatusCode()); throw new RuntimeException("Error creating Notification Hubs registrationId"); } String registrationId = EntityUtils.toString(response.getEntity()); registrationId = registrationId.substring(1, registrationId.length()-1); settings.edit().putString(REGID_SETTING_NAME, registrationId).commit(); return registrationId; } }
Questo componente implementa le chiamate REST necessarie per contattare il back-end dell'app allo scopo di effettuare la registrazione per le notifiche push. Archivia inoltre in locale i registrationId creati dall'hub di notifica, come illustrato in Registrazione dal back-end dell'app. Usa un token di autorizzazione memorizzato nell'archivio locale quando si fa clic sul pulsante Accedi.
Nella classe
MainActivity
aggiungere un campo per la classeRegisterClient
e una stringa per l'endpoint del back-end ASP.NET. Assicurarsi di sostituire<Enter Your Backend Endpoint>
con l'endpoint back-end effettivo ottenuto in precedenza. Ad esempio:http://mybackend.azurewebsites.net
.private RegisterClient registerClient; private static final String BACKEND_ENDPOINT = "<Enter Your Backend Endpoint>"; FirebaseInstanceId fcm; String FCM_token = null;
Nella classe
MainActivity
, all'interno del metodoonCreate
, rimuovere o impostare come commento l'inizializzazione del campohub
e la chiamata al metodoregisterWithNotificationHubs
. Aggiungere quindi il codice per inizializzare un'istanza della classeRegisterClient
. Il metodo deve contenere le seguenti righe:@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mainActivity = this; FirebaseService.createChannelAndHandleNotifications(getApplicationContext()); fcm = FirebaseInstanceId.getInstance(); registerClient = new RegisterClient(this, BACKEND_ENDPOINT); setContentView(R.layout.activity_main); }
Aggiungere le istruzioni
import
seguenti al fileMainActivity.java
.import android.util.Base64; import android.view.View; import android.widget.EditText; import android.widget.Button; import android.widget.ToggleButton; import java.io.UnsupportedEncodingException; import android.content.Context; import java.util.HashSet; import android.widget.Toast; import org.apache.http.client.ClientProtocolException; import java.io.IOException; import org.apache.http.HttpStatus; import android.os.AsyncTask; import org.apache.http.HttpResponse; import org.apache.http.client.methods.HttpPost; import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.DefaultHttpClient; import android.app.AlertDialog; import android.content.DialogInterface; import com.google.firebase.iid.FirebaseInstanceId; import com.google.firebase.iid.InstanceIdResult; import com.google.android.gms.tasks.OnSuccessListener; import java.util.concurrent.TimeUnit;
Sostituire il codice metodo onStart con il codice seguente:
super.onStart(); Button sendPush = (Button) findViewById(R.id.sendbutton); sendPush.setEnabled(false);
Aggiungere quindi i metodi seguenti per gestire l'evento clic del pulsante Accedi e inviare notifiche push.
public void login(View view) throws UnsupportedEncodingException { this.registerClient.setAuthorizationHeader(getAuthorizationHeader()); final Context context = this; new AsyncTask<Object, Object, Object>() { @Override protected Object doInBackground(Object... params) { try { FirebaseInstanceId.getInstance().getInstanceId().addOnSuccessListener(new OnSuccessListener<InstanceIdResult>() { @Override public void onSuccess(InstanceIdResult instanceIdResult) { FCM_token = instanceIdResult.getToken(); Log.d(TAG, "FCM Registration Token: " + FCM_token); } }); TimeUnit.SECONDS.sleep(1); registerClient.register(FCM_token, new HashSet<String>()); } catch (Exception e) { DialogNotify("MainActivity - Failed to register", e.getMessage()); return e; } return null; } protected void onPostExecute(Object result) { Button sendPush = (Button) findViewById(R.id.sendbutton); sendPush.setEnabled(true); Toast.makeText(context, "Signed in and registered.", Toast.LENGTH_LONG).show(); } }.execute(null, null, null); } private String getAuthorizationHeader() throws UnsupportedEncodingException { EditText username = (EditText) findViewById(R.id.usernameText); EditText password = (EditText) findViewById(R.id.passwordText); String basicAuthHeader = username.getText().toString()+":"+password.getText().toString(); basicAuthHeader = Base64.encodeToString(basicAuthHeader.getBytes("UTF-8"), Base64.NO_WRAP); return basicAuthHeader; } /** * This method calls the ASP.NET WebAPI backend to send the notification message * to the platform notification service based on the pns parameter. * * @param pns The platform notification service to send the notification message to. Must * be one of the following ("wns", "fcm", "apns"). * @param userTag The tag for the user who will receive the notification message. This string * must not contain spaces or special characters. * @param message The notification message string. This string must include the double quotes * to be used as JSON content. */ public void sendPush(final String pns, final String userTag, final String message) throws ClientProtocolException, IOException { new AsyncTask<Object, Object, Object>() { @Override protected Object doInBackground(Object... params) { try { String uri = BACKEND_ENDPOINT + "/api/notifications"; uri += "?pns=" + pns; uri += "&to_tag=" + userTag; HttpPost request = new HttpPost(uri); request.addHeader("Authorization", "Basic "+ getAuthorizationHeader()); request.setEntity(new StringEntity(message)); request.addHeader("Content-Type", "application/json"); HttpResponse response = new DefaultHttpClient().execute(request); if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) { DialogNotify("MainActivity - Error sending " + pns + " notification", response.getStatusLine().toString()); throw new RuntimeException("Error sending notification"); } } catch (Exception e) { DialogNotify("MainActivity - Failed to send " + pns + " notification ", e.getMessage()); return e; } return null; } }.execute(null, null, null); }
Il gestore
login
per il pulsante Accedi genera un token di autenticazione di base usando il nome utente e la password di input (rappresenta qualsiasi token usato dallo schema di autenticazione), quindi usaRegisterClient
per chiamare il back-end per la registrazione.Il metodo
sendPush
chiama il back-end per attivare una notifica sicura per l'utente in base al tag user. Il servizio di notifica della piattaforma a cui è destinatosendPush
dipende dalla stringapns
passata.Aggiungere il seguente metodo
DialogNotify
alla classeMainActivity
.protected void DialogNotify(String title, String message) { AlertDialog alertDialog = new AlertDialog.Builder(MainActivity.this).create(); alertDialog.setTitle(title); alertDialog.setMessage(message); alertDialog.setButton(AlertDialog.BUTTON_NEUTRAL, "OK", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); } }); alertDialog.show(); }
Nella classe
MainActivity
aggiornare il metodosendNotificationButtonOnClick
per chiamare il metodosendPush
con i servizi di notifica della piattaforma selezionati dell'utente, come indicato di seguito./** * Send Notification button click handler. This method sends the push notification * message to each platform selected. * * @param v The view */ public void sendNotificationButtonOnClick(View v) throws ClientProtocolException, IOException { String nhMessageTag = ((EditText) findViewById(R.id.editTextNotificationMessageTag)) .getText().toString(); String nhMessage = ((EditText) findViewById(R.id.editTextNotificationMessage)) .getText().toString(); // JSON String nhMessage = "\"" + nhMessage + "\""; if (((ToggleButton)findViewById(R.id.toggleButtonWNS)).isChecked()) { sendPush("wns", nhMessageTag, nhMessage); } if (((ToggleButton)findViewById(R.id.toggleButtonFCM)).isChecked()) { sendPush("fcm", nhMessageTag, nhMessage); } if (((ToggleButton)findViewById(R.id.toggleButtonAPNS)).isChecked()) { sendPush("apns", nhMessageTag, nhMessage); } }
Nel file
build.gradle
aggiungere la riga seguente alla sezioneandroid
dopo la sezionebuildTypes
.useLibrary 'org.apache.http.legacy'
Se l'app è destinata al livello API 28 (Android 9.0) o versione successiva, includere la dichiarazione seguente nell'elemento
<application>
diAndroidManifest.xml
.<uses-library android:name="org.apache.http.legacy" android:required="false" />
Compilare il progetto.
Testare l'app
Eseguire l'applicazione su un dispositivo o un emulatore tramite Android Studio.
Nell'app per Android immettere un nome utente e una password. Devono avere lo stesso valore di stringa e non devono contenere spazi o caratteri speciali.
Nell'app per Android fare clic su Accedi. Attendere che venga visualizzato un avviso popup che indica che sono stati effettuati l'accesso e la registrazione. Viene abilitato il pulsante Send Notification (Invia notifica).
Fare clic sugli interruttori per abilitare tutte le piattaforme in cui è stata eseguita l'app ed è stato registrato un utente.
Immettere il nome dell'utente che riceve il messaggio di notifica. L'utente dovrà essere registrato per le notifiche nei dispositivi di destinazione.
Immettere un messaggio che l'utente riceverà come messaggio di notifica push.
Fare clic su Send Notification. Ogni dispositivo che ha una registrazione con il tag nome utente corrispondente riceve la notifica push.
Passaggi successivi
In questa esercitazione è stato descritto come inviare notifiche push a utenti specifici che hanno tag associati alle loro registrazioni. Per informazioni sulle procedure per effettuare il push di notifiche in base alla posizione, passare all'esercitazione seguente: