Aracılığıyla paylaş


Öğretici: Azure Notification Hubs kullanarak belirli Android uygulamalarına anında iletme bildirimleri gönderme

Not

Firebase Cloud Messaging'in kullanımdan kaldırılması ve geçiş adımları hakkında bilgi için bkz . Google Firebase Cloud Messaging geçişi.

Bu öğreticide, belirli bir cihazdaki belirli bir uygulama kullanıcısına anında iletme bildirimleri göndermek için Azure Bildirim Hubs’ı nasıl kullanacağınız gösterilmektedir. Uygulama arka ucunuzdan kaydolma başlıklı yönerge makalesinde gösterildiği gibi, istemcilerin kimliğini doğrulamak ve bildirimler oluşturmak için ASP.NET WebAPI arka ucu kullanılır. Bu öğretici, Öğretici: Azure Notification Hubs ve Firebase Cloud Messaging kullanarak Android cihazlara anında iletme bildirimleri gönderme öğreticisinde oluşturduğunuz bildirim hub'ını temel alır.

Bu öğreticide, aşağıdaki adımları gerçekleştireceksiniz:

  • Kullanıcıların kimliğini doğrulayan arka uç Web API projesi oluşturma.
  • Android uygulamasını güncelleştirme.
  • Uygulamayı test etme

Önkoşullar

Bu öğreticiyi gerçekleştirmeden önce Azure Notification Hubs ve Firebase Cloud Messaging kullanarak Android cihazlara anında iletme bildirimleri gönderme öğreticisini tamamlayın.

WebAPI projesi oluşturma

Aşağıdaki bölümlerde, yeni bir ASP.NET WebAPI arka ucu oluşturma işlemi açıklanmaktadır. Bu işlemin üç ana amacı vardır:

  • İstemcilerin kimliğini doğrulama: İstemci isteklerinin kimliğini doğrulamak ve kullanıcıyı istekle ilişkilendirmek üzere bir ileti işleyicisi eklersiniz.
  • WebAPI arka ucunu kullanarak bildirimlere kaydolma: Bir istemci cihazının bildirimleri alması için yeni kayıtları işlemek üzere bir denetleyici eklersiniz. Kimliği doğrulanmış kullanıcı adı, otomatik olarak kayda bir etiket halinde eklenir.
  • İstemcilere bildirimleri gönderme: Kullanıcıların etiketle ilişkili cihazlara ve istemcilere güvenli bir gönderimi tetiklemesi için yeni bir yol sağlamak üzere bir denetleyici de eklersiniz.

Aşağıdaki eylemleri gerçekleştirerek yeni ASP.NET Core 6.0 web API arka ucu oluşturun:

Denetlemek için Visual Studio’yu başlatın. Araçlar menüsünde Uzantılar ve Güncelleştirmeler’i seçin. Visual Studio sürümünüz için NuGet Paket Yöneticisi araması yapın ve en son sürümü kullandığınızdan emin olun. Sürümünüz en son sürüm değilse, bunu kaldırın ve NuGet Paket Yöneticisi'ni yeniden yükleyin.

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

Not

Web sitesi dağıtımı için Visual Studio Azure SDK’sını yüklediğinizden emin olun.

  1. Visual Studio veya Visual Studio Express’i başlatın.

  2. Sunucu Gezgini’ni seçip Azure hesabınızda oturum açın. Hesabınızda web sitesi kaynakları oluşturmak için oturum açmanız gerekir.

  3. Visual Studio'nun Dosya menüsünde Yeni Proje'yi> seçin.

  4. Arama kutusuna Web API'sini girin.

  5. ASP.NET Core Web API proje şablonunu seçin ve İleri'yi seçin.

  6. Yeni projenizi yapılandırın iletişim kutusunda projeyi AppBackend olarak adlandırın ve İleri'yi seçin.

  7. Ek bilgi iletişim kutusunda:

    • Framework'ün .NET 6.0 (Uzun vadeli destek) olduğunu onaylayın.
    • Denetleyicileri kullan (en az API kullanmak için işaretini kaldırın) onay kutusunun işaretli olduğunu onaylayın.
    • OpenAPI desteğini etkinleştir seçeneğinin işaretini kaldırın.
    • Oluştur'u belirleyin.

