AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Cross-Platform-Entwicklung Delphi 11.1 IOS Remote Push Notifications
Thema durchsuchen
Ansicht
Themen-Optionen

Delphi 11.1 IOS Remote Push Notifications

Ein Thema von friedt99 · begonnen am 18. Sep 2022 · letzter Beitrag vom 18. Sep 2022
Antwort Antwort
friedt99

Registriert seit: 17. Mär 2010
46 Beiträge
 
#1

Delphi 11.1 IOS Remote Push Notifications

  Alt 18. Sep 2022, 10:16
Hallo Zusammen,

ich richte gerade Push Notifications an meine App ein. In FMX verwende ich dazu "Grijjy.RemotePush.Receiver".

Ich teste das auf dem Mac mit (die Variablen sind gesetzt):

curl -v --header "apns-topic: $TOPIC" --header "apns-push-type: alert" --header "authorization: bearer $AUTHENTICATION_TOKEN" --data '{"aps":{"alert":"test"}}' --http2 https://${APNS_HOST_NAME}/3/device/${DEVICE_TOKEN}

Dieser Push klappt, ich bekomme Status 200 und die Notification kommt bei der App an.

Jetzt versuche ich aber "stille" Notifications zu senden, um der App zu sagen, das neue Daten vorhanden sind.

https://developer.apple.com/document...es_to_your_app

Ich teste das auf dem Mac mit:

curl -v --header "apns-topic: $TOPIC" --header "apns-push-type: background" --header "authorization: bearer $AUTHENTICATION_TOKEN" --header "apns-priority: 5" --data '{"aps":{"content-available" : 1}}' --http2 https://${APNS_HOST_NAME}/3/device/${DEVICE_TOKEN}

Auch hier kommt Status 200 raus, aber diese Notification kommt nicht in der App an.

Ich vermute mal es liegt daran, das diese Notifications laut Apple an application(_:didReceiveRemoteNotification:fetchCo mpletionHandler
gesendet werden. Aber wie komme ich da dran / wie setze ich diesen Handler.


Grüße
Thomas

Geändert von friedt99 (18. Sep 2022 um 12:39 Uhr)
  Mit Zitat antworten Zitat
friedt99

Registriert seit: 17. Mär 2010
46 Beiträge
 
#2

AW: Delphi 11.1 IOS Remote Push Notifications

  Alt 18. Sep 2022, 12:31
So, habe es jetzt mit

TMessageManager.DefaultManager.SubscribeToMessage( TPushRemoteNotificationMessage,HandleRemoteNotific ationReceived);

versucht. Da kommt aber immer noch keine Notification an.
  Mit Zitat antworten Zitat
friedt99

Registriert seit: 17. Mär 2010
46 Beiträge
 
#3

AW: Delphi 11.1 IOS Remote Push Notifications

  Alt 18. Sep 2022, 14:52
Keine Ahnung warum, aber nun klappt es.

Habe es nochmal mit dem hier geposteten curl versucht, auch das klappt nun, auch ohne
TMessageManager.DefaultManager.SubscribeToMessage, es genügt die Unit "Grijjy.RemotePush.Receiver".

Grüße
Thomas
  Mit Zitat antworten Zitat
friedt99

Registriert seit: 17. Mär 2010
46 Beiträge
 
#4

AW: Delphi 11.1 IOS Remote Push Notifications

  Alt 18. Sep 2022, 16:03
Hier mal eine Anleitung wie man Push Notifications unter IOS mit APN zum Laufen bekommt da ich
ziemlich lange gebraucht habe.

Basis ist Delphi 11.1 und XCode 13.4.1 und eine App (mit allen Einstellungen in Apple Developer) die man zumindest auf
einem Entwicklungsgerät ausführen kann.

Remote Push Notifications sind Notifications die von "außen" an ein Device gesendet werden.

1.) In Apple Developer ist folgendes unter "Certificates, Identifiers & Profiles zu tun:

a.) unter Certificates ein Zertifkat für "Services" "Apple Push Notification service SSL (Sandbox & Production)" anlegen und auf den Mac herunterladen.
Datei öffnen damit das Zertifikat im Schlüsselbund eingetragen wird.

b.) Unter "Identifiers" den App Identifier bearbeiten (NICHT XC Wildcard) und dort den Haken bei "Push Notifications" setzen und mit "Edit" dann
das Zertifikat für beide Optionen zuordnen.

c.) Unter Profiles das Profile vom Typ "AppStore" bearbeiten, speichern, herunterladen und öffnen.
Wenn das Profil vom Typ "Development" auf den Identifier "XC Wildcard" eingestellt ist (damit man Demo Projekte einfach auf das Entwicklungsgerät bekommt), dann am
besten ein weiteres Profil z.B. "Development PUSH" anlegen. Push Notifications gehen nur bei einem Profil mit dem echten App Identifier (country.domain.appname).
Im (neuen) Profil dann also den echten App Identifier auswählen, dann sollte unter "Enabled Capabilities" der Eintrag "Push Notifications" sichtbar sein.
Das neue Profil herunterladen und öffnen damit es in XCode installiert wird.

