Delen via


Zelfstudie: Pushmeldingen verzenden naar specifieke Android-apps met behulp van Azure Notification Hubs

In deze zelfstudie wordt uitgelegd hoe u met Azure Notification Hubs pushmeldingen kunt verzenden naar een specifieke app-gebruiker op een specifiek apparaat. Er wordt een WebAPI-back-end van ASP.NET gebruikt om clients te verifiëren en meldingen te genereren, zoals u kunt lezen in het artikel Registering from your App Backend (Registreren vanuit uw app-back-end). Deze zelfstudie bouwt voort op de Notification Hub die u in de zelfstudie hebt gemaakt: Pushmeldingen verzenden naar Android-apparaten met behulp van Azure Notification Hubs en Firebase Cloud Messaging.

In deze zelfstudie voert u de volgende stappen uit:

  • Het Web API-project voor de back-end maken waarmee gebruikers worden geverifieerd.
  • De Android-toepassing bijwerken.
  • De app testen

Vereisten

Voltooi de zelfstudie: Pushmeldingen verzenden naar Android-apparaten met behulp van Azure Notification Hubs en Firebase Cloud Messaging voordat u deze zelfstudie uitvoert.

Het WebAPI-project maken

In de volgende secties wordt het maken van een nieuwe ASP.NET WebAPI-back-end besproken. Dit proces heeft drie hoofddoelen:

  • Clients verifiëren: er wordt een berichtenhandler toegevoegd voor het verifiëren van aanvragen van clients en het koppelen van de gebruiker aan de aanvraag.
  • Registreren voor meldingen met behulp van de WebAPI-back-end: u voegt een controller toe voor het afhandelen van nieuwe registraties voor een clientapparaat voor het ontvangen van meldingen. De naam van de geverifieerde gebruiker wordt automatisch aan de registratie toegevoegd als een tag.
  • Meldingen verzenden naar clients: u voegt een controller toe om gebruikers een manier te bieden voor het activeren van een beveiligde push naar apparaten en clients die zijn gekoppeld aan de tag.

Maak de nieuwe ASP.NET Core 6.0-web-API-back-end door de volgende acties uit te voeren:

Start Visual Studio om dit te controleren. Selecteer Extensies en updates in het menu Extra. Zoek naar NuGet Package Manager in uw versie van Visual Studio en controleer of u de meest recente versie hebt. Als uw versie niet de nieuwste versie is, verwijdert u deze en installeert u NuGet Package Manager.

Screenshot of the Extensions and Updates dialog box with the NuGet Package manage for Visual Studios package highlighted.

Notitie

