@maccesar/titools 5.3.0 → 5.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (98) hide show
  1. package/CONTRIBUTING.md +1 -1
  2. package/README.md +31 -60
  3. package/agents/ti-pro.md +3 -1
  4. package/commands/ti-audit.md +6 -4
  5. package/docs/examples.md +9 -0
  6. package/docs/knowledge-index.md +2 -1
  7. package/lib/config.js +1 -0
  8. package/package.json +1 -1
  9. package/skills/alloy-guides/SKILL.md +18 -179
  10. package/skills/alloy-guides/references/CLI_TASKS.md +17 -216
  11. package/skills/alloy-guides/references/CONCEPTS.md +27 -162
  12. package/skills/alloy-guides/references/CONTROLLERS.md +38 -236
  13. package/skills/alloy-guides/references/MODELS.md +47 -723
  14. package/skills/alloy-guides/references/MODELS_ADVANCED.md +21 -482
  15. package/skills/alloy-guides/references/VIEWS_DYNAMIC.md +12 -222
  16. package/skills/alloy-guides/references/VIEWS_STYLES.md +39 -358
  17. package/skills/alloy-guides/references/VIEWS_XML.md +36 -552
  18. package/skills/alloy-guides/references/WIDGETS.md +49 -127
  19. package/skills/alloy-howtos/SKILL.md +14 -169
  20. package/skills/alloy-howtos/references/best_practices.md +9 -113
  21. package/skills/alloy-howtos/references/cli_reference.md +18 -223
  22. package/skills/alloy-howtos/references/config_files.md +50 -133
  23. package/skills/alloy-howtos/references/debugging_troubleshooting.md +19 -63
  24. package/skills/alloy-howtos/references/samples.md +21 -138
  25. package/skills/ti-api/SKILL.md +10 -2
  26. package/skills/ti-api/references/api-android.md +36 -2
  27. package/skills/ti-api/references/api-app-platform.md +39 -3
  28. package/skills/ti-api/references/api-core.md +50 -18
  29. package/skills/ti-api/references/api-data-network.md +49 -35
  30. package/skills/ti-api/references/api-media.md +45 -27
  31. package/skills/ti-api/references/api-services.md +39 -9
  32. package/skills/ti-api/references/api-ui-android.md +33 -13
  33. package/skills/ti-api/references/api-ui-extras.md +41 -15
  34. package/skills/ti-api/references/api-ui-ios-animator.md +42 -26
  35. package/skills/ti-api/references/api-ui-ios.md +74 -2
  36. package/skills/ti-api/references/api-ui-lists.md +32 -16
  37. package/skills/ti-api/references/api-ui-text-input.md +34 -17
  38. package/skills/ti-api/references/api-ui-views.md +27 -1
  39. package/skills/ti-api/references/api-ui-windows-navigation.md +32 -18
  40. package/skills/ti-api/references/api-xml-global.md +66 -16
  41. package/skills/ti-create-release/SKILL.md +98 -0
  42. package/skills/ti-create-release/references/module-discovery.md +69 -0
  43. package/skills/ti-expert/references/adaptive-layouts.md +1 -1
  44. package/skills/ti-guides/SKILL.md +37 -76
  45. package/skills/ti-guides/references/advanced-data-and-images.md +122 -126
  46. package/skills/ti-guides/references/android-manifest.md +24 -83
  47. package/skills/ti-guides/references/app-distribution.md +31 -377
  48. package/skills/ti-guides/references/application-frameworks.md +127 -335
  49. package/skills/ti-guides/references/cli-reference.md +184 -633
  50. package/skills/ti-guides/references/commonjs-advanced.md +81 -231
  51. package/skills/ti-guides/references/compatibility-matrix.md +36 -75
  52. package/skills/ti-guides/references/hello-world.md +95 -70
  53. package/skills/ti-guides/references/hyperloop-native-access.md +52 -448
  54. package/skills/ti-guides/references/resources.md +174 -142
  55. package/skills/ti-guides/references/sdk-release-notes.md +28 -71
  56. package/skills/ti-guides/references/tiapp-config.md +222 -598
  57. package/skills/ti-howtos/SKILL.md +23 -123
  58. package/skills/ti-howtos/references/cross-platform-development.md +119 -324
  59. package/skills/ti-howtos/references/debugging-profiling.md +77 -445
  60. package/skills/ti-howtos/references/extending-titanium.md +199 -673
  61. package/skills/ti-howtos/references/local-data-sources.md +87 -300
  62. package/skills/ti-howtos/references/location-and-maps.md +86 -213
  63. package/skills/ti-howtos/references/media-apis.md +103 -223
  64. package/skills/ti-howtos/references/notification-services.md +86 -506
  65. package/skills/ti-howtos/references/remote-data-sources.md +97 -316
  66. package/skills/ti-howtos/references/using-modules.md +77 -133
  67. package/skills/ti-ui/SKILL.md +28 -143
  68. package/skills/ti-ui/references/icons-and-splash-screens.md +74 -403
  69. package/skills/ti-ui/references/layouts-and-positioning.md +175 -402
  70. package/skills/ti-ui/references/listviews-and-performance.md +100 -703
  71. package/skills/ti-ui/references/platform-conventions.md +180 -0
  72. package/skills/ti-ui/references/user-interface.md +43 -0
  73. package/skills/alloy-guides/references/VIEWS_WITHOUT_CONTROLLERS.md +0 -102
  74. package/skills/alloy-howtos/references/custom_tags.md +0 -148
  75. package/skills/ti-guides/references/coding-best-practices.md +0 -149
  76. package/skills/ti-guides/references/javascript-primer.md +0 -414
  77. package/skills/ti-guides/references/reserved-words.md +0 -36
  78. package/skills/ti-guides/references/style-and-conventions.md +0 -103
  79. package/skills/ti-howtos/references/android-platform-deep-dives.md +0 -624
  80. package/skills/ti-howtos/references/automation-fastlane-appium.md +0 -96
  81. package/skills/ti-howtos/references/buffer-codec-streams.md +0 -162
  82. package/skills/ti-howtos/references/google-maps-v2.md +0 -172
  83. package/skills/ti-howtos/references/ios-map-kit.md +0 -149
  84. package/skills/ti-howtos/references/ios-platform-deep-dives.md +0 -611
  85. package/skills/ti-howtos/references/tutorials.md +0 -565
  86. package/skills/ti-howtos/references/web-content-integration.md +0 -287
  87. package/skills/ti-howtos/references/webpack-build-pipeline.md +0 -124
  88. package/skills/ti-ui/references/accessibility-deep-dive.md +0 -288
  89. package/skills/ti-ui/references/animation-and-matrices.md +0 -569
  90. package/skills/ti-ui/references/application-structures.md +0 -626
  91. package/skills/ti-ui/references/custom-fonts-styling.md +0 -549
  92. package/skills/ti-ui/references/event-handling.md +0 -401
  93. package/skills/ti-ui/references/gestures.md +0 -448
  94. package/skills/ti-ui/references/orientation.md +0 -374
  95. package/skills/ti-ui/references/platform-ui-android.md +0 -727
  96. package/skills/ti-ui/references/platform-ui-ios.md +0 -576
  97. package/skills/ti-ui/references/scrolling-views.md +0 -288
  98. package/skills/ti-ui/references/tableviews.md +0 -542
