~ubuntu-branches/ubuntu/wily/ubuntu-push/wily-proposed

« back to all changes in this revision

Viewing changes to docs/highlevel.txt

  • Committer: Package Import Robot
  • Author(s): Ubuntu daily release, Roberto Alsina, John R. Lenton
  • Date: 2014-09-08 18:05:11 UTC
  • mfrom: (1.1.18)
  • Revision ID: package-import@ubuntu.com-20140908180511-pwkbwac9q2s5sk18
Tags: 0.64+14.10.20140908-0ubuntu1
[ Roberto Alsina ]
* Remove tokens from debug output
* Doc updates
* Included example code in docs directory

[ John R. Lenton]
* Use libaccounts to track changes to the u1 account used for auth; restart the session on change.
* Set the MEDIA_PROP env var to select the right media role for notification sounds

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
Ubuntu Push Client Developer Guide
2
 
==================================
 
1
Ubuntu Push Client High Level Developer Guide
 
2
============================================
3
3
 
4
4
:Version: 0.50+
5
5
 
 
6
.. contents::
 
7
 
6
8
Introduction
7
9
------------
8
10
 
11
13
 
12
14
---------
13
15
 
14
 
Let's describe the push system by way of an example.
15
 
 
16
 
Alice has written a chat application called Chatter. Using it, Bob can send messages to Carol and viceversa. Alice has a
17
 
web application for it, so the way it works now is that Bob connects to the service, posts a message, and when Carol
18
 
connects, she gets it. If Carol leaves the browser window open, it beeps when messages arrive.
19
 
 
20
 
Now Alice wants to create an Ubuntu Touch app for Chatter, so she implements the same architecture using a client that
21
 
does the same thing as the web browser. Sadly, since applications on Ubuntu Touch don't run continuously, messages are
22
 
only delivered when Carol opens the app, and the user experience suffers.
23
 
 
24
 
Using the Ubuntu Push Server, this problem is alleviated: the Chatter server will deliver the messages to the Ubuntu
25
 
Push Server, which in turn will send it in an efficient manner to the Ubuntu Push Client running in Bob and Carol's
26
 
devices. The user sees a notification (all without starting the app) and then can launch it if he's interested in
27
 
reading messages at that point.
28
 
 
29
 
Since the app is not started and messages are delivered oportunistically, this is both battery and bandwidth-efficient.
30
 
 
31
 
.. figure:: push.svg
32
 
 
33
 
The Ubuntu Push system provides:
34
 
 
35
 
* A push server which receives **push messages** from the app servers, queues them and delivers them efficiently
36
 
  to the devices.
37
 
* A push client which receives those messages, queues messages to the app and displays notifications to the user
38
 
 
39
 
The full lifecycle of a push message is:
40
 
 
41
 
* Created in a application-specific server
42
 
* Sent to the Ubuntu Push server, targeted at a user or user+device pair
43
 
* Delivered to one or more Ubuntu devices
44
 
* Passed through the application helper for processing
45
 
* Notification displayed to the user (via different mechanisms)
46
 
* Application Message queued for the app's use
47
 
 
48
 
If the user interacts with the notification, the application is launched and should check its queue for messages
49
 
it has to process.
50
 
 
51
 
For the app developer, there are several components needed:
52
 
 
53
 
* A server that sends the **push messages** to the Ubuntu Push server
54
 
* Support in the client app for registering with the Ubuntu Push client
55
 
* Support in the client app to react to **notifications** displayed to the user and process **application messages**
56
 
* A helper program with application-specific knowledge that transforms **push messages** as needed.
57
 
 
58
 
In the following sections, we'll see how to implement all the client side parts. For the application server, see the
59
 
`Ubuntu Push Server API section <#ubuntu-push-server-api>`__
 
16
.. include:: _description.txt
60
17
 