Controleer of u de Visual Studio Azure SDK voor website-implementatie hebt geïnstalleerd.

  1. Start Visual Studio of Visual Studio Express.

  2. Selecteer Server Explorer en meld u aan bij uw Azure-account. U moet zijn aangemeld om de websiteresources voor uw account te maken.

  3. Selecteer Nieuw>project in het menu Bestand van Visual Studio.

  4. Voer de web-API in het zoekvak in.

  5. Selecteer de ASP.NET Core Web API-projectsjabloon en selecteer Volgende.

  6. Geef in het dialoogvenster Uw nieuwe project configureren de naam AppBackend van het project en selecteer Volgende.

  7. In het dialoogvenster Aanvullende informatie :

    • Controleer of het Framework .NET 6.0 (langetermijnondersteuning) is.
    • Controleer of het selectievakje voor Controllers gebruiken (schakel het selectievakje uit om minimale API's te gebruiken) is ingeschakeld.
    • Schakel openAPI-ondersteuning inschakelen uit.
    • Selecteer Maken.

De WeatherForecast-sjabloonbestanden verwijderen

  1. Verwijder de WeatherForecast.cs en controllers/WeatherForecastController.cs voorbeeldbestanden uit het nieuwe AppBackend-project .
  2. Open Properties\launch Instellingen.json.
  3. StartUrl-eigenschappen wijzigen van weatherforcast in appbackend.

Selecteer een abonnement in het venster Microsoft Azure Web App configureren en voer in de lijst App Service-plan een van de volgende acties uit:

  • Selecteer een Azure-app Service-plan dat u al hebt gemaakt.
  • Selecteer Een nieuw App Service-plan maken, en maak er vervolgens een.

U hebt geen database nodig voor deze zelfstudie. Nadat u uw App Service-plan hebt geselecteerd, selecteert u OK om het project te maken.

The Configure Microsoft Azure Web App window

Als u deze pagina voor het configureren van het App Service-plan niet ziet, gaat u door met de zelfstudie. U kunt het configureren en de app later publiceren.

Clients verifiëren bij de WebAPI-back-end

In deze sectie maakt u een nieuwe berichtenhandlerklasse met de naam AuthenticationTestHandler voor de nieuwe back-end. Deze klasse wordt afgeleid van DelegatingHandler en toegevoegd als een berichtenhandler zodat deze alle aanvragen die de back-end ontvangt, kan verwerken.

  1. Klik in Solution Explorer met de rechtermuisknop op het project AppBackend, selecteer Toevoegen en selecteer vervolgens Klasse.

  2. Geef de nieuwe klasse de naam AuthenticationTestHandler.cs en selecteer Toevoegen om de klasse te genereren. Deze klasse verifieert gebruikers met behulp van Basisverificatie om het eenvoudig te houden. Uw app kan een willekeurig verificatieschema gebruiken.

  3. Voeg in AuthenticationTestHandler.cs de volgende using-instructies toe:

    using System.Net.Http;
    using System.Threading;
    using System.Security.Principal;
    using System.Net;
    using System.Text;
    using System.Threading.Tasks;
    
  4. Vervang in AuthenticationTestHandler.cs de AuthenticationTestHandler-klassedefinitie door de volgende code:

    Deze handler verifieert de aanvraag wanneer de volgende drie voorwaarden waar zijn:

    • De aanvraag bevat een autorisatieheader.
    • De aanvraag maakt gebruik van basisverificatie.
    • De gebruikersnaamtekenreeks en de wachtwoordtekenreeks zijn dezelfde tekenreeks.

    Anders wordt de aanvraag geweigerd. Deze verificatie is geen bestaande benadering op verificatie en autorisatie. Dit is slechts een eenvoudig voorbeeld voor deze zelfstudie.

    Als het aanvraagbericht is geverifieerd en geautoriseerd door AuthenticationTestHandler, wordt de basisverificatiegebruiker toegevoegd aan de huidige aanvraag in HttpContext. Gebruikersgegevens in HttpContext worden later gebruikt door een andere controller (RegisterController) om een tag toe te voegen aan de aanvraag voor meldingen van registraties.

    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;
        }
    }
    

    Notitie

    Opmerking over beveiliging: de AuthenticationTestHandler-klasse biedt geen echte verificatie. Het wordt alleen gebruikt om basisverificatie na te bootsen en is niet beveiligd. U moet een veilig verificatiemechanisme implementeren in uw productietoepassingen en -services.

  5. Als u de berichthandler wilt registreren, voegt u de volgende code toe aan het einde van de Register methode in het bestand Program.cs :

    config.MessageHandlers.Add(new AuthenticationTestHandler());
    
  6. Sla uw wijzigingen op.

Registreren voor meldingen met behulp van de WebAPI-back-end