d.) Unter Keys einen neuen Schlüssel anlegen und dort "Apple Push Notification Service (APNs) aktivieren. Zum Abschluß den Schlüssel
herunterladen (Dateiendung wird .p8) und gut aufbewahren, die Datei wird für das Senden der Push Notification z.B. via Curl oder PHP benötigt.

e.) Die "Key ID" des soeben angelegten Keys notieren.

f.) Unter "Membership" die Team ID heraussuchen und notieren (wird für das Senden benötigt)

g.) Die App ID heraussuchen und notieren.


2.) In Delphi ist folgendes zu tun:

a.) Im App Projekt unter "Versionsinformation" den Schlüssel "UIBackgroundModes" um "remote-notification" ergänzen.

b.) Im App Projekt unter "Bereitstellung - Provisioning" das Development Profile auswählen, welches in Apple Developer unter Enabled Capabilities" den
Eintrag "Push Notifications" hat, z.B. "Development PUSH".

c.) Folgende Unit herunterladen und im Suchpfad ablegen: https://github.com/grijjy/GrijjyFoun...h.Receiver.pas

3.) Im Source folgendes einbauen:

Delphi-Quellcode:
uses ...Grijjy.RemotePush.Receiver;
TForm1 = Class(TForm)
..
private
  FReceiver:TgoRemotePushReceiver;

  procedure HandlePushTokenChanged(const Sender: TObject; const M: TMessage);
  procedure HandlePushMessageReceived(const Sender: TObject; const M: TMessage);

  --
end;


TForm1.FormCreate(Sender: TObject);
begin
  ...
  FReceiver:=TgoRemotePushReceiver.Create('');
  
  TMessageManager.DefaultManager.SubscribeToMessage(TgoDeviceTokenChangeMessage, HandlePushTokenChanged);
  TMessageManager.DefaultManager.SubscribeToMessage(TgoRemoteNotificationMessage, HandlePushMessageReceived);
end;

TForm1.FormDestroy(Sender: TObject);
begin
  ...
  FReceiver.Free;
end;

procedure TForm1.HandlePushTokenChanged(const Sender: TObject; const M: TMessage);
begin
  if (M is TgoDeviceTokenChangeMessage) then
  begin
    // Token an den Sender (z.B. PHP Webservice) übermitteln
    // Token steht in: TgoDeviceTokenChangeMessage(M).DeviceToken
  end;
end;

procedure TForm1.HandlePushMessageReceived(const Sender: TObject; const M: TMessage);
begin
  if (M is TgoRemoteNotificationMessage) then
  begin
    // Die Nachricht verarbeiten.
    // TgoRemoteNotificationMessage(M).DataKey enthält den Provider (aps, fmc)
    // TgoRemoteNotificationMessage(M).Json enthält den JSON String der Notification
  end;
end;
Die App einmal starten / Debuggen und den Token auslesen und notieren.


4.) Um das zu testen, auf dem Mac im Terminalfenster folgendes ausführen (eigene ID's / Pfade ergänzen)
Siehe auch hier: https://developer.apple.com/document...and-line_tools
unter dem Abschnitt "Send a Push Notification Using a Token"

a.) diverse Variablen anlegen
Code:
TEAM_ID=<hier Team ID eintragen>
AUTH_KEY_ID=<Key ID des oben angelegten Key eintragen>
TOPIC=<App ID der App eintragen>
APNS_HOST_NAME=api.sandbox.push.apple.com
DEVICE_TOKEN=<den Device Token der bei HandlePushTokenChanged beim Programmstart erzeugt wird, hier eintragen>
TOKEN_KEY_FILE_NAME=<Pfad auf die Schlüsseldatei (.p8) angeben, z.B. /Users/<username>/Downloads/<Name der Datei>.p8
b.) Verbindungstest
Code:
openssl s_client -connect "${APNS_HOST_NAME}":443
c.) Authentication Token erzeugen (muß alle 20min erneuert werden)
Code:
 
JWT_ISSUE_TIME=$(date +%s)
JWT_HEADER=$(printf '{ "alg": "ES256", "kid": "%s" }' "${AUTH_KEY_ID}" | openssl base64 -e -A | tr -- '+/' '-_' | tr -d =)
JWT_CLAIMS=$(printf '{ "iss": "%s", "iat": %d }' "${TEAM_ID}" "${JWT_ISSUE_TIME}" | openssl base64 -e -A | tr -- '+/' '-_' | tr -d =)
JWT_HEADER_CLAIMS="${JWT_HEADER}.${JWT_CLAIMS}"
JWT_SIGNED_HEADER_CLAIMS=$(printf "${JWT_HEADER_CLAIMS}" | openssl dgst -binary -sha256 -sign "${TOKEN_KEY_FILE_NAME}" | openssl base64 -e -A | tr -- '+/' '-_' | tr -d =)
AUTHENTICATION_TOKEN="${JWT_HEADER}.${JWT_CLAIMS}.${JWT_SIGNED_HEADER_CLAIMS}"
d.) Test ausführen
Code:
curl -v --header "apns-topic: $TOPIC" --header "apns-push-type: alert" --header "authorization: bearer $AUTHENTICATION_TOKEN" --data '{"aps":{"alert":"test"}}' --http2 https://${APNS_HOST_NAME}/3/device/${DEVICE_TOKEN}
Es sollte dann ein http/2 Status von 200 angezeigt werden und die Notification in der App unter HandlePushMessageReceived aufschlagen.
Ansonsten Fehlermeldungen lesen und ggf. Angaben (Pfade / ID's) kontrollieren.


5.) Um per PHP eine Notification an ein Device zu senden, kann dieser Code verwendet werden

PHP-Quellcode:
<?php

//Retrieved from [url]https://stackoverflow.com/questions/70105632/can-this-php-script-still-be-used-to-send-test-push-notifications-using-apns-c[/url]
//Provide some variables

$Cert = '<Pfad auf die Schlüsseldatei (.p8) angeben, /Pfad/<Name der Datei>.p8>';
$DeviceToken = '<den Device Token der bei HandlePushTokenChanged beim Programmstart erzeugt wird, hier eintragen>';
$PushType = 'alert';
$Url = 'https://api.sandbox.push.apple.com:443';
$Topic = '<App ID der App eintragen>';
$KeyID = '<Key ID des oben angelegten Key eintragen>';
$TeamID = '<hier Team ID eintragen>';
                  
//generate token. Needs to be done at least every 20 minutes. Generated token could be kept in a file for 20 min to speed up.   
//https://developer.apple.com/documentation/usernotifications/setting_up_a_remote_notification_server/establishing_a_token-based_connection_to_apns

$assocToken = array();
$assocToken['alg'] = 'ES256'; //The encryption algorithm you used to encrypt the token. APNs supports only the ES256 algorithm, so set the value of this key to ES256.
$assocToken['kid'] = $KeyID; //The 10-character Key ID you obtained from your developer account
$assocToken['iss'] = $TeamID; //The issuer key, the value for which is the 10-character Team ID you use for developing your company’s apps. Obtain this value from your developer account.
$assocToken['iat'] = time(); //The “issued at” time, whose value indicates the time at which this JSON token was generated. Specify the value as the number of seconds since Epoch, in UTC. The value must be no more than one hour from the current time.

$header = '{'
           . ' "alg" : "'.$assocToken['alg'].'",'
      . ' "kid" : "'.$assocToken['kid'].'"'
      . '}';

$payload = '{'
      . ' "iss" : "'.$assocToken['iss'].'",'
      . ' "iat" : "'.$assocToken['iat'].'"'
      . '}';

$headerB64URL = base64url_encode($header);
$payloadB64URL = base64url_encode($payload);
$secret = file_get_contents($Cert);

$signature = '';
openssl_sign($headerB64URL.'.'.$payloadB64URL, $signature, $secret, \OPENSSL_ALGO_SHA256);
$ServerToken = $headerB64URL.'.'.$payloadB64URL.'.'.base64url_encode($signature);
                                                   
//token generated, send notification
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => $Url . '/3/device/'.$DeviceToken,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 1,
CURLOPT_TIMEOUT => 10,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_HTTPHEADER => array(
   "authorization: bearer " . $ServerToken,
        "apns-push-type: " . $PushType,
        "apns-topic: " . $Topic,
        ),
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_2_0,
CURLOPT_POST => '1',
CURLOPT_POSTFIELDS => '{"aps":{"alert":"test"}}'   
));
                
$response = curl_exec($curl);
                
if(curl_errno($curl) == 0){
    return True;   
}
else{
    return False;   
};

?>
6.) Um "Stille" Notification zu senden, sind folgende Änderungen notwendig:

Stille Notifications sind Notifications die der Anwender niemals sieht. Diese sind nur gedacht, die Anwendung mit neuen / geänderten
Daten zu versorgen bzw. diese zu Informieren, neue Daten abzurufen.

Test ausführen
Code:
curl -v --header "apns-topic: $TOPIC" --header "apns-push-type: background" --header "authorization: bearer $AUTHENTICATION_TOKEN" --data '{"aps":{"content-available":1}}' --http2 https://${APNS_HOST_NAME}/3/device/${DEVICE_TOKEN}
Notification per PHP senden
PHP-Quellcode:
$PushType = 'background';

curl_setopt_array($curl, array(
CURLOPT_URL => $Url . '/3/device/'.$DeviceToken,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 1,
CURLOPT_TIMEOUT => 10,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_HTTPHEADER => array(
   "authorization: bearer " . $ServerToken,
        "apns-push-type: " . $PushType,
        "apns-topic: " . $Topic,
        "apns-priority: 5"
        ),
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_2_0,
CURLOPT_POST => '1',
CURLOPT_POSTFIELDS => '{"aps":{"content-available":1}}'   
));
Hoffe das hilft mal jemand.

Grüße
Thomas

Geändert von friedt99 (18. Sep 2022 um 20:59 Uhr)
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 09:46 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz