언어: HTML | XAML

빠른 시작: 푸시 알림 보내기(XAML)

Applies to Windows and Windows Phone

참고  C#/VB/C++를 사용하지 않는 경우 빠른 시작: 푸시 알림 보내기(HTML)를 참조하세요.

클라우드 서버는 WNS(Windows 푸시 알림 서비스)를 통해 앱에 푸시 알림을 보낼 수 있습니다. 이 절차는 타일, 알림, 배지 및 푸시 알림에 적용됩니다.

목표: 타일, 알림, 배지 또는 푸시 알림을 만들어 보냅니다.

사전 요구 사항

이 항목의 내용을 이해하거나 이 항목에서 제공하는 코드를 사용하려면 다음 사항이 필요합니다.

지침

1. 필요한 네임스페이스 참조 포함

이 항목에 제공된 예제는 있는 그대로 사용할 수 있지만 코드에 다음과 같은 네임스페이스 참조를 포함해야 합니다.



using System.Net;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Json;
using System.Web;
using System.Text;

2. HTTP POST 요청을 만듭니다.

uri 매개 변수는 앱에서 요청되고 클라우드 서버로 전달된 채널 URI(Uniform Resource Identifier)입니다. 자세한 내용은 알림 채널을 요청, 생성 및 저장하는 방법을 참조하세요.



HttpWebRequest request = HttpWebRequest.Create(uri) as HttpWebRequest;
request.Method = "POST";

3. 필수 헤더를 추가합니다.

모든 푸시 알림에 포함해야 하는 필수 헤더로는 X-WNS-Type, Content-Type, Content-Length 및 Authorization 등 4가지가 있습니다.

  • X-WNS-Type 헤더는 이 헤더가 타일, 알림 메시지, 배지 또는 원시 알림인지 여부를 지정합니다.
  • Content-Type은 X-WNS-Type의 값에 따라 다르게 설정됩니다.
  • Content-Length는 포함된 알림 페이로드의 크기를 지정합니다.
  • Authorization 헤더는 이 채널을 통해 이 사용자에게 푸시 알림을 보낼 수 있도록 하는 인증 자격 증명을 지정합니다.

Authorization 헤더의 accessToken 매개 변수는 클라우드 서버가 인증을 요청할 때 WNS로부터 받아서 서버에 저장되어 있는 액세스 토큰을 지정합니다. 액세스 토큰이 없으면 알림이 거부됩니다.

가능한 헤더의 전체 목록은 푸시 알림 서비스 요청 및 응답 헤더를 참조하세요.



request.Headers.Add("X-WNS-Type", notificationType);
request.ContentType = contentType;
request.Headers.Add("Authorization", String.Format("Bearer {0}", accessToken.AccessToken));

4. 준비된 콘텐츠를 추가합니다.

HTTP 요청의 경우, 알림의 XML 콘텐츠가 요청 본문의 데이터 Blob입니다. 예를 들어 XML이 X-WNS-Type 사양과 일치하는지는 확인하지 않습니다. 콘텐츠는 XML 페이로드로 지정되며, 여기서 바이트 스트림으로 요청에 추가됩니다.



byte[] contentInBytes = Encoding.UTF8.GetBytes(xml);
                        
using (Stream requestStream = request.GetRequestStream())
    requestStream.Write(contentInBytes, 0, contentInBytes.Length);

5. 알림 수신을 승인하는 WNS의 응답 수신 대기

참고  알림 전송 확인이 아니라 WNS가 알림을 받았다는 승인만 수신됩니다.



using (HttpWebResponse webResponse = (HttpWebResponse)request.GetResponse())
    return webResponse.StatusCode.ToString();

6. WNS 응답 코드 처리

앱 서비스가 알림을 보낼 때 수신할 수 있는 여러 가지 응답 코드가 있습니다. 이러한 응답 코드 중 일부는 다른 코드보다 더 일반적이고 catch 블록에서 쉽게 처리할 수 있습니다.



