-
Notifications
You must be signed in to change notification settings - Fork 90
/
Copy pathreact-to-changes.txt
315 lines (228 loc) · 11.3 KB
/
react-to-changes.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
.. meta::
:robots: noindex, nosnippet
.. _java-react-to-changes:
.. _java-client-notifications:
.. _java-live-queries:
.. _java-live-object:
===========================
React to Changes - Java SDK
===========================
.. contents:: On this page
:local:
:backlinks: none
:depth: 2
:class: singlecol
.. _java-subscribe-to-changes:
Objects in Realm clients are **live objects** that
update automatically to reflect data changes, including
:ref:`synced <sync>` remote changes, and emit
notification events that you
can subscribe to whenever their underlying data changes.
Any modern app should be able to react when data changes,
regardless of where that change originated. When a user adds
a new item to a list, you may want to update the UI, show a
notification, or log a message. When someone updates that
item, you may want to change its visual state or fire off a
network request. Finally, when someone deletes the item, you
probably want to remove it from the UI. Realm's notification
system allows you to watch for and react to changes in your
data, independent of the writes that caused the changes.
Realm emits three kinds of notifications:
- :ref:`Realm notifications <java-realm-notifications>` whenever a specific realm commits a write transaction.
- :ref:`Collection notifications <java-collection-notifications>` whenever any Realm object in a collection changes, including inserts, updates, and deletes.
- :ref:`Object notifications <java-object-notifications>` whenever a specific Realm object changes, including updates and deletes.
.. _java-auto-refresh:
Auto-Refresh
------------
Realm objects accessed on a thread associated with a
:android:`Looper <reference/android/os/Looper.html>` automatically
update periodically to reflect changes to underlying data.
The Android UI thread always contains a ``Looper`` instance. If you need
to keep Realm objects around for long periods of time on
any other thread, you should configure a ``Looper`` for that thread.
.. warning:: Always Close Realm Instances on Non-Looper Threads to Avoid Resource Leaks
Realms on a thread without a :android:`Looper <reference/android/os/Looper>`
do not automatically advance their version. This can increase the size of the
realm in memory and on disk. Avoid using realm instances on
non-Looper threads when possible. If you *do* open a realm on a non-Looper
thread, close the realm when you're done using it.
.. _java-register-a-realm-change-listener:
.. _java-realm-notifications:
Register a Realm Change Listener
--------------------------------
You can register a notification handler on an entire realm.
Realm calls the notification handler whenever any write
transaction involving that realm is committed. The
handler receives no information about the change.
This is useful when you want to know that there has been a
change but do not care to know specifically what changed.
For example, proof of concept apps often use this
notification type and simply refresh the entire UI when
anything changes. As the app becomes more sophisticated and
performance-sensitive, the app developers shift to more
granular notifications.
.. example::
Suppose you are writing a real-time collaborative app. To
give the sense that your app is buzzing with collaborative
activity, you want to have an indicator that lights up when
any change is made. In that case, a realm notification
handler would be a great way to drive the code that controls
the indicator. The following code shows how to observe a realm
for changes with with :java-sdk:`addChangeListener() <io/realm/RealmResults.html#addChangeListener-io.realm.OrderedRealmCollectionChangeListener->`:
.. tabs-realm-languages::
.. tab::
:tabid: java
.. literalinclude:: /examples/Notifications/RealmNotification.java
:language: java
:emphasize-lines: 16
:copyable: false
.. tab::
:tabid: kotlin
.. literalinclude:: /examples/Notifications/RealmNotification.kt
:language: kotlin
:emphasize-lines: 12
:copyable: false
.. important:: Automatic Refresh
All threads that contain a ``Looper`` automatically refresh
``RealmObject`` and ``RealmResult`` instances when new changes are
written to the realm. As a result, it isn't necessary to fetch
those objects again when reacting to a ``RealmChangeListener``, since
those objects are already updated and ready to be redrawn to the
screen.
.. _java-register-a-collection-change-listener:
.. _java-collection-notifications:
Register a Collection Change Listener
-------------------------------------
You can register a notification handler on a specific
collection within a realm. The handler receives a
description of changes since the last notification.
Specifically, this description consists of three lists of
indices:
- The indices of the objects that were deleted.
- The indices of the objects that were inserted.
- The indices of the objects that were modified.
Stop notification delivery by calling the ``removeChangeListener()`` or
``removeAllChangeListeners()`` methods. Notifications also stop if:
- the object on which the listener is registered gets garbage collected.
- the realm instance closes.
Keep a strong reference to the object you're listening to
for as long as you need the notifications.
.. important:: Order Matters
In collection notification handlers, always apply changes
in the following order: deletions, insertions, then
modifications. Handling insertions before deletions may
result in unexpected behavior.
Realm emits an initial notification after retrieving the
collection. After that, Realm delivers collection
notifications asynchronously whenever a write transaction
adds, changes, or removes objects in the collection.
Unlike realm notifications, collection notifications contain
detailed information about the change. This enables
sophisticated and selective reactions to changes. Collection
notifications provide all the information needed to manage a
list or other view that represents the collection in the UI.
The following code shows how to observe a collection for
changes with :java-sdk:`addChangeListener()
<io/realm/Realm.html#addChangeListener-io.realm.RealmChangeListener->`:
.. tabs-realm-languages::
.. tab::
:tabid: kotlin
.. literalinclude:: /examples/generated/java/sync/NotificationsTest.snippet.collection-notifications.kt
:language: kotlin
:copyable: false
.. tab::
:tabid: java
.. literalinclude:: /examples/generated/java/sync/NotificationsTest.snippet.collection-notifications.java
:language: java
:copyable: false
.. _java-register-an-object-change-listener:
.. _java-object-notifications:
Register an Object Change Listener
----------------------------------
You can register a notification handler on a specific object
within a realm. Realm notifies your handler:
- When the object is deleted.
- When any of the object's properties change.
The handler receives information about what fields changed
and whether the object was deleted.
Stop notification delivery by calling the ``removeChangeListener()`` or
``removeAllChangeListeners()`` methods. Notifications also stop if:
- the object on which the listener is registered gets garbage collected.
- the realm instance closes.
Keep a strong reference of the object you're listening to
for as long as you need the notifications.
The following code shows how create a new instance of a class
in a realm and observe that instance for changes with
:java-sdk:`addChangeListener() <io/realm/RealmObject.html#addChangeListener-E-io.realm.RealmObjectChangeListener->`:
.. tabs-realm-languages::
.. tab::
:tabid: kotlin
.. literalinclude:: /examples/generated/java/sync/NotificationsTest.snippet.object-notifications.kt
:language: kotlin
:copyable: false
.. tab::
:tabid: java
.. literalinclude:: /examples/generated/java/sync/NotificationsTest.snippet.object-notifications.java
:language: java
:copyable: false
.. _java-unregister-a-change-listener:
Unregister a Change Listener
----------------------------
You can unregister a change listener by passing your change listener to
:java-sdk:`Realm.removeChangeListener()
<io/realm/Realm.html#removeChangeListener-io.realm.RealmChangeListener->`.
You can unregister all change listeners currently subscribed to changes
in a realm or any of its linked objects or collections with
:java-sdk:`Realm.removeAllChangeListeners()
<io/realm/Realm.html#removeAllChangeListeners-->`.
.. _java-realm-notifications-system-apps-custom-roms:
Use Realm in System Apps on Custom ROMs
---------------------------------------
Realm uses named pipes in order to support notifications and
access to the realm file from multiple processes. While this is
allowed by default for normal user apps, it is disallowed for system
apps.
You can define a system apps by setting
``android:sharedUserId="android.uid.system"`` in the Android manifest.
When working with a system app, you may see a security violation in
Logcat that looks something like this:
.. code-block::
:copyable: false
05-24 14:08:08.984 6921 6921 W .realmsystemapp: type=1400 audit(0.0:99): avc: denied { write } for name="realm.testapp.com.realmsystemapp-Bfqpnjj4mUvxWtfMcOXBCA==" dev="vdc" ino=14660 scontext=u:r:system_app:s0 tcontext=u:object_r:apk_data_file:s0 tclass=dir permissive=0
05-24 14:08:08.984 6921 6921 W .realmsystemapp: type=1400 audit(0.0:100): avc: denied { write } for name="realm.testapp.com.realmsystemapp-Bfqpnjj4mUvxWtfMcOXBCA==" dev="vdc" ino=14660 scontext=u:r:system_app:s0 tcontext=u:object_r:apk_data_file:s0 tclass=dir permissive=0
In order to fix this you need to adjust the SELinux security rules in
the ROM. This can be done by using the tool ``audit2allow``, which ships
as part of AOSP:
1. Pull the current policy from the device:
.. code-block::
:copyable: false
adb pull /sys/fs/selinux/policy
#. Copy the SELinux error inside a text file called input.txt.
#. Run the ``audit2allow`` tool:
.. code-block::
:copyable: false
audit2allow -p policy -i input.txt
#. The tool should output a rule you can add to your existing policy
to enable the use of Realm.
An example of such a policy is provided below:
.. code-block::
:copyable: false
# Allow system_app to create named pipes required by Realm
# Credit: https://github.com/mikalackis/platform_vendor_ariel/blob/master_oreo/sepolicy/system_app.te
allow system_app fuse:fifo_file create;
allow system_app system_app_data_file:fifo_file create;
allow system_app system_app_data_file:fifo_file { read write };
allow system_app system_app_data_file:fifo_file open;
.. seealso:: audit2allow
``audit2allow`` is produced when compiling AOSP/ROM and only runs on
Linux. You can read more about it `here
<https://source.android.com/security/selinux/validate#using_audit2allow>`__.
.. note:: Changes in Android Oreo and Above
Since Android Oreo, Google changed the way it configures SELinux.
The default security policies are now much more modularized.
Read more about that
`here <https://source.android.com/security/selinux/images/SELinux_Treble.pdf>`__.
.. _java-change-notification-limits:
Change Notification Limits
--------------------------
.. include:: /includes/change-notification-limit.rst