Вопрос по ios, c# – Как написать провайдера push-уведомлений Apple на C #?

13

У Apple действительно была плохая документация о том, как провайдер подключается и взаимодействует со своим сервисом (на момент написания статьи - 2009). Я запутался в протоколе. Как это делается в C #?

На мой взгляд, документация Apple довольно ясна:developer.apple.com/iphone/library/documentation/… Linulin
Этот ответ был выбран давно. Также посмотрите на ответ от Шей -stackoverflow.com/a/36963561/19854   Если вы ищете способ написания этого кода вручную, посмотрите на первоначально выбранный ответ:stackoverflow.com/a/1077664/19854 Phobis

Ваш Ответ

5   ответов
1

PushSharp библиотека в GitHub.

Я использую его во всех своих проектах

2

APNSSharp Проект доступен на Github. Это сработало для меня абсолютно хорошо всего за пару минут!

0
  public ActionResult ios()
    {
        string message = string.Empty;

        var certi = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Certificates2.p12");
        var appleCert = System.IO.File.ReadAllBytes(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Certificates2.p12"));

        ApnsConfiguration apnsConfig = new ApnsConfiguration(ApnsConfiguration.ApnsServerEnvironment.Production, appleCert, "Password");

        var apnsBroker = new ApnsServiceBroker(apnsConfig);
        apnsBroker.OnNotificationFailed += (notification, aggregateEx) =>
        {
            aggregateEx.Handle(ex =>
            {
                if (ex is ApnsNotificationException)
                {
                    var notificationException = (ApnsNotificationException)ex;
                    var apnsNotification = notificationException.Notification;
                    var statusCode = notificationException.ErrorStatusCode;
                    var inner = notificationException.InnerException;
                    message = "IOS Push Notifications: Apple Notification Failed: ID=" + apnsNotification.Identifier + ", Code=" + statusCode + ", Inner Exception" + inner;
                }
                else
                {
                    message = "IOS Push Notifications: Apple Notification Failed for some unknown reason : " + ex.InnerException;
                }
                return true;
            });
        };

        apnsBroker.OnNotificationSucceeded += (notification) =>
        {
            message = "IOS Push Notifications: Apple Notification Sent!";
        };

        apnsBroker.Start();
        try
        {
            string deviceToken = "33c2f3a13c90dc62660281913377c22066c1567e23c2ee2c728e0f936ff3ee9b";

            apnsBroker.QueueNotification(new ApnsNotification
            {
                DeviceToken = deviceToken,
                Payload = JObject.Parse("{\"aps\":{\"alert\":\" Test Message\", \"badge\":1, \"sound\":\" default\",}}")
            });
        }
        catch (Exception ex)
        {
            Console.Write(ex);
        }
        apnsBroker.Stop();

        return View(message);
    }
Хотя этот код может ответить на вопрос, было бы лучше объяснить, как он решает проблему, не представляя других и зачем его использовать. Ответы только для кода бесполезны в долгосрочной перспективе.
6

что это уместно (немного), но я только что успешно создал один для Java, так что концептуально очень похож на C # (за исключением, возможно, вещи SSL, но это не должно быть слишком сложно изменить. Ниже приведен пример полезной нагрузки сообщения и настройка шифрования:

    int port = 2195;
    String hostname = "gateway.sandbox.push.apple.com";


    char []passwKey = "<keystorePassword>".toCharArray();
    KeyStore ts = KeyStore.getInstance("PKCS12");
    ts.load(new FileInputStream("/path/to/apn_keystore/cert.p12"), passwKey);

    KeyManagerFactory tmf = KeyManagerFactory.getInstance("SunX509");
    tmf.init(ts,passwKey);
    SSLContext sslContext = SSLContext.getInstance("TLS");
    sslContext.init(tmf.getKeyManagers(), null, null);
    SSLSocketFactory factory =sslContext.getSocketFactory();
    SSLSocket socket = (SSLSocket) factory.createSocket(hostname,port); // Create the ServerSocket
    String[] suites = socket.getSupportedCipherSuites();
    socket.setEnabledCipherSuites(suites);
    //start handshake

    socket.startHandshake();


    // Create streams to securely send and receive data to the server
    InputStream in = socket.getInputStream();
    OutputStream out = socket.getOutputStream();



    // Read from in and write to out...
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    baos.write(0); //The command
    System.out.println("First byte Current size: " + baos.size());

    baos.write(0); //The first byte of the deviceId length    
    baos.write(32); //The deviceId length

    System.out.println("Second byte Current size: " + baos.size());

    String deviceId = "<heaxdecimal representation of deviceId";
    baos.write(hexStringToByteArray(deviceId.toUpperCase()));
    System.out.println("Device ID: Current size: " + baos.size());


    String payload = "{\"aps\":{\"alert\":\"I like spoons also\",\"badge\":14}}";
    System.out.println("Sending payload: " + payload);
    baos.write(0); //First byte of payload length;
    baos.write(payload.length());
    baos.write(payload.getBytes());

    out.write(baos.toByteArray());
    out.flush();

    System.out.println("Closing socket..");
    // Close the socket
    in.close();
    out.close();

}