In deze sectie voegen we een nieuwe controller toe aan de WebAPI-back-end om aanvragen voor het registreren van een gebruiker en een apparaat voor meldingen af te handelen met behulp van de clientbibliotheek voor notification hubs. De controller voegt een gebruikerstag toe voor de gebruiker die door AuthenticationTestHandler is geverifieerd en gekoppeld aan HttpContext. De tag heeft de indeling van de tekenreeks, "username:<actual username>".

  1. Klik in Solution Explorer met de rechtermuisknop op het project AppBackend en selecteer vervolgens NuGet-pakketten beheren.

  2. Selecteer in het linkerdeelvenster Online en typ Microsoft.Azure.NotificationHubs in het vak Zoeken.

  3. Selecteer Microsoft Azure Notification Hubs in de lijst met resultaten en selecteer vervolgens Installeren. Voltooi de installatie en sluit vervolgens het venster Nuget Package Manager.

    Met deze actie wordt een verwijzing toegevoegd aan de Azure Notification Hubs-SDK met het Microsoft.Azure.Notification Hubs NuGet-pakket.

  4. Maak een nieuw klassebestand waarmee de verbinding met de notification hub die wordt gebruikt voor het verzenden van meldingen. Klik in Solution Explorer met de rechtermuisknop op de map Modellen en selecteer achtereenvolgens Toevoegen en Klasse. Noem de nieuwe klasse Notifications.cs en selecteer vervolgens Toevoegen om de klasse te genereren.

    The Add New Item window

  5. Voeg in Notifications.cs de volgende using-instructie toe aan het begin van het bestand:

    using Microsoft.Azure.NotificationHubs;
    
  6. Vervang de Notifications-klassedefinitie door de volgende code en vervang de twee tijdelijke aanduidingen door de verbindingsreeks (met volledige toegang) voor uw notification hub en de naam van de hub (beschikbaar in Azure Portal):

    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>");
        }
    }
    

    Belangrijk

    Voer de naam en de DefaultListenSharedAccessSignature van uw hub in voordat u verdergaat.

  7. Maak vervolgens een nieuwe controller met de naam RegisterController. Klik in Solution Explorer met de rechtermuisknop op de map Controllers en selecteer achtereenvolgens Toevoegen en Controller.

  8. Selecteer API-controller - leeg en selecteer vervolgens Toevoegen.

  9. Typ in het vak ControllernaamRegisterController als naam voor de nieuwe klasse en selecteer vervolgens Toevoegen.

    The Add Controller window.

  10. Voeg in RegisterController.cs de volgende using-instructies toe:

    using Microsoft.Azure.NotificationHubs;
    using Microsoft.Azure.NotificationHubs.Messaging;
    using AppBackend.Models;
    using System.Threading.Tasks;
    using System.Web;
    
  11. Voeg de volgende code in de RegisterController-klassedefinitie. In deze code voegt u een gebruikerstag toe voor de gebruiker die is gekoppeld aan HttpContext. De gebruiker is geverifieerd en gekoppeld aan HttpContext door het berichtenfilter dat u hebt toegevoegd, AuthenticationTestHandler. U kunt ook optionele controles toevoegen om te controleren of de gebruiker rechten heeft voor het registreren voor de aangevraagde tags.

    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());
        }
    }
    
  12. Sla uw wijzigingen op.

Meldingen verzenden vanuit de WebAPI-back-end

In deze sectie voegt u een nieuwe domeincontroller toe die clientapparaten een manier biedt om een melding te verzenden. De melding is gebaseerd op de gebruikersnaamtag die gebruikmaakt van de Azure Notification Hubs .NET-bibliotheek in de ASP.NET WebAPI-back-end.

  1. Maak nog een nieuwe controller met de naam NotificationsController op dezelfde manier als u RegisterController in de vorige sectie hebt gemaakt.

  2. Voeg in NotificationsController.cs de volgende using-instructies toe:

    using AppBackend.Models;
    using System.Threading.Tasks;
    using System.Web;
    
  3. Voeg de volgende methode toe aan de klasse NotificationsController:

    Met deze code wordt een meldingstype verzonden die is gebaseerd op de pns-parameter (Platform Notification Service, PNS). De waarde van to_tag wordt gebruikt om de tag gebruikersnaam in te stellen in het bericht. Deze tag moet overeenkomen met een gebruikersnaamtag van een actieve notification hub-registratie. Het meldingsbericht wordt opgehaald uit de hoofdtekst van de POST-aanvraag en geformatteerd voor de doel-PNS.

    Afhankelijk van de PNS die uw ondersteunde apparaten gebruiken om meldingen te ontvangen, worden de meldingen met verschillende indelingen ondersteund. Bijvoorbeeld op Windows-apparaten kunt u een pop-upmelding met WNS gebruiken die niet rechtstreeks wordt ondersteund door een andere PNS. In een dergelijk geval moet uw back-end de melding in een ondersteunde melding indelen voor de PNS van apparaten die u wilt ondersteunen. Gebruik vervolgens de juiste API voor verzending in de NotificationHubClient-klasse.

    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);
    }
    
  4. Selecteer de toets F5 om de toepassing uit te voeren en om de juistheid van uw werk tot nu toe te controleren. De app opent een webbrowser en deze wordt weergegeven met de startpagina van ASP.NET.

De nieuwe WebAPI-back-end publiceren

U gaat de app nu implementeren op een Azure-website zodat deze toegankelijk is vanaf alle apparaten.

  1. Klik met de rechtermuisknop op het project AppBackend en selecteer Publiceren.

  2. Selecteer Microsoft Azure App Service als publicatiedoel en selecteer vervolgens \*\*Publiceren. Het venster App Service maken wordt geopend. Hier kunt u alle benodigde Azure-resources maken die nodig zijn om de ASP.NET-web-app in Azure uit te voeren.

    The Microsoft Azure App Service tile

  3. Selecteer uw Azure-account in het venster App Service maken. Selecteer Type wijzigen>Web App. Houd de standaard Web App-naam en selecteer het Abonnement, de Resourcegroep en het App Service-plan.

  4. Selecteer Maken.

  5. Noteer de Site-URL-eigenschap in de sectie Samenvatting. Deze URL is het eindpunt van uw back-end verderop in de zelfstudie.

  6. Selecteer Publiceren.

Nadat u de wizard hebt voltooid, wordt de ASP.NET-web-app naar Azure gepubliceerd. Daarna wordt de app geopend in de standaardbrowser. Uw toepassing is zichtbaar in Azure App Services.

De URL gebruikt de naam van de web-app die u eerder hebt opgegeven, met de indeling http://< app_name.azurewebsites.net>.

Het Android-project maken

De volgende stap is het bijwerken van de Android-toepassing die is gemaakt in de zelfstudie: Pushmeldingen verzenden naar Android-apparaten met behulp van Azure Notification Hubs en Firebase Cloud Messaging.

  1. Open het bestand res/layout/activity_main.xml en vervang de volgende inhoudsdefinities:

    Hiermee worden nieuwe EditText-besturingselementen toegevoegd voor aanmelding als een gebruiker. Er wordt ook een veld toegevoegd voor een gebruikersnaam-tag die deel gaat uitmaken van meldingen die u verzendt:

    <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>
    
  2. Open het bestand res/values/strings.xml en vervang de definitie send_button door de volgende regels die de tekenreeks voor de send_button aanpassen. Voeg vervolgens tekenreeksen toe voor de andere besturingselementen:

    <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>
    

    De grafische indeling van main_activity.xml ziet er nu uit als in de volgende afbeelding:

    Screenshot of an emulator displaying what the main activity X M L graphical layout will look like.

  3. Maak in hetzelfde pakket als de klasse MainActivity een nieuwe klasse met de naam RegisterClient. Gebruik de onderstaande code voor het nieuwe klassebestand.

    
    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;
        }
    }
    

    Dit onderdeel implementeert de REST-aanroepen die nodig zijn om contact op te nemen met de app-back-end, om registratie voor pushmeldingen mogelijk te maken. Daarnaast wordt de registrationIds die is gemaakt door de Notification Hub, lokaal opgeslagen. Zie Registering from your App Backend (Registreren vanuit uw app-back-end) voor meer informatie. De klasse maakt gebruik van een verificatietoken dat wordt opgeslagen in de lokale opslag wanneer u op de knop Sign in klikt.

  4. Voeg in uw klasse MainActivity een veld toe voor de klasse RegisterClient en een tekenreeks voor het eindpunt van uw ASP.NET-back-end. Zorg ervoor dat u <Enter Your Backend Endpoint> vervangt door het eindpunt van de back-end dat u eerder hebt vastgesteld. Bijvoorbeeld: http://mybackend.azurewebsites.net.

    private RegisterClient registerClient;
    private static final String BACKEND_ENDPOINT = "<Enter Your Backend Endpoint>";
    FirebaseInstanceId fcm;
    String FCM_token = null;
    
  5. Ga in de klasse MainActivity naar de methode onCreate en verwijder de initialisatie van het veld hub en de aanroep van de methode registerWithNotificationHubs of maak er een commentaar van. Voeg vervolgens code toe voor het initialiseren van een exemplaar van de klasse RegisterClient. De methode moet de volgende regels bevatten:

    @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);
    }
    
  6. Voeg de volgende instructies voor import toe aan uw MainActivity.java-bestand.

    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;
    
  7. Vervang de code van de onStart-methode door de volgende code:

    super.onStart();
    Button sendPush = (Button) findViewById(R.id.sendbutton);
    sendPush.setEnabled(false);
    
  8. Voeg vervolgens de volgende methoden toe voor het afhandelen van het klikken op de knop Sign in en het verzenden van pushmeldingen.

    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);
    }
    

    De login-handler voor de knop Sign in genereert een eenvoudig verificatietoken op basis van de gebruikersnaam en het wachtwoord die zijn ingevoerd (of ieder ander token dat door uw verificatieschema wordt gebruikt) en gebruikt vervolgens RegisterClient om de back-end aan te roepen voor registratie.

    De methode sendPush roept de back-end aan om een beveiligde melding te activeren naar de gebruiker, op basis van de gebruikerstag. De Platform Notification Service die door sendPush wordt benaderd, is afhankelijk van de pns-tekenreeks die wordt doorgegeven.

  9. Voeg de volgende methode DialogNotify toe aan de klasse MainActivity.

    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();
    }
    
  10. Werk in uw klasse MainActivity de methode sendNotificationButtonOnClick als volgt bij voor het aanroepen van de methode sendPush met de door de gebruiker geselecteerd Platform Notification Services.

    /**
    * 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);
        }
    }
    
  11. Voeg in het bestand build.gradle de volgende regel toe aan de sectie android na de sectie buildTypes.

    useLibrary 'org.apache.http.legacy'
    
  12. Als uw app is gericht op API-niveau 28 (Android 9.0) of hoger, neemt u de volgende declaratie op in het <application>-element van AndroidManifest.xml.

    <uses-library
        android:name="org.apache.http.legacy"
        android:required="false" />
    
  13. Maak het project.

De app testen

  1. Voer de toepassing uit op een apparaat of in een emulator met Android Studio.

  2. Voer in de Android-app een gebruikersnaam en wachtwoord in. Deze moeten beide dezelfde tekenreekswaarde zijn en ze mogen geen spaties of speciale tekens bevatten.

  3. Klik in de Android-app op Sign in. Wacht tot u het pop-upbericht Signed in and registered ziet. De knop Send Notification kan nu worden gekozen.

    Screenshot of an emulator showing what the Notification Hubs Notify Users app looks like after logging in.

  4. Klik op de wisselknoppen om alle platforms in te schakelen waarop u de app hebt uitgevoerd en een gebruiker hebt geregistreerd.

  5. Voer de naam van de gebruiker in die de melding moet ontvangen. Die gebruiker moet zijn geregistreerd voor meldingen op de doelapparaten.

  6. Voer een bericht in dat de gebruiker als een pushmelding moet ontvangen.

  7. Klik op Send Notification. Elk apparaat dat een registratie heeft met de overeenkomende gebruikersnaam-tag ontvangt de pushmelding.

Volgende stappen

In deze zelfstudie hebt u geleerd hoe u pushmeldingen kunt verzenden naar specifieke gebruikers door een tag te koppelen aan hun registraties. Als u wilt weten hoe u locatiegebaseerde pushmeldingen kunt verzenden, gaat u verder met de volgende zelfstudie: