how to send rich push to APNS - ios

I can send a regular push just fine but cannot figure out to send a "rich" push. I've read Apples "Local and Push Notification Programming Guide" 5 times and it makes no mention of sending anything other than an alert, badge and sound. I cannot find any documentation for rich push in the developer center.
I must be looking for the wrong thing, maybe someone else has been down this road already?

You won't send a whole HTML content directly in your notification, but you can send "rich push" in the sense that you can send additional data in your Push Notifications, and not just alert, badge and sound: you can send any other key you want/need. (just put them outside of the aps entry of your JSON, like at the root of the JSON object).
Only limitation is that you are limited to 255 characters, so that's not designed to provide sthg like a large HTML file for example. Just to provide some additional keys of your choice, like for example an URL, some fields to describe internal ids of objects you want to display, etc.
Everything is described here in the Local and Push Notifications Programming Guide: look at the paragraph called "Examples of JSON Payloads", where they add dummy parameters like "acme1" and "acme2".
So applied to your case your could have a payload like that for your Push notification:
{
"aps" : { "alert" : "Message received from Bob" },
"rich-text-url" : "http://yourserver/message/1234"
"id-of-object-to-show" : 456
}
The only thing to keep in mind is the 255 characters limit.
(Note: obviously the descriptive keys in my example above are only for explanation but one generally choose shorter key names like url and id instead to shorten the overall payload)

Related

How can I queue multiple accessibility notifications for VoiceOver?

This is how I'm notifying the system to read out my elements:
UIAccessibilityPostNotification(UIAccessibilityAnnouncementNotification, cell)
The problem is that when I send multiple notifications, the one that is already reading gets interrupted! I want to be able to queue it...
I also found in another question here that I should use attributed string:
attributedString.addAttribute(NSAttributedStringKey(
rawValue: UIAccessibilitySpeechAttributeQueueAnnouncement),
value: true,
range: range!.nsRange)
What am I missing here?
What am I missing here?
I have made many tests to try and understand this behaviour that drove me crazy.
My conclusion is that if you send a notification while VoiceOver is speaking a {label / hint / value}, your notification won't be taken into account : there may be a kind of preemption when the system needs to vocalize an attribute of a focused element.
That's only at the end of the vocalization that you can post as many notifications as you want to be well analyzed and interpreted as you wish.
The UIAccessibilitySpeechAttributeQueueAnnouncement key is only useful with your own notifications when the system doesn't need to take over.
If you send many notifications and that the user flicks to focus a new element for instance, the notifications that weren't vocalized will be removed as soon as the system vocalizes the element's attributes.
In that case, if you catch the UIAccessibilityAnnouncementDidFinish event, you will have a false value with the UIAccessibilityAnnouncementKeyWasSuccessful key for the last vocalized notification (UIAccessibilityAnnouncementKeyStringValue)... all the following ones will be ignored with no info given by the observer.
Conclusion : no personal notification is taken into account by VoiceOver when a new focused element or screen/layout changed notification occurs.
How can I queue multiple accessibility notifications for VoiceOver?
According to what's exposed above, I suggest to set up a kind of retry mechanism that would still send your notifications (x times) while they're not perfectly received after y seconds for instance.
That could be a tricky way to be more certain that the notifications are flawlessly received.
With Swift 5 this is working for me:
if (UIAccessibility.isVoiceOverRunning) {
let message: NSAttributedString = NSAttributedString(string: "read me", attributes: [.accessibilitySpeechQueueAnnouncement: true])
UIAccessibility.post(notification: .announcement, argument: message)
}
The key is to set .accessibilitySpeechQueueAnnouncement true.
UIAccessibilityAnnouncementNotification is supposed to be used when the app needs to make an ad-hoc announcement to the user. It's probably not designed to be called repeatedly.
If you did want to queue, you might need to post the first notification, then wait for UIAccessibilityAnnouncementDidFinishNotification to be posted by the system, then you could post the next message in your queue.
(But I'd offer caution: is this really what a visually-impaired user will be expecting?)
You could try using https://github.com/spanage/AccessibilityAnnouncer for your own notifications but keep in mind that if the user taps and interacts with the screen these notifications will be ignored.

Good way to design mqtt topic?

I am very new with mqtt design.
As I see from some tutorials in the internet, common mqtt topic has this format: /home/room/device_type/device_id
I could not see the benefit to do that. And have no idea how to use this kind of design.
From my point of view, the device (dev) might subscribe (sub) to control topic and publish (pub) to status topic. Like this:
pub: clients/dev/devid/stat
sub: clients/dev/devid/ctrl
In this way, it seems sub,pub logic is very simple for both clients and devices
Could someone please tell me some good way to design mqtt topic ?
(!) Please do not start topic with '/' (This one has been recommended by HiveMQ Team)
EDIT:
I just figured out that for whatever kind of design, the model must serve-able at least:
Individual control: send control command to a particular device.
Group control: send control command to a group of devices: type, defined group
Able to recieve the status of device.
Thank you very much
I found that the following topic split scheme works very well in multiple applications
protocol_prefix / src_id / dest_id / message_id / extra_properties
protocol_prefix is used to differentiate between different protocols / application that can be used at the same time
src_id is the ID of the mqtt client that publishes the message. It is expected to be the same as "client ID" used to connect to MQTT broker. It allows quick ACL control to check whether the client is allowed to publish specific topic.
dest_id is client ID of the "destination" unit, i.e. to whom the message is intended. Also allows quick ACL control on the broker of whether client is allowed to subscribe to a particular topic. There can be reserved "destination" strings to specify that the message is broadcasted to anyone who is interested. For example all.
message_id is actual ID of the message within used protocol. I usually use numeric value (as string of course), because the IOT or other embedded system that is connected to MQTT broker can have other I/O links and I would like to use the same protocol (but with different transport framing) to control the device using these other I/O links. I usually use numeric message IDs in such communication links.
extra_properties is an optional subtopic which can be used to communicate other MQTT specific extra information (comma separated key=value pairs for example). Good example would be reporting timestamp of the message when it was actually sent by the client. In case of "retained" messages it can help to identify the relevance of the received message. With MQTTv5 protocol that is expected to arrive soon, the need for this subtopic may disappear because there will be other way to communicate extra properties.
Hope it helps.
We have done some work on that for the domain of manufacturing (Industrial-IoT, not IoT!).
In our scenario there are lots of serverside apps of different companies communicating through MQTT. Thus we needed some overall structure. We call this "Manufacturing Message Stack".
The bottom layer is MQTT, then there is the "Messaging Layer". It consists mainly of
basic topic specs
basic payload specs
On top of the messaging layer there are domain message layers covering various domain specific topics as system messages, alerting, physical device / digital twin messages or other manufacturing related messages.
Topics
The topics are roughly defined as <senderapp>/<app-id>/<message-name>/<args> e.g. pacman/pacman-1/gameover (this is a sample for illustration only!)
The developer of an app which publishes MQTT messages defines <message-name> and <args> depending on the semantics of the payload.
The <senderapp> and <app-id> refers to the sending App and allows to quickly select messages from a defines origin (publisher). We deploy Apps in a microservice environment built with Docker, Rancher - and soon - Kubernetes.
Payload
The payload is specified in JSON format. There is a JSON schema reference URL in each
build an URL to an API of the publishing app which holds further information (e.g. JSON schema) of the message sent. Thus a subscriber can get meta data of a MQTT message on demand. Static meta data is not sent with a message to reduce the payload size.
Payload sample:
{
"$schema": "http://app/api/messages/message1.json",
"score": 1234,
"highscore": false
}
Publisher's message meta data
The publishing app holds an index of all messages which can be sent in an API at
http://<app>/api/messages/index.json:
{
"message1": "message1.json",
...
}
Each message is described by its JSON schema message1.json:
{
"$schema": "http://json-schema.org/draft-06/schema#",
"title": "Pacman end of game",
"properties": {
"score": {
"description": "Players score at the end of game",
"type": "integer"
},
...
}
}
Unfortunately we did not publish our manufacturing message stack yet. Publishing is planned in the next months. Feedback is welcome.
I think if topics are to reflect the physical world, we should look at something like Signal K.
EDIT:
That spec is also still maturing, but it includes concepts like "self" for the server/broker, and a tree that can start at the current vessel/home, but easily extends upwards to other vessels/aircraft/things.
My two cents:
All topics are read-only unless they end in "/set"
Ideally, topics are reasonably normalized and granular. I can understand grouping values up into a group topic. IMHO, this kind of decision should be application-specific.
Payloads should be strings, to avoid endian-ness issues
Here's one suggested tree:
broker = information of this specific broker
broker/clients
broker/clients/count
broker/clients/0/name or broker/clients[0]/name
broker/topics
home = this current location (could also be "here" or something)
home/kitchen/temperature "19C"
home/kitchen/temperature/hardware/type "ESP8266"
home/garage/maindoor/set "closed"
locations = list of all known locations
locations/0/uuid
locations/0/name
locations/0/address

How is should look like push notifications request to wallet/passbook?

I saw loot of questions about how to send push notifications to passbook, but I didn't find correct answer how should look like request. I have created passbook/wallet coupon, I have received POST request from apple with "pushToken" in payload and device id in URL. My coupon pass.json include next field:
{
"key" : "TestDiscount",
"label" : "Discount",
"value" : "1%",
"changeMessage": "Discount updated to %#."
}
Now I try to update Discount value in coupon, but I don't now how :( After lot of test I did it, but I didn't so when it happend, so now I know that is possible because I did it, but don't how how I did it :) Could you explain me how is should look like push request? Do I need to use device id any where ? So the correct payload is : {"pushToken":"token which I received from apple","TestDiscount":"newValue"} ? And where/when I have to use authenticationToken from my coupon pass.json. I'm really stuck
You need to send an empty payload in the push request.
When the device receives it, it will call your web service, first to get the list of serials for that device that need updating, and then to download a full pkpass bundle containing new data.
If the value for your TestDiscount key is different to the value in the old pass, then the change message will show.

How do apps display stored notifications as localised strings?

I'm trying to localise my app, and have noticed that apps like Twitter and Facebook immediately switch the language used in previous notifications stored on the server to match the devices language. How are they doing that?
For example is someone comments on a post so that the notifications is:
John commented "hi" on your post.
It's later translated into French if my device language is set to French.
Would they store a localised string such as:
%# commented %# on your post.
And then somehow reference that string in the notification along with the variables?
There are many localisation related tools out there, one is like Phraseapp. The way these tools work are fairly simply, and the localisation is mostly front end driven, not backend.
You define a key for some content, and the key could accept parameters as well. So in your example, it could look the following.
English: user_commented_message = %# commented %# on your post.
German: user_commented_message = %# Kommentierte %# auf Ihrem Beitrag.
Than you save this into your Localizable.strings, what is being shipped with your app binary.
Once the localisation is done, all you need to do is to create the right payload for your notification. In your example, it would be looking something like the following:
{
aps = {
alert = {
"loc-args" = (
"John",
"hi"
);
"loc-key" = "user_commented_message";
};
badge = 1;
sound = default;
};
}
As you can see, you pass 2 arguments in the loc-args sections, where you pretty much define, what should be display instead of %# in your key. The order of the arguments is important, they will replace the %# in the same order, as they are in loc-args sections.
In the loc-key section, you just pretty much define what key should be used from your Localizable.strings. From this on, the Notification Center will just display the notification based on the device language settings reading the content the localisation dictionary, the Twitter or Facebook server has nothing to do with it.
For further reading, i would recommend to take a look at the Apple notification programming guide.
EDIT
This post says you are not able to use body and loc-args at the same time. It is an exclusive EITHER ONE or the OTHER relationship.
If it is in your app, than simply just use localisation. Do not send hard coded language content or store hard coded language text on the server, always use every text content with the localisation keys. It is still front end driven, the server should only keep the localised keys, not the content itself.

Parse and Swift: How use advance targeting push to specific devices without users?

I currently creating an app where the users can add a posting without logging into the app or using any credentials.
Other users of the app can open the app and directly comment on the posts(the comments are an array of the post object).
I read the parse docs and I believe that this will use advance targeting. I saw PFInstallation.currentInstallation() for advanced targeting but I believe that is based on the users class and I am not using the Parse.com users class
What I would like to do is to send a push notification to the original poster when a comment is added to their post... So, I was wondering how I would go completing that?
Thanks!
It couldn't be easier,
Installation has a "user" column. Just make a query that matches the "user" of interest. So, your code will look something like this....
if ( .. comment made, need to send a push .. )
{
console.log(">>> 'comment' was added....");
var query = new Parse.Query(Parse.Installation);
query.equalTo('user', .. whoWroteThePost .. );
alert = "Wow! You have a new comment on a post you wrote!!!";
Parse.Push.send(
{
where:query,
data:{ alert: alert, badge: "Increment" }
});
return;
}
Note that you said ...
"What I would like to do is to send a push notification to the original poster when a comment is added to their post... "
In that sentence you speak of the "original poster". So, that's going to be a variable like originalPoster. So this line of code
query.equalTo('user', .. whoWroteThePost .. );
will be
query.equalTo('user', originalPoster );
Note that this is extremely common, and you can find endless examples on the web! Here's just one: example
Note that:
Parse's term "advanced targeting" is very confusing.
To phrase the same thought another way,
Parse's 'channels' are just silly, ignore them.
That is to say, simply ignore the "channels" nonsense, and just search on users. It's easier and less confusing than the channels business, which is just an extra field you have to fill-out al the time.
It's just one of those weird things about Parse.
I've never used the "non-advanced targeting" - it's stupid and pointless. And the "advanced" targeting is trivial to use: assuming you can write cloud code at all you can do "advanced" targeting. If you can write a query in cloud code, you can do "advanced" targeting.
Essentially,
query.equalTo('user', .. whoWroteThePost .. );
Note that, of course, you may have to first look up who wrote the post, and then from there you can make the query for the Push.
Note, in this process it makes:
no difference at all if the user is anonymous.
You can and should go ahead and send pushes, in the same way.
Advanced targeting is not done against users. It's just that is the easiest way to show an example.
You need to store the installation against the objects you want to push to. So in this case store the installation against the post. Then when the comment comes in you can send a notification to the installation connected to the post it relates to.
I think you are looking something called anonymous users. There is almost impossible to send notification without user's data. But, Parse.com provides something called anonymous users so that app users are not necessary to sign up in order to fully function something user related operations.
Then, you will need to store some information in order to find the target.
Parse.com Anonymous Users

Resources