@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.
- package/CONTRIBUTING.md +1 -1
- package/README.md +31 -60
- package/agents/ti-pro.md +3 -1
- package/commands/ti-audit.md +6 -4
- package/docs/examples.md +9 -0
- package/docs/knowledge-index.md +2 -1
- package/lib/config.js +1 -0
- package/package.json +1 -1
- package/skills/alloy-guides/SKILL.md +18 -179
- package/skills/alloy-guides/references/CLI_TASKS.md +17 -216
- package/skills/alloy-guides/references/CONCEPTS.md +27 -162
- package/skills/alloy-guides/references/CONTROLLERS.md +38 -236
- package/skills/alloy-guides/references/MODELS.md +47 -723
- package/skills/alloy-guides/references/MODELS_ADVANCED.md +21 -482
- package/skills/alloy-guides/references/VIEWS_DYNAMIC.md +12 -222
- package/skills/alloy-guides/references/VIEWS_STYLES.md +39 -358
- package/skills/alloy-guides/references/VIEWS_XML.md +36 -552
- package/skills/alloy-guides/references/WIDGETS.md +49 -127
- package/skills/alloy-howtos/SKILL.md +14 -169
- package/skills/alloy-howtos/references/best_practices.md +9 -113
- package/skills/alloy-howtos/references/cli_reference.md +18 -223
- package/skills/alloy-howtos/references/config_files.md +50 -133
- package/skills/alloy-howtos/references/debugging_troubleshooting.md +19 -63
- package/skills/alloy-howtos/references/samples.md +21 -138
- package/skills/ti-api/SKILL.md +10 -2
- package/skills/ti-api/references/api-android.md +36 -2
- package/skills/ti-api/references/api-app-platform.md +39 -3
- package/skills/ti-api/references/api-core.md +50 -18
- package/skills/ti-api/references/api-data-network.md +49 -35
- package/skills/ti-api/references/api-media.md +45 -27
- package/skills/ti-api/references/api-services.md +39 -9
- package/skills/ti-api/references/api-ui-android.md +33 -13
- package/skills/ti-api/references/api-ui-extras.md +41 -15
- package/skills/ti-api/references/api-ui-ios-animator.md +42 -26
- package/skills/ti-api/references/api-ui-ios.md +74 -2
- package/skills/ti-api/references/api-ui-lists.md +32 -16
- package/skills/ti-api/references/api-ui-text-input.md +34 -17
- package/skills/ti-api/references/api-ui-views.md +27 -1
- package/skills/ti-api/references/api-ui-windows-navigation.md +32 -18
- package/skills/ti-api/references/api-xml-global.md +66 -16
- package/skills/ti-create-release/SKILL.md +98 -0
- package/skills/ti-create-release/references/module-discovery.md +69 -0
- package/skills/ti-expert/references/adaptive-layouts.md +1 -1
- package/skills/ti-guides/SKILL.md +37 -76
- package/skills/ti-guides/references/advanced-data-and-images.md +122 -126
- package/skills/ti-guides/references/android-manifest.md +24 -83
- package/skills/ti-guides/references/app-distribution.md +31 -377
- package/skills/ti-guides/references/application-frameworks.md +127 -335
- package/skills/ti-guides/references/cli-reference.md +184 -633
- package/skills/ti-guides/references/commonjs-advanced.md +81 -231
- package/skills/ti-guides/references/compatibility-matrix.md +36 -75
- package/skills/ti-guides/references/hello-world.md +95 -70
- package/skills/ti-guides/references/hyperloop-native-access.md +52 -448
- package/skills/ti-guides/references/resources.md +174 -142
- package/skills/ti-guides/references/sdk-release-notes.md +28 -71
- package/skills/ti-guides/references/tiapp-config.md +222 -598
- package/skills/ti-howtos/SKILL.md +23 -123
- package/skills/ti-howtos/references/cross-platform-development.md +119 -324
- package/skills/ti-howtos/references/debugging-profiling.md +77 -445
- package/skills/ti-howtos/references/extending-titanium.md +199 -673
- package/skills/ti-howtos/references/local-data-sources.md +87 -300
- package/skills/ti-howtos/references/location-and-maps.md +86 -213
- package/skills/ti-howtos/references/media-apis.md +103 -223
- package/skills/ti-howtos/references/notification-services.md +86 -506
- package/skills/ti-howtos/references/remote-data-sources.md +97 -316
- package/skills/ti-howtos/references/using-modules.md +77 -133
- package/skills/ti-ui/SKILL.md +28 -143
- package/skills/ti-ui/references/icons-and-splash-screens.md +74 -403
- package/skills/ti-ui/references/layouts-and-positioning.md +175 -402
- package/skills/ti-ui/references/listviews-and-performance.md +100 -703
- package/skills/ti-ui/references/platform-conventions.md +180 -0
- package/skills/ti-ui/references/user-interface.md +43 -0
- package/skills/alloy-guides/references/VIEWS_WITHOUT_CONTROLLERS.md +0 -102
- package/skills/alloy-howtos/references/custom_tags.md +0 -148
- package/skills/ti-guides/references/coding-best-practices.md +0 -149
- package/skills/ti-guides/references/javascript-primer.md +0 -414
- package/skills/ti-guides/references/reserved-words.md +0 -36
- package/skills/ti-guides/references/style-and-conventions.md +0 -103
- package/skills/ti-howtos/references/android-platform-deep-dives.md +0 -624
- package/skills/ti-howtos/references/automation-fastlane-appium.md +0 -96
- package/skills/ti-howtos/references/buffer-codec-streams.md +0 -162
- package/skills/ti-howtos/references/google-maps-v2.md +0 -172
- package/skills/ti-howtos/references/ios-map-kit.md +0 -149
- package/skills/ti-howtos/references/ios-platform-deep-dives.md +0 -611
- package/skills/ti-howtos/references/tutorials.md +0 -565
- package/skills/ti-howtos/references/web-content-integration.md +0 -287
- package/skills/ti-howtos/references/webpack-build-pipeline.md +0 -124
- package/skills/ti-ui/references/accessibility-deep-dive.md +0 -288
- package/skills/ti-ui/references/animation-and-matrices.md +0 -569
- package/skills/ti-ui/references/application-structures.md +0 -626
- package/skills/ti-ui/references/custom-fonts-styling.md +0 -549
- package/skills/ti-ui/references/event-handling.md +0 -401
- package/skills/ti-ui/references/gestures.md +0 -448
- package/skills/ti-ui/references/orientation.md +0 -374
- package/skills/ti-ui/references/platform-ui-android.md +0 -727
- package/skills/ti-ui/references/platform-ui-ios.md +0 -576
- package/skills/ti-ui/references/scrolling-views.md +0 -288
- package/skills/ti-ui/references/tableviews.md +0 -542
|
@@ -1,354 +1,135 @@
|
|
|
1
|
-
#
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
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
|
|
32
|
-
Ti.API.
|
|
19
|
+
onerror(e) {
|
|
20
|
+
Ti.API.error(`request failed: ${e.error}`);
|
|
33
21
|
},
|
|
34
|
-
timeout:
|
|
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
|
-
|
|
82
|
-
|
|
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
|
-
|
|
101
|
-
`
|
|
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
|
-
|
|
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
|
-
|
|
119
|
-
JSON cannot represent methods. Stringifying Titanium objects returns an empty representation.
|
|
35
|
+
## Reading the response
|
|
120
36
|
|
|
121
|
-
|
|
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
|
-
|
|
124
|
-
|
|
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
|
-
```
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
##
|
|
66
|
+
## Sending
|
|
149
67
|
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
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
|
-
|
|
75
|
+
`setRequestHeader` goes **after** `open` and before `send`. Called before
|
|
76
|
+
`open` it is discarded, silently.
|
|
171
77
|
|
|
172
|
-
|
|
173
|
-
|
|
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
|
-
|
|
81
|
+
## Files
|
|
180
82
|
|
|
181
|
-
|
|
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
|
-
|
|
87
|
+
```js
|
|
88
|
+
const target = Ti.Filesystem.getFile(Ti.Filesystem.applicationDataDirectory, 'sdk.zip');
|
|
184
89
|
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
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
|
-
|
|
198
|
-
|
|
95
|
+
client.file = target;
|
|
96
|
+
client.open('GET', 'https://example.com/sdk.zip');
|
|
97
|
+
client.send();
|
|
199
98
|
```
|
|
200
99
|
|
|
201
|
-
|
|
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
|
-
|
|
204
|
-
xhr.file = Ti.Filesystem.getFile(Ti.Filesystem.applicationDataDirectory, 'download.zip');
|
|
205
|
-
```
|
|
106
|
+
## Is there a connection
|
|
206
107
|
|
|
207
|
-
```
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
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
|
-
|
|
326
|
-
|
|
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
|
-
|
|
329
|
-
|
|
330
|
-
const xhr = Ti.Network.createHTTPClient();
|
|
119
|
+
`networkType` distinguishes wifi from mobile, which is worth checking before a
|
|
120
|
+
large download.
|
|
331
121
|
|
|
332
|
-
|
|
333
|
-
xhr.addTrustManager(certificateStore.getTrustManager());
|
|
334
|
-
|
|
335
|
-
xhr.open('GET', url);
|
|
336
|
-
xhr.send();
|
|
337
|
-
```
|
|
122
|
+
## Certificates
|
|
338
123
|
|
|
339
|
-
|
|
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
|
-
|
|
342
|
-
- Enable CORS headers on the server
|
|
343
|
-
- Or configure a proxy service
|
|
344
|
-
- Use custom `Ti.Network.httpURLFormatter`
|
|
130
|
+
## Next
|
|
345
131
|
|
|
346
|
-
|
|
132
|
+
[Media](https://titaniumsdk.com/docs/build/media.md) covers the camera, the photo library, and playing
|
|
133
|
+
audio and video.
|
|
347
134
|
|
|
348
|
-
|
|
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).
|