WeatherForecast şablon dosyalarını kaldırma

  1. Yeni AppBackend projesinden WeatherForecast.cs ve Denetleyiciler/WeatherForecastController.cs örnek dosyalarını kaldırın.
  2. Özellikler\başlatma Ayarlar.json açın.
  3. launchUrl özelliklerini weatherforcast olan appbackend olarak değiştirin.

Microsoft Azure Web App’i yapılandırma penceresinde, bir abonelik seçin ve App Service planı listesinde aşağıdaki eylemlerden birini yapın:

  • Önceden oluşturduğunuz bir Azure Uygulaması Hizmet planı seçin.
  • Yeni bir App Service planı oluştur’u seçin ve yeni bir plan oluşturun.

Bu öğretici için bir veritabanı gerekmez. App Service planınızı seçtikten sonra projeyi oluşturmak için Tamam’ı seçin.

The Configure Microsoft Azure Web App window

App Service planını yapılandırmak için bu sayfayı görmüyorsanız öğreticiye devam edin. Uygulamayı daha sonra yayımlarken yapılandırabilirsiniz.

WebAPI arka ucunda istemcilerin kimliğini doğrulama

Bu bölümde, yeni arka uç için AuthenticationTestHandler adlı yeni bir ileti işleyicisi oluşturacaksınız. Bu sınıf DelegatingHandler’dan türetilip bir ileti işleyicisi olarak eklenir, böylece arka uca gelen tüm istekleri işleyebilir.

  1. Çözüm Gezgini'nde AppBackend projesine sağ tıklayın, Ekle'yi ve ardından Sınıf'ı seçin.

  2. Yeni AuthenticationTestHandler.cs sınıfını adlandırıp Ekle’yi seçerek sınıfı oluşturun. Bu sınıf, kolaylık için Temel Kimlik Doğrulaması kullanarak kullanıcıların kimliklerini doğrular. Uygulamanız herhangi bir kimlik doğrulama şemasını kullanabilir.

  3. AuthenticationTestHandler.cs sınıfına aşağıdaki using deyimlerini ekleyin:

    using System.Net.Http;
    using System.Threading;
    using System.Security.Principal;
    using System.Net;
    using System.Text;
    using System.Threading.Tasks;
    
  4. AuthenticationTestHandler.cs sınıfında AuthenticationTestHandler sınıf tanımını aşağıdaki kod ile değiştirin:

    Bu işleyici aşağıdaki üç koşul geçerli olduğunda bu isteği yetkilendirir:

    • İstek bir Yetkilendirme üst bilgisi içerir.
    • İstek temel kimlik doğrulaması kullanır.
    • Kullanıcı adı dizesi ve parola dizesi aynı dizelerdir.

    Aksi takdirde istek reddedilir. Bu kimlik doğrulama işlemi, geçerli bir kimlik doğrulama ve yetkilendirme yaklaşımı değildir. Yalnızca bu öğreticiye yönelik basit bir örnektir.

    İstek iletisi AuthenticationTestHandler tarafından kimlik doğrulaması yapılır ve yetkilendirilirse, temel kimlik doğrulaması kullanıcısı HttpContext üzerindeki geçerli isteğe eklenir. HttpContext içindeki kullanıcı bilgileri, bildirim kaydı isteğine bir etiket eklemek amacıyla daha sonra başka bir denetleyici (RegisterController) tarafından kullanılır.

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

    Not

    Güvenlik notu: AuthenticationTestHandler sınıfı gerçek kimlik doğrulaması sağlamaz. Yalnızca temel kimlik doğrulamasını taklit etmek için kullanılır ve güvenli değildir. Üretim uygulamalarınızda ve hizmetlerinizde güvenli bir kimlik doğrulama mekanizması uygulamanız gerekir.

  5. İleti işleyicisini kaydetmek için Program.cs dosyasında yönteminin Register sonuna aşağıdaki kodu ekleyin:

    config.MessageHandlers.Add(new AuthenticationTestHandler());
    
  6. Değişikliklerinizi kaydedin.

WebAPI arka ucunu kullanarak bildirimlere kaydolma