Еще раз, не C #, но, по крайней мере, ближе, чем бедный образец ObjC, который предоставляет Apple.

Я все еще пытаюсь заставить это работать. Я продублировал ваш код на C #, но, так как .NET использует другой тип объекта для подключения через SSL & quot; SSLStream & quot; он не имеет «рукопожатия»; метод. Кажется, я не могу понять, как добиться правильного рукопожатия. Phobis
Это не верно. Он не создает сокет сервера. Это создает клиентский сокет. ts и tmf иногда используются для обозначения «хранилища доверия» и «фабрика доверительных управляющих»; но здесь они ссылаются на материал ключа клиента ... действительно странно.
Хорошо, я думаю, что получил его на работу. Я опубликую код, как только смогу проверить его работоспособность. Одна проблема, хотя. Я подключаюсь и отправляю полезную нагрузку, а затем читаю ответ сервера (который - нет ответа), и я не получаю сообщения на свой телефон. Что-то мне не хватает (мое приложение уже зарегистрировало push-сервис) Я использую песочницу, это проблема? Phobis
Отображается ли ваше приложение под «уведомлениями»; на устройстве? Если нет, то вам, вероятно, нужно восстановить свои сертификаты и повторно развернуть свое приложение, которое я получил на некоторое время. Кроме того, убедитесь, что выabsolutely верно, побайтово, в том, что вы передаете (см. выше). Если вы ошиблись, это не сработает вообще. Кроме того - в этом документе MS на SSLStream, примерно на 1/2 - 3/4 пути вниз, речь идет о соединениях клиент-сервер.
Смотри сюда:msdn.microsoft.com/en-us/library/… (Примерно на три четверти страницы внизу приведен пример рукопожатия клиента C # SSL с использованием объекта SSLStream. Похоже, способ сделать это, по его мнению (обратный вызов)
23

int port = 2195;
String hostname = "gateway.sandbox.push.apple.com";

//load certificate
string certificatePath = @"cert.p12";
string certificatePassword = "";
X509Certificate2 clientCertificate = new X509Certificate2(certificatePath, certificatePassword);
X509Certificate2Collection certificatesCollection = new X509Certificate2Collection(clientCertificate);

TcpClient client = new TcpClient(hostname, port);
SslStream sslStream = new SslStream(
        client.GetStream(),
        false,
        new RemoteCertificateValidationCallback(ValidateServerCertificate),
        null
);

try
{
    sslStream.AuthenticateAsClient(hostname, certificatesCollection, SslProtocols.Tls, true);
}
catch (AuthenticationException ex)
{
    client.Close();
    return;
}

// Encode a test message into a byte array.
MemoryStream memoryStream = new MemoryStream();
BinaryWriter writer = new BinaryWriter(memoryStream);

writer.Write((byte)0);  //The command
writer.Write((byte)0);  //The first byte of the deviceId length (big-endian first byte)
writer.Write((byte)32); //The deviceId length (big-endian second byte)

String deviceId = "DEVICEIDGOESHERE";
writer.Write(ToByteArray(deviceId.ToUpper()));

String payload = "{\"aps\":{\"alert\":\"I like spoons also\",\"badge\":14}}";

writer.Write((byte)0); //First byte of payload length; (big-endian first byte)
writer.Write((byte)payload.Length); //payload length (big-endian second byte)

byte[] b1 = System.Text.Encoding.UTF8.GetBytes(payload);
writer.Write(b1);
writer.Flush();

byte[] array = memoryStream.ToArray();
sslStream.Write(array);
sslStream.Flush();

// Close the client connection.
client.Close();
больше информации:x-cake.ning.com/profiles/blogs/setting-up-a-push-notification
Другим вариантом является бесплатный push-сервис (для тех, кто не хочет писать код):http://www.pushwoosh.com/
Исходная ссылка на x-cake мертва ... вот архивная версия.web.archive.org/web/20130719213517/http://x-cake.ning.com/…
это c #, который является asp.net
Как получить ответ от APNS? сообщение отправлено или не выполнено?

Похожие вопросы