@@ -1,354 +1,135 @@
1
- # Remote data sources
2
-
3
- <!-- TOC-START -->
4
- ## Contents
5
-
6
- - [1. HTTPClient and request lifecycle](#1-httpclient-and-request-lifecycle)
7
- - [2. Working with JSON data](#2-working-with-json-data)
8
- - [3. Working with XML data](#3-working-with-xml-data)
9
- - [4. File uploads and downloads](#4-file-uploads-and-downloads)
10
- - [5. Sockets](#5-sockets)
11
- - [6. Dealing with SOAP web services](#6-dealing-with-soap-web-services)
12
- - [7. SSL certificate and SecurityManager](#7-ssl-certificate-and-securitymanager)
13
- - [8. CORS considerations for Mobile Web](#8-cors-considerations-for-mobile-web)
14
- - [Best practices](#best-practices)
15
-
16
- <!-- TOC-END -->
17
-
18
- ## 1. HTTPClient and request lifecycle
19
-
20
- ### Basic pattern
21
- `Ti.Network.HTTPClient` mirrors the XHR (XMLHttpRequest) API. Always handle both success and error paths.
22
-
23
- ```javascript
24
- const xhr = Ti.Network.createHTTPClient({
25
- onload: (e) => {
26
- // this.responseText - raw text (JSON/text)
27
- // this.responseXML - XML document (including SOAP)
28
- // this.responseData - binary data (Blob)
29
- Ti.API.debug(xhr.responseText);
1
+ # Networking & remote data
2
+
3
+ Based on the [current official guide](https://titaniumsdk.com/docs/build/data/networking.md). Examples target released SDK 13.4.1; verify the selected SDK before adopting version-specific behavior.
4
+
5
+ `Ti.Network.HTTPClient` is the HTTP client. It is shaped like
6
+ `XMLHttpRequest` - `open`, then `send`, with callbacks - because that is what it
7
+ was modelled on, not because there is a browser anywhere.
8
+
9
+ ```js
10
+ const client = Ti.Network.createHTTPClient({
11
+ onload() {
12
+ try {
13
+ const body = JSON.parse(this.responseText);
14
+ Ti.API.info(body);
15
+ } catch (error) {
16
+ Ti.API.error(`Invalid JSON: ${error.message}`);
17
+ }
30
18
  },
31
- onerror: (e) => {
32
- Ti.API.debug(e.error);
19
+ onerror(e) {
20
+ Ti.API.error(`request failed: ${e.error}`);
33
21
  },
34
- timeout: 5000
22
+ timeout: 10000
35
23
  });
36
- xhr.open('GET', 'https://api.example.com/data');
37
- xhr.send();
38
- ```
39
-
40
- ### HTTP methods
41
- - GET: `xhr.open('GET', url)` then `xhr.send()`
42
- - POST: `xhr.open('POST', url)` then `xhr.send({key: 'value'})`
43
- - PUT/DELETE/PATCH: all supported (PATCH since 4.1.0 on Android)
44
-
45
- ### Setting headers
46
- Headers must be set after `open()` but before `send()`.
47
-
48
- ```javascript
49
- const client = Ti.Network.createHTTPClient();
50
- client.open('POST', 'http://server.com/upload');
51
- client.setRequestHeader('Content-Type', 'text/csv');
52
- client.setRequestHeader('Authorization', `Bearer ${token}`);
53
- client.send('data');
54
- ```
55
-
56
- ### XHR lifecycle states
57
- Monitor with `onreadystatechange`:
58
- - `UNSENT` - object constructed
59
- - `OPENED` - `open()` called successfully
60
- - `HEADERS_RECEIVED` - all redirects followed, headers received
61
- - `LOADING` - response body being received
62
- - `DONE` - transfer complete or error occurred
63
-
64
- ```javascript
65
- xhr.onreadystatechange = (e) => {
66
- switch (xhr.readyState) {
67
- case Ti.Network.HTTPClient.HEADERS_RECEIVED:
68
- Ti.API.info(`Headers: ${xhr.getResponseHeader('Content-Type')}`);
69
- break;
70
- case Ti.Network.HTTPClient.DONE:
71
- Ti.API.info('Complete');
72
- break;
73
- }
74
- };
75
- ```
76
-
77
- ### Progress monitoring
78
- - `onsendstream`: upload progress (0.0-1.0)
79
- - `ondatastream`: download progress (0.0-1.0)
80
24
 
81
- ```javascript
82
- xhr.onsendstream = (e) => {
83
- progressBar.value = e.progress;
84
- };
85
- xhr.ondatastream = (e) => {
86
- progressBar.value = e.progress;
87
- };
88
- ```
89
-
90
- ## 2. Working with JSON data
91
-
92
- ### Receiving JSON
93
- ```javascript
94
- xhr.onload = () => {
95
- const data = JSON.parse(xhr.responseText);
96
- Ti.API.info(data.users[0].name);
97
- };
25
+ client.open('GET', 'https://titaniumsdk.com/registry/v1/releases');
26
+ client.send();
98
27
  ```
99
28
 
100
- ### Sending JSON
101
- `send()` stringifies objects for you.
102
-
103
- ```javascript
104
- const postData = { title: 'My Post', body: 'Content' };
105
- xhr.open('POST', 'http://blog.com/api/posts');
106
- xhr.send(postData); // Auto-stringified
107
- ```
29
+ `onload` and `onerror` are called with the client as `this`, which is where
30
+ `responseText`, `status` and the headers live.
108
31
 
109
- For GET query strings, stringify and encode yourself.
110
-
111
- ```javascript
112
- const data = { search: 'titanium' };
113
- const queryString = encodeURIComponent(JSON.stringify(data));
114
- xhr.open('GET', `http://api.com/search?q=${queryString}`);
115
- xhr.send();
116
- ```
32
+ **Set a `timeout`.** Without one a request on a dropped connection hangs until
33
+ the platform gives up, which is measured in minutes on a mobile network.
117
34
 
118
- ### Important limitation
119
- JSON cannot represent methods. Stringifying Titanium objects returns an empty representation.
35
+ ## Reading the response
120
36
 
121
- ## 3. Working with XML data
37
+ | Property | What you get |
38
+ | -------- | ------------ |
39
+ | `responseText` | The body as a string |
40
+ | `responseData` | The body as a `Blob`, for binary |
41
+ | `responseXML` | A parsed document, for XML |
42
+ | `status` | The HTTP status code |
43
+ | `getResponseHeader(name)` | One header |
122
44
 
123
- ### Parsing XML
124
- Titanium provides XML DOM Level 2. If the response is XML and the server sends the correct Content-Type, Titanium auto-parses it.
45
+ There is no `responseJSON`. Parse `responseText` yourself, and do it inside a
46
+ `try` - a proxy or a captive portal will hand you an HTML error page with a 200
47
+ on it, and `JSON.parse` throwing inside `onload` is an unhandled exception.
125
48
 
126
- ```javascript
127
- xhr.onload = () => {
128
- const doc = xhr.responseXML.documentElement;
129
- const items = doc.getElementsByTagName('item');
130
- for (let i = 0; i < items.length; i++) {
131
- const title = items.item(i)
132
- .getElementsByTagName('title').item(0)
133
- .textContent;
134
- Ti.API.info(title);
49
+ ```js
50
+ client.onload = function () {
51
+ let body;
52
+ try {
53
+ body = JSON.parse(this.responseText);
54
+ } catch {
55
+ Ti.API.error('expected JSON, got something else');
56
+ return;
135
57
  }
58
+ Ti.API.info(body);
136
59
  };
137
60
  ```
138
61
 
139
- ### Common DOM methods
140
- - `getElementsByTagName(name)` - returns array of nodes
141
- - `item(index)` - selects a specific node from the array
142
- - `getAttribute(name)` - gets an attribute value
143
- - `textContent` / `nodeValue` - gets a leaf node value
62
+ ## Failure callbacks and server status
144
63
 
145
- ### Important: know your DTD
146
- You must understand the XML structure (node hierarchy) to parse correctly. Use tools like apigee.com to inspect API responses.
64
+ Handle both `onload` and `onerror`; inspect `client.status` and the error payload before choosing a retry or UI message. Network, timeout and TLS failures can reach `onerror`, and HTTP failures can too: the released Android implementation dispatches HTTP status 400+ to `onerror`. Do not assume a 404/500 always reaches `onload` as the current guide suggests. Finish loading indicators in both handlers.
147
65
 
148
- ## 4. File uploads and downloads
66
+ ## Sending
149
67
 
150
- ### File upload
151
- Pass a Blob to `send()`.
152
-
153
- ```javascript
154
- Ti.Media.openPhotoGallery({
155
- success: (event) => {
156
- const xhr = Ti.Network.createHTTPClient({
157
- onload: () => {
158
- Ti.API.info(`Upload complete: ${xhr.status}`);
159
- }
160
- });
161
- xhr.open('POST', 'https://server.com/upload');
162
- xhr.send({
163
- file: event.media, // Blob from gallery
164
- username: 'user'
165
- });
166
- }
167
- });
68
+ ```js
69
+ const client = Ti.Network.createHTTPClient({ onload() { /* ... */ } });
70
+ client.open('POST', 'https://example.com/notes');
71
+ client.setRequestHeader('Content-Type', 'application/json');
72
+ client.send(JSON.stringify({ body: 'A note' }));
168
73
  ```
169
74
 
170
- For file uploads with actual file contents:
75
+ `setRequestHeader` goes **after** `open` and before `send`. Called before
76
+ `open` it is discarded, silently.
171
77
 
172
- ```javascript
173
- const file = Ti.Filesystem.getFile(event.media.nativePath);
174
- if (file.exists()) {
175
- xhr.send({ file: file.read() });
176
- }
177
- ```
78
+ Pass a plain object to `send` instead and it is encoded as a form post. Pass a
79
+ dictionary containing a file and it becomes a multipart upload.
178
80
 
179
- Note: when uploading from the photo gallery, `event.media` is a Blob. For filesystem uploads, use `Ti.Filesystem.getFile(path).read()` to get a Blob.
81
+ ## Files
180
82
 
181
- ### File download (cross-platform)
83
+ Set `file` on the client and the response is written straight to disk rather
84
+ than held in memory, which is how to download something larger than you want
85
+ resident:
182
86
 
183
- Option 1: write manually to the filesystem.
87
+ ```js
88
+ const target = Ti.Filesystem.getFile(Ti.Filesystem.applicationDataDirectory, 'sdk.zip');
184
89
 
185
- ```javascript
186
- const xhr = Ti.Network.createHTTPClient({
187
- onload: () => {
188
- const file = Ti.Filesystem.getFile(
189
- Ti.Filesystem.applicationDataDirectory,
190
- 'downloaded.png'
191
- );
192
- file.write(xhr.responseData);
193
- Ti.App.fireEvent('download_complete', { path: file.nativePath });
194
- },
195
- timeout: 10000
90
+ const client = Ti.Network.createHTTPClient({
91
+ onload() { Ti.API.info(`saved ${target.size} bytes`); },
92
+ onerror(e) { Ti.API.error(e.error); },
93
+ timeout: 60000
196
94
  });
197
- xhr.open('GET', 'http://example.com/image.png');
198
- xhr.send();
95
+ client.file = target;
96
+ client.open('GET', 'https://example.com/sdk.zip');
97
+ client.send();
199
98
  ```
200
99
 
201
- Option 2 (iOS only): set `xhr.file` to save directly without buffering.
100
+ `ondatastream` reports progress as a `progress` value from 0 to 1, which is
101
+ what to wire a progress bar to. `onsendstream` does the same for uploads. Both
102
+ must be set **before** `open`, and `progress` is
103
+ `Ti.Network.PROGRESS_UNKNOWN` when the size is not known ahead of time, which
104
+ is the case for a chunked response.
202
105
 
203
- ```javascript
204
- xhr.file = Ti.Filesystem.getFile(Ti.Filesystem.applicationDataDirectory, 'download.zip');
205
- ```
106
+ ## Is there a connection
206
107
 
207
- ```javascript
208
- const xhr = Ti.Network.createHTTPClient({
209
- onload: () => {
210
- Ti.API.info('Saved to applicationDataDirectory/test.pdf');
211
- }
212
- });
213
- xhr.open('GET', 'http://example.com/file.pdf');
214
- xhr.file = Ti.Filesystem.getFile(
215
- Ti.Filesystem.applicationDataDirectory,
216
- 'test.pdf'
217
- );
218
- xhr.send();
219
- ```
220
-
221
- ### File storage locations
222
- - `applicationDataDirectory` - primary read/write location for app files
223
- - `resourcesDirectory` - read-only app resources (writeable in simulator only)
224
- - `tempDirectory` - temporary files, OS may delete when app closes
225
- - `externalCacheDirectory` - Android SD card cache (check `isExternalStoragePresent()`)
226
- - `applicationCacheDirectory` - cache data, persists but OS may clean it up
227
-
228
- ## 5. Sockets
229
-
230
- Titanium supports TCP sockets via `Ti.Network.Socket`.
231
-
232
- ### Creating a TCP socket
233
-
234
- ```javascript
235
- const socket = Ti.Network.Socket.createTCP({
236
- host: 'example.com',
237
- port: 80,
238
- connected: function (e) {
239
- Ti.API.info('Socket connected');
240
- // Write data
241
- this.write(Ti.createBuffer({
242
- value: 'GET / HTTP/1.1\r\nHost: example.com\r\n\r\n'
243
- }));
244
- },
245
- error: (e) => {
246
- Ti.API.error(`Socket error: ${e.error}`);
247
- }
248
- });
249
-
250
- socket.connect();
251
- ```
252
-
253
- ### Socket listening (Android/iOS)
254
- To create a socket server that accepts connections:
255
-
256
- ```javascript
257
- const listenSocket = Ti.Network.Socket.createTCP({
258
- host: '127.0.0.1', // localhost
259
- port: 40404,
260
- accepted: (e) => {
261
- Ti.API.info(`Incoming connection accepted: ${e.inbound}`);
262
- e.inbound.close();
263
- }
264
- });
265
- listenSocket.listen();
266
- listenSocket.accept(); // Asynchronous, waits for next connection
267
- ```
268
-
269
- Platform note: on iOS, `Ti.Platform.address` returns the WiFi interface address. On Android, only the loopback address (`127.0.0.1`) is available for listening sockets.
270
-
271
- ## 6. Dealing with SOAP web services
272
-
273
- JSON is recommended, but you can consume legacy SOAP services by sending the XML envelope manually.
274
-
275
- ### Manual approach (SOAP envelope)
276
- ```javascript
277
- const client = Ti.Network.createHTTPClient();
278
- client.onload = () => {
279
- const doc = client.responseXML.documentElement;
280
- // Parse the response XML manually
281
- };
282
-
283
- const soapRequest = "<?xml version=\"1.0\" encoding=\"UTF-8\"?> \n" +
284
- "<SOAP-ENV:Envelope xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\"> \n" +
285
- "<SOAP-ENV:Body> \n" +
286
- " <GetUserDetailsReq> \n" +
287
- " <SessionToken>XXXX</SessionToken> \n" +
288
- " </GetUserDetailsReq> \n" +
289
- "</SOAP-ENV:Body> \n" +
290
- "</SOAP-ENV:Envelope>";
291
-
292
- client.open('POST', 'https://server.com/service.asmx');
293
- client.setRequestHeader('Content-Type', 'text/xml; charset=utf-8');
294
- client.send({ xml: soapRequest });
295
- ```
296
-
297
- ## 7. SSL certificate and SecurityManager
298
-
299
- For SSL pinning, use the `securityManager` property.
300
-
301
- ### SSL pinning (TiSDK 3.3.0+)
302
- Pinning ensures the app only communicates with a server that presents a specific certificate.
303
-
304
- ```javascript
305
- const xhr = Ti.Network.createHTTPClient({
306
- validatesSecureCertificate: true,
307
- // securityManager allows custom validation logic
308
- securityManager: mySecurityModule
309
- });
310
- ```
311
-
312
- ### SSL certificate store (Android)
313
- ```javascript
314
- const certificateStore = require('ti.certificatestore');
315
- const httpClient = Ti.Network.createHTTPClient({
316
- securityManager: certificateStore.createX509CertificatePinningSecurityManager([
317
- {
318
- url: 'https://api.example.com',
319
- serverCertificate: 'api_cert.der'
320
- }
321
- ])
322
- });
108
+ ```js
109
+ if (!Ti.Network.online) {
110
+ // ...
111
+ }
323
112
  ```
324
113
 
325
- ### Android: addTrustManager
326
- Use this for development environments or private networks with custom certs.
114
+ `Ti.Network.online` is whether the device has a route, not whether your server
115
+ is reachable. Treat it as a way to explain a failure rather than a way to
116
+ predict one: send the request, and use the flag to say "you appear to be
117
+ offline" when it fails.
327
118
 
328
- ```javascript
329
- const certificateStore = require('ti.certificatestore');
330
- const xhr = Ti.Network.createHTTPClient();
119
+ `networkType` distinguishes wifi from mobile, which is worth checking before a
120
+ large download.
331
121
 
332
- certificateStore.addCertificate('server.p12', 'password');
333
- xhr.addTrustManager(certificateStore.getTrustManager());
334
-
335
- xhr.open('GET', url);
336
- xhr.send();
337
- ```
122
+ ## Certificates
338
123
 
339
- ## 8. CORS considerations for Mobile Web
124
+ `validatesSecureCertificate` defaults to true in distribution mode and false
125
+ in simulator/testing mode (including development device builds), so a self-signed certificate works in
126
+ development and fails in production. That is deliberate. Do not set it to false
127
+ to make a release work - pin properly with `securityManager` or fix the
128
+ certificate.
340
129
 
341
- For Mobile Web targets accessing cross-domain resources:
342
- - Enable CORS headers on the server
343
- - Or configure a proxy service
344
- - Use custom `Ti.Network.httpURLFormatter`
130
+ ## Next
345
131
 
346
- ## Best practices
132
+ [Media](https://titaniumsdk.com/docs/build/media.md) covers the camera, the photo library, and playing
133
+ audio and video.
347
134
 
348
- 1. Set timeouts to prevent hanging requests.
349
- 2. Handle both `onload` and `onerror`.
350
- 3. Use progress callbacks for large file operations.
351
- 4. Save large downloads to disk using `file` (iOS) or `write()` to avoid memory exhaustion.
352
- 5. For complex JSON, validate schema before parsing.
353
- 6. For XML, test with real responses to verify node hierarchy.
354
- 7. Use `onsendstream` and `ondatastream` for user feedback during transfers.
135
+ Contract correction: [released HTTPClient API](https://github.com/tidev/titanium-sdk/blob/13_4_1_GA/apidoc/Titanium/Network/HTTPClient.yml) and [Android response dispatch](https://github.com/tidev/titanium-sdk/blob/13_4_1_GA/android/modules/network/src/java/ti/modules/titanium/network/TiHTTPClient.java).