Bu bölümde, bildirim hub’ları için istemci kitaplığını kullanarak WebAPI arka ucuna bir kullanıcı ve cihazı bildirimlere kaydetme isteklerini işlemek üzere yeni bir denetleyici ekleyeceksiniz. Denetleyici, kimliği doğrulanmış ve AuthenticationTestHandler tarafından HttpContext’e eklenmiş kullanıcı için bir kullanıcı etiketi ekler. Etiket "username:<actual username>" dize biçiminde olacaktır.

  1. Çözüm Gezgini'nde, AppBackend projesine sağ tıklayın ve ardından NuGet Paketlerini Yönet'i seçin.

  2. Sol bölmede Çevrimiçi’ni seçin ve Arama kutusuna Microsoft.Azure.NotificationHubs yazın.

  3. Sonuç listesinde Microsoft Azure Notification Hubs’ı ve ardından Yükle’yi seçin. Yüklemeyi tamamlayın ve sonra NuGet Paket Yöneticisi penceresini kapatın.

    Bu eylem Microsoft.Azure.Notification Hubs NuGet paketini kullanarak Azure Notification Hubs SDK'sına bir başvuru ekler.

  4. Bildirimleri göndermek için kullanılan bildirim hub'ı bağlantısını temsil eden yeni bir sınıf dosyası oluşturun. Çözüm Gezgini'nde Modeller klasörüne sağ tıklayın, Ekle'yi ve ardından Sınıf'ı seçin. Yeni sınıfı Notifications.cs olarak adlandırın, ardından Ekle’yi seçerek sınıfı oluşturun.

    The Add New Item window

  5. Notifications.cs sınıfında aşağıdaki using deyimini dosyanın üst kısmına ekleyin:

    using Microsoft.Azure.NotificationHubs;
    
  6. Notifications sınıf tanımını aşağıdaki kodla değiştirin ve iki yer tutucuyu bildirim hub’ınızın bağlantı dizesi (tam erişimli) ve hub adı ile değiştirdiğinizden emin olun (Azure portalında bulunabilir):

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

    Önemli

    Devam etmeden önce hub'ınızın adını ve DefaultFullSharedAccessSignature değerini girin.

  7. Ardından RegisterController adlı yeni bir denetleyici oluşturun. Çözüm Gezgini'nde Denetleyiciler klasörüne sağ tıklayın, Ekle'yi ve ardından Denetleyici'yi seçin.

  8. API Denetleyicisi - Boş'a ve ardından Ekle'ye tıklayın.

  9. Denetleyici adı kutusuna, yeni sınıfı adlandırmak için RegisterController yazın ve Ekle’yi seçin.

    The Add Controller window.

  10. RegisterController.cs sınıfına aşağıdaki using deyimlerini ekleyin:

    using Microsoft.Azure.NotificationHubs;
    using Microsoft.Azure.NotificationHubs.Messaging;
    using AppBackend.Models;
    using System.Threading.Tasks;
    using System.Web;
    
  11. Aşağıdaki kodu RegisterController sınıf tanımına ekleyin. Bu kodda, HttpContext’e eklenen kullanıcı için bir kullanıcı etiketi eklersiniz. Kullanıcının kimliği doğrulanmış ve eklediğiniz AuthenticationTestHandler ileti filtresi tarafından HttpContext’e eklenmiştir. Ayrıca, kullanıcının istenen etiketlere kaydolma haklarının olduğunu doğrulamak için isteğe bağlı denetimler ekleyebilirsiniz.

    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. Değişikliklerinizi kaydedin.

WebAPI arka ucundan bildirim gönderme