catch (WebException webException)
{
    HttpStatusCode status = ((HttpWebResponse)webException.Response).StatusCode;

HttpStatusCode.Unauthorized: 제공한 액세스 토큰이 만료되었습니다. 새 토큰을 얻은 후 알림을 다시 보내 보세요. 캐시된 액세스 토큰은 24시간 후 만료되므로 하루에 한 번 이상 WNS에서 이 응답을 받을 수 있습니다. 최대 재시도 정책을 구현하는 것이 좋습니다.



    if (status == HttpStatusCode.Unauthorized)
    {
        GetAccessToken(secret, sid);
        return PostToWns(uri, xml, secret, sid, notificationType, contentType);
    }

HttpStatusCode.Gone / HttpStatusCode.NotFound: 채널 URI가 더 이상 유효하지 않습니다. 알림을 추가로 보내지 않게 하려면 데이터베이스에서 이 채널을 제거하세요. 이 사용자가 다음에 앱을 시작할 때 새 WNS 채널을 요청합니다. 앱이 채널 변경을 감지해야 새 채널 URI를 앱 서버에 보내도록 앱이 트리거됩니다. 자세한 내용은 알림 채널을 요청, 생성 및 저장하는 방법을 참조하세요.



    else if (status == HttpStatusCode.Gone || status == HttpStatusCode.NotFound)
    {
        return "";
    }

HttpStatusCode.NotAcceptable: 이 채널이 WNS에 의해 제한되고 있습니다. 다시 제한되지 않도록 보내는 알림 수를 크게 줄이는 재시도 전략을 구현하세요. 또한 알림을 제한하게 되는 시나리오를 다시 생각하세요. True 값을 추가하는 알림으로 보내는 알림을 제한하면 더욱 편리한 사용자 환경을 제공할 수 있습니다.



    else if (status == HttpStatusCode.NotAcceptable)
    {
        return "";
    }

기타 응답 코드: WNS가 덜 일반적인 응답 코드로 응답했습니다. 디버깅에 도움이 되도록 이 코드를 기록해 두세요. WNS 응답 코드의 전체 목록은 푸시 알림 서비스 요청 및 응답 헤더를 참조하세요.



    else
    {
        string[] debugOutput = {
                                   status.ToString(),
                                   webException.Response.Headers["X-WNS-Debug-Trace"],
                                   webException.Response.Headers["X-WNS-Error-Description"],
                                   webException.Response.Headers["X-WNS-Msg-ID"],
                                   webException.Response.Headers["X-WNS-Status"]
                               };
        return string.Join(" | ", debugOutput);            
    }

7. 코드를 단일 함수로 캡슐화

다음 예제는 위 단계에서 제공된 코드를 단일 함수로 패키지합니다. 이 함수는 WNS로 보낼 알림이 포함된 HTTP POST 요청을 구성합니다. type 매개 변수의 값을 변경하고 추가 헤더를 조정하면 이 코드를 알림, 타일, 배지 또는 푸시 알림에 사용할 수 있습니다. 이 함수를 클라우드 서버 코드의 일부로 사용할 수 있습니다.

이 함수의 오류 처리에는 액세스 토큰이 만료된 경우도 포함됩니다. 이 경우 이 함수는 WNS를 사용하여 다시 인증하는 다른 클라우드 서버 함수를 호출하여 새 액세스 토큰을 받습니다. 그런 다음 원래 함수를 새로 호출합니다.



// Post to WNS
public string PostToWns(string secret, string sid, string uri, string xml, string notificationType, string contentType)
{
    try
    {
        // You should cache this access token.
        var accessToken = GetAccessToken(secret, sid);

        byte[] contentInBytes = Encoding.UTF8.GetBytes(xml);

        HttpWebRequest request = HttpWebRequest.Create(uri) as HttpWebRequest;
        request.Method = "POST";
        request.Headers.Add("X-WNS-Type", notificationType);
        request.ContentType = contentType;
        request.Headers.Add("Authorization", String.Format("Bearer {0}", accessToken.AccessToken));

        using (Stream requestStream = request.GetRequestStream())
            requestStream.Write(contentInBytes, 0, contentInBytes.Length);

        using (HttpWebResponse webResponse = (HttpWebResponse)request.GetResponse())
            return webResponse.StatusCode.ToString();
    }
    
    catch (WebException webException)
    {
        HttpStatusCode status = ((HttpWebResponse)webException.Response).StatusCode;

        if (status == HttpStatusCode.Unauthorized)
        {
            // The access token you presented has expired. Get a new one and then try sending
            // your notification again.
              
            // Because your cached access token expires after 24 hours, you can expect to get 
            // this response from WNS at least once a day.

            GetAccessToken(secret, sid);

            // We recommend that you implement a maximum retry policy.
            return PostToWns(uri, xml, secret, sid, notificationType, contentType);
        }
        else if (status == HttpStatusCode.Gone || status == HttpStatusCode.NotFound)
        {
            // The channel URI is no longer valid.

            // Remove this channel from your database to prevent further attempts
            // to send notifications to it.

            // The next time that this user launches your app, request a new WNS channel.
            // Your app should detect that its channel has changed, which should trigger
            // the app to send the new channel URI to your app server.

            return "";
        }
        else if (status == HttpStatusCode.NotAcceptable)
        {
            // This channel is being throttled by WNS.

            // Implement a retry strategy that exponentially reduces the amount of
            // notifications being sent in order to prevent being throttled again.

            // Also, consider the scenarios that are causing your notifications to be throttled. 
            // You will provide a richer user experience by limiting the notifications you send 
            // to those that add true value.

            return "";
        }
        else
        {
            // WNS responded with a less common error. Log this error to assist in debugging.

            // You can see a full list of WNS response codes here:
            // http://msdn.microsoft.com/en-us/library/windows/apps/hh868245.aspx#wnsresponsecodes

            string[] debugOutput = {
                                       status.ToString(),
                                       webException.Response.Headers["X-WNS-Debug-Trace"],
                                       webException.Response.Headers["X-WNS-Error-Description"],
                                       webException.Response.Headers["X-WNS-Msg-ID"],
                                       webException.Response.Headers["X-WNS-Status"]
                                   };
            return string.Join(" | ", debugOutput);            
        }
    }

    catch (Exception ex)
    {
        return "EXCEPTION: " + ex.Message;
    }
}

// Authorization
[DataContract]
public class OAuthToken
{
    [DataMember(Name = "access_token")]
    public string AccessToken { get; set; }
    [DataMember(Name = "token_type")]
    public string TokenType { get; set; }
}

private OAuthToken GetOAuthTokenFromJson(string jsonString)
{
    using (var ms = new MemoryStream(Encoding.Unicode.GetBytes(jsonString)))
    {
        var ser = new DataContractJsonSerializer(typeof(OAuthToken));
        var oAuthToken = (OAuthToken)ser.ReadObject(ms);
        return oAuthToken;
    }
}

protected OAuthToken GetAccessToken(string secret, string sid)
{
    var urlEncodedSecret = HttpUtility.UrlEncode(secret);
    var urlEncodedSid = HttpUtility.UrlEncode(sid);

    var body = String.Format("grant_type=client_credentials&client_id={0}&client_secret={1}&scope=notify.windows.com", 
                             urlEncodedSid, 
                             urlEncodedSecret);

    string response;
    using (var client = new WebClient())
    {
        client.Headers.Add("Content-Type", "application/x-www-form-urlencoded");
        response = client.UploadString("https://login.live.com/accesstoken.srf", body);
    }
    return GetOAuthTokenFromJson(response);
}

아래에는 푸시 알림 메시지용 HTTP POST 요청 콘텐츠의 예제 콘텐츠가 나와 있습니다.



POST https://db3.notify.windows.com/?token=AgUAAADCQmTg7OMlCg%2fK0K8rBPcBqHuy%2b1rTSNPMuIzF6BtvpRdT7DM4j%2fs%2bNNm8z5l1QKZMtyjByKW5uXqb9V7hIAeA3i8FoKR%2f49ZnGgyUkAhzix%2fuSuasL3jalk7562F4Bpw%3d HTTP/1.1
Authorization: Bearer EgAaAQMAAAAEgAAACoAAPzCGedIbQb9vRfPF2Lxy3K//QZB79mLTgK
X-WNS-RequestForStatus: true
X-WNS-Type: wns/toast
Content-Type: text/xml
Host: db3.notify.windows.com
Content-Length: 196

<toast launch="">
  <visual lang="en-US">
    <binding template="ToastImageAndText01">
      <image id="1" src="World" />
      <text id="1">Hello</text>
    </binding>
  </visual>
</toast>

아래에는 HTTP POST 요청에 대한 응답으로 WNS에서 클라우드 서버로 보내는 예제 HTTP 응답이 나와 있습니다.



HTTP/1.1 200 OK
Content-Length: 0
X-WNS-DEVICECONNECTIONSTATUS: connected
X-WNS-STATUS: received
X-WNS-MSG-ID: 3CE38FF109E03A74
X-WNS-DEBUG-TRACE: DB3WNS4011534

요약

이 빠른 시작에서는 WNS로 보낼 HTTP POST 요청을 구성했습니다. WNS가 이 알림을 앱에 전달합니다. 지금까지 앱을 등록하고, 클라우드 서버를 WNS에 인증하고, XML 콘텐츠를 만들어 알림을 정의하고, 서버에서 해당 알림을 앱으로 보냈습니다.

관련 항목

알림 채널을 요청, 생성 및 저장하는 방법
푸시 알림 서비스 요청 및 응답 헤더
모바일 서비스 시작
푸시 알림 및 정기 알림 샘플

 

 

표시:
© 2014 Microsoft