@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,342 +1,129 @@
1
- # Local data sources
2
-
3
- <!-- TOC-START -->
4
- ## Contents
5
-
6
- - [1. Filesystem access and storage](#1-filesystem-access-and-storage)
7
- - [Modules overview](#modules-overview)
8
- - [Storage locations](#storage-locations)
9
- - [File operations](#file-operations)
10
- - [Directory operations](#directory-operations)
11
- - [Case sensitivity warning](#case-sensitivity-warning)
12
- - [2. SQLite database](#2-sqlite-database)
13
- - [Installing a pre-populated database](#installing-a-pre-populated-database)
14
- - [Opening databases](#opening-databases)
15
- - [Querying data](#querying-data)
16
- - [Parameterized queries](#parameterized-queries)
17
- - [Data modification](#data-modification)
18
- - [Transactions for batch operations](#transactions-for-batch-operations)
19
- - [SQLite limitations](#sqlite-limitations)
20
- - [Disable iCloud backup for databases (iOS)](#disable-icloud-backup-for-databases-ios)
21
- - [Always close connections](#always-close-connections)
22
- - [3. Properties API (Ti.App.Properties)](#3-properties-api-tiappproperties)
23
- - [Overview](#overview)
24
- - [Data type methods](#data-type-methods)
25
- - [Usage examples](#usage-examples)
26
- - [Storing complex objects as JSON](#storing-complex-objects-as-json)
27
- - [Platform storage](#platform-storage)
28
- - [4. Advanced data manipulation (Buffer, Codec, and Streams)](#4-advanced-data-manipulation-buffer-codec-and-streams)
29
- - [5. Choosing a persistence strategy](#5-choosing-a-persistence-strategy)
30
- - [Decision guide](#decision-guide)
31
- - [Best practices](#best-practices)
32
-
33
- <!-- TOC-END -->
34
-
35
- ## 1. Filesystem access and storage
36
-
37
- ### Modules overview
38
- - `Ti.Filesystem` - top-level module for file/directory operations
39
- - `Ti.Filesystem.File` - file object with read/write methods
40
- - `Ti.Filesystem.FileStream` - stream wrapper implementing `Ti.IOStream`
41
-
42
- ### Storage locations
43
-
44
- | Location | Read/Write | Persistence | Notes |
45
- | --------------------------- | ---------- | ---------------- | -------------------------------------- |
46
- | `applicationDataDirectory` | R/W | Until uninstall | Primary app data location |
47
- | `resourcesDirectory` | R-only | Until uninstall | App resources (R/W in simulator only) |
48
- | `tempDirectory` | R/W | Until app closes | OS may delete anytime |
49
- | `applicationCacheDirectory` | R/W | OS may clean | For cached data |
50
- | `externalCacheDirectory` | R/W | OS may clean | Android SD card cache |
51
- | `externalStorageDirectory` | R/W | Until uninstall | Android SD card storage |
52
-
53
- Always check `Ti.Filesystem.isExternalStoragePresent()` before using external storage on Android.
54
-
55
- ### File operations
56
-
57
- #### Getting a file handle
58
- ```javascript
59
- const f = Ti.Filesystem.getFile(
60
- Ti.Filesystem.applicationDataDirectory,
61
- 'myfile.txt'
62
- );
63
- ```
1
+ # Working with data
64
2
 
65
- #### Writing files
66
- ```javascript
67
- f.write('Content here'); // Overwrites or creates
68
- ```
3
+ Based on the [current official guide](https://titaniumsdk.com/docs/build/data.md). Examples target released SDK 13.4.1; verify the selected SDK before adopting version-specific behavior.
69
4
 
70
- #### Reading files
71
- ```javascript
72
- const contents = f.read(); // Returns Blob
73
- Ti.API.info(contents.text); // Text content
74
- Ti.API.info(contents.mimeType); // MIME type
75
- ```
5
+ Titanium gives you three places to keep data on the device, and the whole
6
+ decision is how much of it there is and what shape it has.
76
7
 
77
- #### Appending
78
- ```javascript
79
- f.append('More content\n'); // String, Blob, or File
80
- ```
8
+ | Store | For | Survives an uninstall |
9
+ | ----- | --- | --------------------- |
10
+ | `Ti.App.Properties` | Settings and small values | No |
11
+ | `Ti.Filesystem` | Files, downloads, generated content | No |
12
+ | `Ti.Database` | Rows you query | No |
81
13
 
82
- #### Creating/copying
83
- ```javascript
84
- // Auto-creates on write, but explicit option exists:
85
- if (!f.exists()) {
86
- f.createFile();
87
- }
14
+ None of them survive an uninstall. Anything that must is on a server, and
15
+ [networking](https://titaniumsdk.com/docs/build/data/networking.md) is how it gets there.
88
16
 
89
- // Android copy method:
90
- const oldFile = Ti.Filesystem.getFile(applicationDataDirectory, 'old.txt');
91
- oldFile.copy(`${applicationDataDirectory}new.txt`);
17
+ ## Properties
92
18
 
93
- // iOS (no copy method):
94
- const newFile = Ti.Filesystem.getFile(applicationDataDirectory, 'new.txt');
95
- newFile.write(oldFile.read());
96
- ```
19
+ Key-value storage for small things: the last tab, a token, whether the user has
20
+ seen the tour. It is backed by `NSUserDefaults` on iOS and `SharedPreferences`
21
+ on Android, and it is read synchronously.
97
22
 
98
- #### Renaming
99
- Important: the file handle still points to the old name after rename.
23
+ ```js
24
+ Ti.App.Properties.setString('lastTab', 'inbox');
25
+ Ti.App.Properties.setBool('seenTour', true);
100
26
 
101
- ```javascript
102
- const f = Ti.Filesystem.getFile(applicationDataDirectory, 'old.txt');
103
- f.rename('new.txt');
104
- // f still references 'old.txt' (now non-existent)
105
- const newf = Ti.Filesystem.getFile(applicationDataDirectory, 'new.txt');
27
+ const tab = Ti.App.Properties.getString('lastTab', 'inbox');
28
+ const seen = Ti.App.Properties.getBool('seenTour', false);
106
29
  ```
107
30
 
108
- #### Deleting
109
- ```javascript
110
- if (f.exists() && f.writable) {
111
- const success = f.deleteFile(); // Returns Boolean, no error thrown
112
- }
113
- ```
31
+ Every getter takes a default as its second argument. Use it rather than
32
+ checking `hasProperty` first, which is a second lookup for the same answer.
114
33
 
115
- ### Directory operations
34
+ There is a setter and getter per type - `setString`, `setInt`, `setBool`,
35
+ `setDouble`, `setList`, `setObject` - and reading with the wrong one does not
36
+ convert. Store with `setInt` and read with `getString` and you get the default
37
+ back.
116
38
 
117
- ```javascript
118
- // Create directory
119
- const dir = Ti.Filesystem.getFile(applicationDataDirectory, 'mysubdir');
120
- dir.createDirectory();
39
+ `setObject` and `setList` serialise to JSON, so they are for a handful of
40
+ values, not a collection you keep adding to.
121
41
 
122
- // List contents
123
- const listing = dir.getDirectoryListing();
42
+ > [!WARNING]
43
+ > Properties are not secure storage. They are plain preferences, readable on a
44
+ > rooted or jailbroken device and included in an unencrypted device backup. A
45
+ > token you would mind losing belongs in the keychain or keystore, which is a
46
+ > native module rather than a core API.
124
47
 
125
- // Move file into directory
126
- const file = Ti.Filesystem.getFile(applicationDataDirectory, 'file.txt');
127
- file.move('mysubdir/file.txt');
48
+ ## Files
128
49
 
129
- // Delete directory (must be empty or force recursive)
130
- dir.deleteDirectory(false); // Fails if not empty
131
- dir.deleteDirectory(true); // Recursive delete
132
- ```
50
+ `Ti.Filesystem` addresses directories by purpose, and the purpose decides
51
+ whether the operating system may delete what you put there.
133
52
 
134
- ### Case sensitivity warning
135
- Android and Mobile Web use case-sensitive filesystems. File names referenced in code must match actual file names exactly. Recommendation: use lowercase file names.
53
+ | Directory | Use for | Backed up |
54
+ | --------- | ------- | --------- |
55
+ | `applicationDataDirectory` | Content the app created and needs | Yes |
56
+ | `applicationCacheDirectory` | Anything re-downloadable | No, and may be purged |
57
+ | `tempDirectory` | Working files for right now | No |
58
+ | `resourcesDirectory` | What you shipped. **Read-only** | n/a |
136
59
 
137
- ## 2. SQLite database
60
+ ```js
61
+ const file = Ti.Filesystem.getFile(Ti.Filesystem.applicationDataDirectory, 'notes.txt');
62
+ file.write('written on ' + new Date().toISOString());
138
63
 
139
- ### Installing a pre-populated database
140
- Ship a database with your app and install it on first launch:
141
- ```javascript
142
- // Copies db from Resources/ (or app/assets/) to applicationDataDirectory
143
- const db = Ti.Database.install('seeds/mydata.sqlite', 'mydata');
144
- // On subsequent launches, install() just opens the existing database
64
+ if (file.exists()) {
65
+ Ti.API.info(file.read().text);
66
+ }
145
67
  ```
146
68
 
147
- ### Opening databases
69
+ `getFile` takes path segments and joins them, so pass the directory and the
70
+ name rather than concatenating with a separator yourself.
148
71
 
149
- ```javascript
150
- // Install (copies from Resources if first time)
151
- const db = Ti.Database.install('mydb.sqlite', 'myInstalledDB');
72
+ Putting a cache in `applicationDataDirectory` is the common mistake: it is
73
+ backed up, so a 200MB image cache goes into the user's iCloud backup.
152
74
 
153
- // Or open existing database in applicationDataDirectory
154
- const db = Ti.Database.open('myDatabase');
75
+ ## A database
155
76
 
156
- // For app data directory location:
157
- const dbFile = Ti.Filesystem.getFile(
158
- Ti.Filesystem.applicationDataDirectory,
159
- 'mydb.sqlite'
160
- );
161
- const db = Ti.Database.open(dbFile.nativePath);
162
- ```
77
+ `Ti.Database` is SQLite. Open a database by name and it is created on first
78
+ use.
79
+
80
+ ```js
81
+ const db = Ti.Database.open('notes');
163
82
 
164
- ### Querying data
83
+ db.execute(`
84
+ CREATE TABLE IF NOT EXISTS notes (
85
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
86
+ body TEXT NOT NULL,
87
+ created TEXT NOT NULL
88
+ )
89
+ `);
165
90
 
166
- ```javascript
167
- const rows = db.execute('SELECT * FROM users WHERE age > ?', [18]);
91
+ db.execute('INSERT INTO notes (body, created) VALUES (?, ?)', 'First note', new Date().toISOString());
92
+ Ti.API.info(`inserted row ${db.lastInsertRowId}`);
168
93
 
94
+ const rows = db.execute('SELECT id, body FROM notes ORDER BY id DESC');
169
95
  while (rows.isValidRow()) {
170
- Ti.API.info(rows.fieldByName('name'));
171
- Ti.API.info(rows.field(0)); // First column by index
96
+ Ti.API.info(`${rows.fieldByName('id')}: ${rows.fieldByName('body')}`);
172
97
  rows.next();
173
98
  }
174
-
175
- // Always close result set
176
99
  rows.close();
177
- ```
178
-
179
- ### Parameterized queries
180
- Always use parameters to prevent SQL injection:
181
-
182
- ```javascript
183
- // Safe - parameterized
184
- db.execute('INSERT INTO users (name, age) VALUES (?, ?)', ['John', 25]);
185
-
186
- // Unsafe - never do this
187
- db.execute(`INSERT INTO users (name, age) VALUES ('${name}', ${age})`);
188
- ```
189
-
190
- ### Data modification
191
-
192
- ```javascript
193
- // INSERT
194
- db.execute('INSERT INTO users (name, age) VALUES (?, ?)', ['Jane', 30]);
195
- const lastId = db.lastInsertRowId; // ID of the last inserted row
196
- const affected = db.rowsAffected; // number of rows changed by last statement
197
-
198
- // UPDATE
199
- db.execute('UPDATE users SET age = ? WHERE name = ?', [31, 'Jane']);
200
- const rowsAffected = db.rowsAffected;
201
-
202
- // DELETE
203
- db.execute('DELETE FROM users WHERE age < ?', [18]);
204
- ```
205
-
206
- ### Transactions for batch operations
207
- Use transactions to speed up multiple inserts or updates:
208
- ```javascript
209
- const db = Ti.Database.open('mydb');
210
- db.execute('BEGIN');
211
- try {
212
- for (let i = 0; i < items.length; i++) {
213
- db.execute('INSERT INTO products (name, price) VALUES (?, ?)', items[i].name, items[i].price);
214
- }
215
- db.execute('COMMIT');
216
- } catch (e) {
217
- db.execute('ROLLBACK');
218
- Ti.API.error(`Transaction failed: ${e.message}`);
219
- }
220
- db.close();
221
- ```
222
-
223
- Performance: wrapping 1000 inserts in a transaction can be 10-100x faster than individual inserts.
224
-
225
- ### SQLite limitations
226
- - No `FULL OUTER JOIN` support. Use `LEFT JOIN` with `UNION`.
227
- - Limited `ALTER TABLE`. You can only `ADD COLUMN` or `RENAME TABLE`.
228
- - No built-in referential integrity (foreign keys). Enable with `PRAGMA foreign_keys = ON`.
229
- - No native boolean type. Use INTEGER (0/1).
230
-
231
- ### Disable iCloud backup for databases (iOS)
232
-
233
- iOS backs up databases to iCloud by default. For large or recreatable databases, disable this:
234
- ```javascript
235
- const db = Ti.Database.open('mydb');
236
- db.file.setRemoteBackup(false);
237
100
  db.close();
238
101
  ```
239
102
 
240
- Important: Apple may reject apps that back up large recreatable data to iCloud.
241
-
242
- ### Always close connections
243
-
244
- ```javascript
245
- try {
246
- // Database operations
247
- } finally {
248
- // Always close, even on error
249
- if (rows) rows.close();
250
- if (db) db.close();
251
- }
252
- ```
253
-
254
- ## 3. Properties API (Ti.App.Properties)
255
-
256
- ### Overview
257
- Lightweight key-value storage for simple data types. Loaded into memory at launch for fast access.
258
-
259
- Warning: there is no hard limit, but all properties load into memory. Avoid storing large data.
260
-
261
- ### Data type methods
103
+ **Pass values as arguments, never by building the SQL string.** The `?`
104
+ placeholders are escaped for you; string concatenation is how an apostrophe in
105
+ a note becomes a syntax error and how a hostile value becomes an injection.
262
106
 
263
- | Type | Get method | Set method |
264
- | ------ | -------------------------- | ------------------------ |
265
- | String | `getString(name, default)` | `setString(name, value)` |
266
- | Int | `getInt(name, default)` | `setInt(name, value)` |
267
- | Double | `getDouble(name, default)` | `setDouble(name, value)` |
268
- | Bool | `getBool(name, default)` | `setBool(name, value)` |
269
- | List | `getList(name, default)` | `setList(name, value)` |
107
+ A result set is a cursor, not an array: walk it with `isValidRow()` and
108
+ `next()`, and close it. Close the database when you are done with it.
270
109
 
271
- ### Usage examples
110
+ `executeAsync` and `executeAllAsync` run off the main thread and take a
111
+ callback. Use them for anything large enough to be noticeable, which on a
112
+ phone is sooner than you would guess.
272
113
 
273
- ```javascript
274
- // Set values
275
- Ti.App.Properties.setString('username', 'john');
276
- Ti.App.Properties.setInt('loginCount', 5);
277
- Ti.App.Properties.setBool('isLoggedIn', true);
278
- Ti.App.Properties.setDouble('price', 19.99);
279
- Ti.App.Properties.setList('favorites', ['item1', 'item2']);
114
+ ### Shipping a prepared database
280
115
 
281
- // Get values (with defaults)
282
- const username = Ti.App.Properties.getString('username', 'guest');
283
- const count = Ti.App.Properties.getInt('loginCount', 0);
116
+ `Ti.Database.install` copies a `.sqlite` file out of your resources on first
117
+ run and opens it, so an app can ship with data already in it.
284
118
 
285
- // Check if property exists
286
- if (Ti.App.Properties.hasProperty('username')) {
287
- // ...
288
- }
289
-
290
- // Remove property
291
- Ti.App.Properties.removeProperty('username');
292
-
293
- // List all properties
294
- const allProps = Ti.App.Properties.listProperties();
295
- ```
296
-
297
- ### Storing complex objects as JSON
298
-
299
- ```javascript
300
- // Store object as JSON string
301
- const data = { city: 'Mountain View', temp: 72 };
302
- Ti.App.Properties.setString('weatherData', JSON.stringify(data));
303
-
304
- // Retrieve and parse
305
- const stored = Ti.App.Properties.getString('weatherData', '{}');
306
- const weather = JSON.parse(stored);
307
- Ti.API.info(weather.city); // 'Mountain View'
119
+ ```js
120
+ const db = Ti.Database.install('/data/seed.sqlite', 'notes');
308
121
  ```
309
122
 
310
- ### Platform storage
311
- - iOS: `NSUserDefaults` in a `.plist` file
312
- - Android: XML file at `/data/data/com.domain.app/shared_prefs/titanium.xml`
313
-
314
- ## 4. Advanced data manipulation (Buffer, Codec, and Streams)
315
-
316
- For binary data handling, character encoding, and large file streams, see:
317
-
318
- - Buffer, Codec, and Streams: `buffer-codec-streams.md`
319
-
320
- ## 5. Choosing a persistence strategy
321
-
322
- ### Decision guide
323
-
324
- | Scenario | Recommended approach |
325
- | ---------------------------------- | ---------------------------------------- |
326
- | User settings/preferences | `Ti.App.Properties` |
327
- | Small config data (< 100KB) | `Ti.App.Properties` with JSON |
328
- | Structured relational data | SQLite |
329
- | Large binary data (images, videos) | Filesystem |
330
- | Downloaded content cache | Filesystem (`applicationCacheDirectory`) |
331
- | Temporary processing data | Filesystem (`tempDirectory`) |
332
- | User-generated files | Filesystem (`applicationDataDirectory`) |
333
- | Offline-first app data | SQLite + Filesystem combo |
123
+ The copy happens once. Changing the shipped file in a later release does not
124
+ replace a database the user already has, so version your schema and migrate.
334
125
 
335
- ### Best practices
126
+ ## Next
336
127
 
337
- 1. Properties API: use only for small, frequently accessed config data.
338
- 2. SQLite: always close connections and result sets; use parameterized queries.
339
- 3. Filesystem: check external storage availability on Android; handle case sensitivity.
340
- 4. Streams: use for large file operations to avoid memory issues.
341
- 5. Hybrid approach: store metadata in SQLite, file paths in records, actual files on filesystem.
342
- 6. Cleanup: implement cleanup for temp files and cache; do not let them accumulate.
128
+ [Networking and remote data](https://titaniumsdk.com/docs/build/data/networking.md) is the other half:
129
+ getting data in and out over HTTP.