Bu bölümde, istemci cihazlarına bildirim göndermeleri için bir yol sunan yeni bir denetleyici ekleyeceksiniz. Bildirim, ASP.NET WebAPI arka ucundaki Azure Notification Hubs .NET Kitaplığı’nı kullanan kullanıcı adı etiketini temel alır.

  1. Önceki bölümde RegisterController denetleyicisini oluşturduğunuz gibi NotificationsController adlı yeni bir denetleyici oluşturun.

  2. NotificationsController.cs sınıfına aşağıdaki using deyimlerini ekleyin:

    using AppBackend.Models;
    using System.Threading.Tasks;
    using System.Web;
    
  3. Aşağıdaki yöntemi NotificationsController sınıfına ekleyin:

    Bu kod, Platform Bildirim Hizmeti (PNS) pns parametresini temel alan bir bildirim türü gönderir. to_tag değeri, iletideki kullanıcı adı etiketini ayarlamak için kullanılır. Bu etiket, etkin bir bildirim hub'ı kaydının kullanıcı etiketi ile eşleşmelidir. Bildirim iletisi, POST isteğinin gövdesinden çekilir ve hedef PNS biçimlendirilir.

    Desteklenen cihazlarınızın bildirimleri almak için kullandığı PNS’e bağlı olarak, bildirimler çeşitli biçimler tarafından desteklenmektedir. Örneğin, Windows cihazlarında başka bir PNS tarafından doğrudan desteklenmeyen bir WNS ile bildirim kullanabilirsiniz. Böyle bir durumda arka ucunuzun, desteklemeyi planladığınız cihazların PNS’si için bildirimi desteklenen bir bildirim biçimine dönüştürmesi gerekir. Daha sonra NotificationHubClient sınıfında uygun gönderme API’sini kullanın.

    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. Uygulamayı çalıştırmak ve o ana kadar gerçekleştirdiğiniz işin doğruluğundan emin olmak için F5 tuşuna basın. Uygulama bir web tarayıcısı açar ve ASP.NET giriş sayfasında görüntülenir.

Yeni WebAPI arka ucunu yayımlama

Ardından bu uygulamayı tüm cihazlardan erişilebilir kılmak için bir Azure web sitesine dağıtacaksınız.

  1. AppBackend projesine sağ tıklayıp Yayımla’yı seçin.

  2. Yayımlama hedefi olarak Microsoft Azure App Service’i ve ardından \*\*Yayımla’yı seçin. App Service Oluştur penceresi açılır. Burada, Azure’da ASP.NET web uygulamasını çalıştırmak için gereken tüm Azure kaynaklarını oluşturabilirsiniz.

    The Microsoft Azure App Service tile

  3. App Service Oluştur penceresinde Azure hesabınızı seçin. Türü Değiştir>Web App’i seçin. Varsayılan Web App Adı’nı değiştirmeyin ve Abonelik, Kaynak Grubu ve App Service Planı’nı seçin.

  4. Oluştur'u belirleyin.

  5. Özet bölümündeki Site URL özelliğini not edin. Bu URL, daha sonra bu öğreticide arka uca ait uç noktanız olacaktır.

  6. Yayımla öğesini seçin.

Sihirbazı tamamladıktan sonra ASP.NET web uygulamasını Azure’da yayımlar ve ardından uygulamayı varsayılan tarayıcıda açar. Uygulamanız Azure App Services’te görüntülenebilir.

URL, daha önce belirttiğiniz web uygulaması adını http://< app_name.azurewebsites.net> biçiminde kullanır.

Android Projesi oluşturma