61
18
The PushClient Component
62
19
------------------------
68
25
    PushClient {
69
26
        id: pushClient
70
27
        Component.onCompleted: {
71
 
            newNotifications.connect(messageList.handle_notifications)
 
28
            notificationsChanged.connect(messageList.handle_notifications)
72
29
            error.connect(messageList.handle_error)
73
30
        }
74
31
        appId: "com.ubuntu.developer.push.hello_hello"
95
52
~~~~~~~~~~~~~~~~~~~~~~~
96
53
 
97
54
When a notification is received by the Push Client, it will be delivered to your application's push helper, and then
98
 
placed in your application's mailbox. At that point, the PushClient will emit the ``newNotifications(QStringList)`` signal
 
55
placed in your application's mailbox. At that point, the PushClient will emit the ``notificationsChanged(QStringList)`` signal
99
56
containing your messages. You should probably connect to that signal and handle those messages.
100
57
 
101
58
Because of the application's lifecycle, there is no guarantee that it will be running when the signal is emitted. For that
102
59
reason, apps should check for pending notifications whenever they are activated or started. To do that, use the
103
60
``getNotifications()`` slot. Triggering that slot will fetch notifications and trigger the
104
 
``newNotifications(QStringList)`` signal.
 
61
``notificationsChanged(QStringList)`` signal.
105
62
 
106
63
Error Handling
107
64
~~~~~~~~~~~~~~
111
68
Persistent Notification Management
112
69
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
113
70
 
114
 
Some notifications are persistent, meaning they don't disappear automatically. For those notifications, there is an API that
115
 
allows the app to manage them without having to know the underlying details of the platform.
 
71
Some notifications are persistent, meaning that, after they are presented, they don't disappear automatically.
 
72
This API allows the app to manage that type of notifications.
116
73
 
117
74
On each notification there's an optional ``tag`` field, used for this purpose.
118
75
 
125
82
 
126
83
The ``count`` property sets the counter in the application's icon to the given value.
127
84
 
128
 
 
129
 
Application Helpers
130
 
-------------------
131
 
 
132
 
The payload delivered to push-client will be passed onto a helper program that can modify it as needed before passing it onto
133
 
the postal service (see `Helper Output Format <#helper-output-format>`__).
134
 
 
135
 
The helper receives two arguments ``infile`` and ``outfile``. The message is delivered via ``infile`` and the transformed
136
 
version is placed in ``outfile``.
137
 
 
138
 
This is the simplest possible useful helper, which simply passes the message through unchanged::
139
 
 
140
 
        #!/usr/bin/python3
141
 
 
142
 
        import sys
143
 
        f1, f2 = sys.argv[1:3]
144
 
        open(f2, "w").write(open(f1).read())
145
 
 
146
 
Helpers need to be added to the click package manifest::
147
 
 
148
 
        {
149
 
                "name": "com.ubuntu.developer.ralsina.hello",
150
 
                "description": "description of hello",
151
 
                "framework": "ubuntu-sdk-14.10-qml-dev2",
152
 
                "architecture": "all",
153
 
                "title": "hello",
154
 
                "hooks": {
155
 
                        "hello": {
156
 
                                "apparmor": "hello.json",
157
 
                                "desktop": "hello.desktop"
158
 
                        },
159
 
                        "helloHelper": {
160
 
                                "apparmor": "helloHelper-apparmor.json",
161
 
                                "push-helper": "helloHelper.json"
162
 
                        }
163
 
                },
164
 
                "version": "0.2",
165
 
                "maintainer": "Roberto Alsina <roberto.alsina@canonical.com>"
166
 
        }
167
 
 
168
 
Here, we created a helloHelper entry in hooks that has an apparmor profile and an additional JSON file for the push-helper hook.
169
 
 
170
 
helloHelper-apparmor.json must contain **only** the push-notification-client policy group::
171
 
 
172
 
        {
173
 
                "policy_groups": [
174
 
                        "push-notification-client"
175
 
                ],
176
 
                "policy_version": 1.2
177
 
        }
178
 
 
179
 
And helloHelper.json must have at least a exec key with the path to the helper executable relative to the json, and optionally
180
 
an app_id key containing the short id of one of the apps in the package (in the format packagename_appname without a version).
181
 
If the app_id is not specified, the helper will be used for all apps in the package::
182
 
 
183
 
        {
184
 
                "exec": "helloHelper",
185
 
                "app_id": "com.ubuntu.developer.ralsina.hello_hello"
186
 
        }
187
 
 
188
 
.. note:: For deb packages, helpers should be installed into /usr/lib/ubuntu-push-client/legacy-helpers/ as part of the package.
189
 
 
190
 
Helper Output Format
191
 
--------------------
192
 
 
193
 
Helpers output has two parts, the postal message (in the "message" key) and a notification to be presented to the user (in the "notification" key).
194
 
 
195
 
Here's a simple example::
196
 
 
197
 
        {
198
 
                "message": "foobar",
199
 
                "notification": {
200
 
                        "tag": "foo",
201
 
                        "card": {
202
 
                                "summary": "yes",
203
 
                                "body": "hello",
204
 
                                "popup": true,
205
 
                                "persist": true,
206
 
                                "timestamp": 1407160197
207
 
                        }
208
 
                        "sound": "buzz.mp3",
209
 
                        "vibrate": {
210
 
                                "pattern": [200, 100],
211
 
                                "repeat": 2
212
 
                        }
213
 
                        "emblem-counter": {
214
 
                                "count": 12,
215
 
                                "visible": true
216
 
                        }
217
 
                }
218
 
        }
219
 
 
220
 
The notification can contain a **tag** field, which can later be used by the `persistent notification management API. <#persistent-notification-management>`__
221
 
 
222
 
:message: (optional) A JSON object that is passed as-is to the application via PopAll.
223
 
:notification: (optional) Describes the user-facing notifications triggered by this push message.
224
 
 
225
 
The notification can contain a **card**. A card describes a specific notification to be given to the user,
226
 
and has the following fields:
227
 
 
228
 
:summary: (required) a title. The card will not be presented if this is missing.
229
 
:body: longer text, defaults to empty.
230
 
:actions: If empty (the default), a bubble notification is non-clickable.
231
 
          If you add a URL, then bubble notifications are clickable and launch that URL. One use for this is using a URL like
232
 
          ``appid://com.ubuntu.developer.ralsina.hello/hello/current-user-version`` which will switch to the app or launch
233
 
          it if it's not running. See `URLDispatcher <https://wiki.ubuntu.com/URLDispatcher>`__ for more information.
234
 
 
235
 
:icon: An icon relating to the event being notified. Defaults to empty (no icon);
236
 
       a secondary icon relating to the application will be shown as well, regardless of this field.
237
 
:timestamp: Seconds since the unix epoch, only used for persist (for now). If zero or unset, defaults to current timestamp.
238
 
:persist: Whether to show in notification centre; defaults to false
239
 
:popup: Whether to show in a bubble. Users can disable this, and can easily miss them, so don't rely on it exclusively. Defaults to false.
240
 
 
241
 
.. note:: Keep in mind that the precise way in which each field is presented to the user depends on factors such as
242
 
          whether it's shown as a bubble or in the notification centre, or even the version of Ubuntu Touch the user
243
 
          has on their device.
244
 
 
245
 
The notification can contain a **sound** field. This is either a boolean (play a predetermined sound) or the path to a sound file. The user can disable it, so don't rely on it exclusively.
246
 
Defaults to empty (no sound). The path is relative, and will be looked up in (a) the application's .local/share/<pkgname>, and (b)
247
 
standard xdg dirs.
248
 
 
249
 
The notification can contain a **vibrate** field, causing haptic feedback, which can be either a boolean (if true, vibrate a predetermined way) or an object that has the following content:
250
 
 
251
 
:pattern: a list of integers describing a vibration pattern (duration of alternating vibration/no vibration times, in milliseconds).
252
 
:repeat: number of times the pattern has to be repeated (defaults to 1, 0 is the same as 1).
253
 
 
254
 
The notification can contain a **emblem-counter** field, with the following content:
255
 
 
256
 
:count: a number to be displayed over the application's icon in the launcher.
257
 
:visible: set to true to show the counter, or false to hide it.
258
 
 
259
 
.. note:: Unlike other notifications, emblem-counter needs to be cleaned by the app itself.
260
 
          Please see `the persistent notification management section. <#persistent-notification-management>`__
261
 
 
262
 
.. FIXME crosslink to hello example app on each method
263
 
 
264
 
Security
265
 
~~~~~~~~
266
 
 
267
 
To use the push API, applications need to request permission in their security profile, using something like this::
268
 
 
269
 
        {
270
 
                "policy_groups": [
271
 
                        "networking",
272
 
                        "push-notification-client"
273
 
                ],
274
 
                "policy_version": 1.2
275
 
        }
276
 
 
277
 
 
278
 
Ubuntu Push Server API
279
 
----------------------
280
 
 
281
 
The Ubuntu Push server is located at https://push.ubuntu.com and has a single endpoint: ``/notify``.
282
 
To notify a user, your application has to do a POST with ``Content-type: application/json``.
283
 
 
284
 
Here is an example of the POST body using all the fields::
285
 
 
286
 
        {
287
 
                "appid": "com.ubuntu.music_music",
288
 
                "expire_on": "2014-10-08T14:48:00.000Z",
289
 
                "token": "LeA4tRQG9hhEkuhngdouoA==",
290
 
                "clear_pending": true,
291
 
                "replace_tag": "tagname",
292
 
                "data": {
293
 
                        "message": "foobar",
294
 
                        "notification": {
295
 
                                "card": {
296
 
                                        "summary": "yes",
297
 
                                        "body": "hello",
298
 
                                        "popup": true,
299
 
                                        "persist": true,
300
 
                                        "timestamp": 1407160197
301
 
                                }
302
 
                                "sound": "buzz.mp3",
303
 
                                "tag": "foo",
304
 
                                "vibrate": {
305
 
                                        "pattern": [200, 100],
306
 
                                        "repeat": 2
307
 
                                }
308
 
                                "emblem-counter": {
309
 
                                        "count": 12,
310
 
                                        "visible": true
311
 
                                }
312
 
                        }
313
 
                }
314
 
        }
315
 
 
316
 
 
317
 
:appid: ID of the application that will receive the notification, as described in the client side documentation.
318
 
:expire_on: Expiration date/time for this message, in `ISO8601 Extendend format <http://en.wikipedia.org/wiki/ISO_8601>`__
319
 
:token: The token identifying the user+device to which the message is directed, as described in the client side documentation.
320
 
:clear_pending: Discards all previous pending notifications. Usually in response to getting a "too-many-pending" error.
321
 
:replace_tag: If there's a pending notification with the same tag, delete it before queuing this new one.
322
 
:data: A JSON object.
323
 
 
324
 
In this example, data is `what a helper would output <#helper-output-format>`__ but that's not necessarily the case.
325
 
The content of the data field will be passed to the helper application which **has** to produce output in that format.
 
85
.. include:: _common.txt
 
 
b'\\ No newline at end of file'