Sonraki adım, Öğretici: Azure Notification Hubs ve Firebase Cloud Messaging kullanarak Android cihazlara anında iletme bildirimleri gönderme öğreticisinde oluşturulan Android uygulamasını güncelleştirmektir.

  1. Dosyanızı res/layout/activity_main.xml açın, aşağıdaki içerik tanımlarını değiştirin:

    Kullanıcı olarak oturum açmak için yeni EditText denetimleri ekler. Ayrıca gönderdiğiniz bildirimlerin parçası olacak kullanıcı adı etiketi için bir alan da eklenir:

    <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. Dosyanızı res/values/strings.xml açın ve tanımını öğesinin dizesini yeniden tanımlayan ve diğer denetimler için send_button dizeler ekleyen aşağıdaki satırlarla değiştirinsend_button:

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

    Grafik düzeniniz main_activity.xml artık aşağıdaki görüntü gibi görünmelidir:

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

  3. Sınıfınızla MainActivity aynı pakette adlı RegisterClient yeni bir sınıf oluşturun. Yeni sınıf dosyası için aşağıdaki kodu kullanın.

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

    Bu bileşen, anında iletme bildirimlerine kaydolmak üzere uygulama arka ucuna başvurmak için gereken REST çağrılarını uygular. Uygulama arka ucunuzdan kaydetme bölümünde açıklandığı gibi Bildirim Hub’ı tarafından oluşturulan registrationId’leri de yerel olarak depolar. Oturum aç düğmesine tıkladığınızda yerel depolama alanında depolanan bir yetkilendirme belirteci kullanır.

  4. Sınıfınızda sınıfınız MainActivity için RegisterClient bir alan ve ASP.NET arka ucunuzun uç noktası için bir dize ekleyin. <Enter Your Backend Endpoint> değerini, önceden aldığınız gerçek arka ucun uç noktasıyla değiştirdiğinizden emin olun. Örneğin, http://mybackend.azurewebsites.net.

    private RegisterClient registerClient;
    private static final String BACKEND_ENDPOINT = "<Enter Your Backend Endpoint>";
    FirebaseInstanceId fcm;
    String FCM_token = null;
    
  5. MainActivity sınıfınızda onCreate yönteminde, registerWithNotificationHubs yöntemine yapılan çağrının ve hub alanının başlatmasını kaldırın veya açıklama satırı yapın. RegisterClient sınıfının bir örneğini başlatmak için kod ekleyin. Yöntem aşağıdaki satırları içermelidir:

    @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. Aşağıdaki import deyimlerini MainActivity.java dosyanıza ekleyin.

    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. onStart yöntemindeki kodu, aşağıdaki kodla değiştirin:

    super.onStart();
    Button sendPush = (Button) findViewById(R.id.sendbutton);
    sendPush.setEnabled(false);
    
  8. Ardından, Oturum aç düğmesine tıklama olayını işlemek ve anında iletme bildirimleri göndermek için aşağıdaki yöntemleri ekleyin.

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

    login Oturum aç düğmesinin işleyicisi, giriş kullanıcı adı ve parolayı kullanarak temel bir kimlik doğrulama belirteci oluşturur (kimlik doğrulama düzeninizin kullandığı tüm belirteçleri temsil eder), ardından kayıt için arka ucu çağırmak için kullanırRegisterClient.

    sendPush yöntemi, kullanıcı etiketine dayalı olarak kullanıcıya güvenli bir bildirim tetiklemek için arka ucu çağırır. sendPush tarafından hedeflenen platform bildirim hizmeti, geçirilen pns dizesine bağlıdır.

  9. MainActivity sınıfına aşağıdaki DialogNotify yöntemini ekleyin.

    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. MainActivity sınıfınızda, aşağıdaki adımları uygulayarak kullanıcının seçtiği platform bildirim hizmetleriyle sendPush yöntemini çağırmak için sendNotificationButtonOnClick yöntemini güncelleştirin.

    /**
    * 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. build.gradle dosyasında, bölümünden sonraki buildTypes bölüme android aşağıdaki satırı ekleyin.

    useLibrary 'org.apache.http.legacy'
    
  12. Uygulamanız API düzeyi 28 (Android 9.0) veya üzerini hedefleiyorsa öğesinde <application>AndroidManifest.xmlaşağıdaki bildirimi ekleyin.

    <uses-library
        android:name="org.apache.http.legacy"
        android:required="false" />
    
  13. Projeyi derleyin.

Uygulamayı test etme

  1. Android Studio kullanarak bir cihazda veya öykünücüde uygulamayı çalıştırın.

  2. Android uygulamasında bir kullanıcı adı ve parola girin. Her ikisi de aynı dize değerine sahip olmalı ve boşluk veya özel karakterler içermemelidir.

  3. Android uygulamasında Oturum aç'a tıklayın. Oturum açıldı ve kaydedildi ifadesinin yer alan bir bildirim iletisi bekleyin. Bildirim Gönder düğmesini etkinleştirir.

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

  4. Uygulamayı çalıştırdığınız ve bir kullanıcı kaydettiğiniz tüm platformları etkinleştirmek için iki durumlu düğmelere tıklayın.

  5. Bildirim iletisini alan kullanıcının adını girin. Bu kullanıcı, hedef cihazlarda bildirimlere kaydolmalıdır.

  6. Kullanıcının anında iletme bildirimi olarak alması için bir ileti girin.

  7. Bildirim Gönder’e tıklayın. Eşleşen kullanıcı adı etiketini içeren bir kaydı olan her cihaz, anında iletme bildirimini alır.

Sonraki adımlar

Bu öğreticide, kayıtlarıyla ilişkili etiketleri olan belirli kullanıcılara anında iletme bildirimleri göndermeyi öğrendiniz. Konum tabanlı anında iletme bildirimleri göndermeyi öğrenmek için aşağıdaki öğreticiye ilerleyin: