@maccesar/titools 3.2.0 → 4.0.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/README.md +27 -61
- package/lib/cleanup.js +29 -0
- package/lib/commands/agents.js +8 -7
- package/lib/commands/skills.js +118 -23
- package/lib/config.js +13 -15
- package/lib/installer.js +5 -3
- package/lib/utils.js +36 -0
- package/package.json +1 -1
- package/skills/alloy-guides/SKILL.md +188 -0
- package/skills/alloy-guides/references/CLI_TASKS.md +233 -0
- package/skills/alloy-guides/references/CONCEPTS.md +171 -0
- package/skills/alloy-guides/references/CONTROLLERS.md +279 -0
- package/skills/alloy-guides/references/MODELS.md +742 -0
- package/skills/alloy-guides/references/MODELS_ADVANCED.md +482 -0
- package/skills/alloy-guides/references/PURGETSS.md +57 -0
- package/skills/alloy-guides/references/VIEWS_DYNAMIC.md +235 -0
- package/skills/alloy-guides/references/VIEWS_STYLES.md +375 -0
- package/skills/alloy-guides/references/VIEWS_WITHOUT_CONTROLLERS.md +102 -0
- package/skills/alloy-guides/references/VIEWS_XML.md +581 -0
- package/skills/alloy-guides/references/WIDGETS.md +160 -0
- package/skills/alloy-howtos/SKILL.md +179 -0
- package/skills/alloy-howtos/references/best_practices.md +121 -0
- package/skills/alloy-howtos/references/cli_reference.md +230 -0
- package/skills/alloy-howtos/references/config_files.md +158 -0
- package/skills/alloy-howtos/references/custom_tags.md +148 -0
- package/skills/alloy-howtos/references/debugging_troubleshooting.md +78 -0
- package/skills/alloy-howtos/references/samples.md +156 -0
- package/skills/purgetss/SKILL.md +184 -181
- package/skills/purgetss/references/EXAMPLES.md +8 -6
- package/skills/purgetss/references/app-branding.md +5 -0
- package/skills/purgetss/references/apply-directive.md +1 -1
- package/skills/purgetss/references/class-categories.md +1 -1
- package/skills/purgetss/references/class-index-properties.md +618 -0
- package/skills/purgetss/references/class-index.md +4 -610
- package/skills/purgetss/references/cli-commands.md +41 -410
- package/skills/purgetss/references/custom-fonts.md +292 -0
- package/skills/purgetss/references/custom-rules.md +1 -1
- package/skills/purgetss/references/customization-deep-dive.md +64 -1
- package/skills/purgetss/references/icon-fonts.md +208 -118
- package/skills/purgetss/references/installation-setup.md +4 -4
- package/skills/purgetss/references/migration-guide.md +53 -1
- package/skills/purgetss/references/multi-density-images.md +53 -2
- package/skills/purgetss/references/svg-pipeline.md +249 -0
- package/skills/purgetss/references/tikit-components.md +2 -2
- package/skills/purgetss/references/titanium-resets.md +2 -2
- package/skills/purgetss/references/ui-ux-design.md +7 -5
- package/skills/purgetss/references/version-history.md +71 -82
- package/skills/ti-api/SKILL.md +128 -0
- package/skills/ti-api/references/api-android.md +675 -0
- package/skills/ti-api/references/api-app-platform.md +636 -0
- package/skills/ti-api/references/api-core.md +764 -0
- package/skills/ti-api/references/api-data-network.md +641 -0
- package/skills/ti-api/references/api-media.md +655 -0
- package/skills/ti-api/references/api-modules-ble-bluetooth.md +657 -0
- package/skills/ti-api/references/api-modules-coremotion-urlsession.md +411 -0
- package/skills/ti-api/references/api-modules-map.md +632 -0
- package/skills/ti-api/references/api-modules-nfc.md +725 -0
- package/skills/ti-api/references/api-modules-social-misc.md +526 -0
- package/skills/ti-api/references/api-services.md +700 -0
- package/skills/ti-api/references/api-ui-android.md +499 -0
- package/skills/ti-api/references/api-ui-extras.md +702 -0
- package/skills/ti-api/references/api-ui-ios-animator.md +378 -0
- package/skills/ti-api/references/api-ui-ios.md +756 -0
- package/skills/ti-api/references/api-ui-lists.md +581 -0
- package/skills/ti-api/references/api-ui-text-input.md +607 -0
- package/skills/ti-api/references/api-ui-views.md +572 -0
- package/skills/ti-api/references/api-ui-windows-navigation.md +676 -0
- package/skills/ti-api/references/api-xml-global.md +743 -0
- package/skills/ti-guides/SKILL.md +82 -0
- package/skills/ti-guides/references/advanced-data-and-images.md +155 -0
- package/skills/ti-guides/references/android-manifest.md +97 -0
- package/skills/ti-guides/references/app-distribution.md +373 -0
- package/skills/ti-guides/references/application-frameworks.md +366 -0
- package/skills/ti-guides/references/cli-reference.md +700 -0
- package/skills/ti-guides/references/coding-best-practices.md +150 -0
- package/skills/ti-guides/references/commonjs-advanced.md +279 -0
- package/skills/ti-guides/references/hello-world.md +99 -0
- package/skills/ti-guides/references/hyperloop-native-access.md +458 -0
- package/skills/ti-guides/references/javascript-primer.md +402 -0
- package/skills/ti-guides/references/reserved-words.md +36 -0
- package/skills/ti-guides/references/resources.md +172 -0
- package/skills/ti-guides/references/style-and-conventions.md +104 -0
- package/skills/ti-guides/references/tiapp-config.md +655 -0
- package/skills/ti-howtos/SKILL.md +131 -0
- package/skills/ti-howtos/references/android-platform-deep-dives.md +609 -0
- package/skills/ti-howtos/references/automation-fastlane-appium.md +96 -0
- package/skills/ti-howtos/references/buffer-codec-streams.md +162 -0
- package/skills/ti-howtos/references/cross-platform-development.md +358 -0
- package/skills/ti-howtos/references/debugging-profiling.md +473 -0
- package/skills/ti-howtos/references/extending-titanium.md +684 -0
- package/skills/ti-howtos/references/google-maps-v2.md +172 -0
- package/skills/ti-howtos/references/ios-map-kit.md +149 -0
- package/skills/ti-howtos/references/ios-platform-deep-dives.md +595 -0
- package/skills/ti-howtos/references/local-data-sources.md +310 -0
- package/skills/ti-howtos/references/location-and-maps.md +267 -0
- package/skills/ti-howtos/references/media-apis.md +268 -0
- package/skills/ti-howtos/references/notification-services.md +539 -0
- package/skills/ti-howtos/references/remote-data-sources.md +339 -0
- package/skills/ti-howtos/references/tutorials.md +552 -0
- package/skills/ti-howtos/references/using-modules.md +182 -0
- package/skills/ti-howtos/references/web-content-integration.md +288 -0
- package/skills/ti-howtos/references/webpack-build-pipeline.md +125 -0
|
@@ -0,0 +1,310 @@
|
|
|
1
|
+
# Local data sources
|
|
2
|
+
|
|
3
|
+
## 1. Filesystem access and storage
|
|
4
|
+
|
|
5
|
+
### Modules overview
|
|
6
|
+
- `Ti.Filesystem` - top-level module for file/directory operations
|
|
7
|
+
- `Ti.Filesystem.File` - file object with read/write methods
|
|
8
|
+
- `Ti.Filesystem.FileStream` - stream wrapper implementing `Ti.IOStream`
|
|
9
|
+
|
|
10
|
+
### Storage locations
|
|
11
|
+
|
|
12
|
+
| Location | Read/Write | Persistence | Notes |
|
|
13
|
+
| --------------------------- | ---------- | ---------------- | -------------------------------------- |
|
|
14
|
+
| `applicationDataDirectory` | R/W | Until uninstall | Primary app data location |
|
|
15
|
+
| `resourcesDirectory` | R-only | Until uninstall | App resources (R/W in simulator only) |
|
|
16
|
+
| `tempDirectory` | R/W | Until app closes | OS may delete anytime |
|
|
17
|
+
| `applicationCacheDirectory` | R/W | OS may clean | For cached data |
|
|
18
|
+
| `externalCacheDirectory` | R/W | OS may clean | Android SD card cache |
|
|
19
|
+
| `externalStorageDirectory` | R/W | Until uninstall | Android SD card storage |
|
|
20
|
+
|
|
21
|
+
Always check `Ti.Filesystem.isExternalStoragePresent()` before using external storage on Android.
|
|
22
|
+
|
|
23
|
+
### File operations
|
|
24
|
+
|
|
25
|
+
#### Getting a file handle
|
|
26
|
+
```javascript
|
|
27
|
+
const f = Ti.Filesystem.getFile(
|
|
28
|
+
Ti.Filesystem.applicationDataDirectory,
|
|
29
|
+
'myfile.txt'
|
|
30
|
+
);
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
#### Writing files
|
|
34
|
+
```javascript
|
|
35
|
+
f.write('Content here'); // Overwrites or creates
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
#### Reading files
|
|
39
|
+
```javascript
|
|
40
|
+
const contents = f.read(); // Returns Blob
|
|
41
|
+
Ti.API.info(contents.text); // Text content
|
|
42
|
+
Ti.API.info(contents.mimeType); // MIME type
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
#### Appending
|
|
46
|
+
```javascript
|
|
47
|
+
f.append('More content\n'); // String, Blob, or File
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
#### Creating/copying
|
|
51
|
+
```javascript
|
|
52
|
+
// Auto-creates on write, but explicit option exists:
|
|
53
|
+
if (!f.exists()) {
|
|
54
|
+
f.createFile();
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// Android copy method:
|
|
58
|
+
const oldFile = Ti.Filesystem.getFile(applicationDataDirectory, 'old.txt');
|
|
59
|
+
oldFile.copy(`${applicationDataDirectory}new.txt`);
|
|
60
|
+
|
|
61
|
+
// iOS (no copy method):
|
|
62
|
+
const newFile = Ti.Filesystem.getFile(applicationDataDirectory, 'new.txt');
|
|
63
|
+
newFile.write(oldFile.read());
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
#### Renaming
|
|
67
|
+
Important: the file handle still points to the old name after rename.
|
|
68
|
+
|
|
69
|
+
```javascript
|
|
70
|
+
const f = Ti.Filesystem.getFile(applicationDataDirectory, 'old.txt');
|
|
71
|
+
f.rename('new.txt');
|
|
72
|
+
// f still references 'old.txt' (now non-existent)
|
|
73
|
+
const newf = Ti.Filesystem.getFile(applicationDataDirectory, 'new.txt');
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
#### Deleting
|
|
77
|
+
```javascript
|
|
78
|
+
if (f.exists() && f.writable) {
|
|
79
|
+
const success = f.deleteFile(); // Returns Boolean, no error thrown
|
|
80
|
+
}
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### Directory operations
|
|
84
|
+
|
|
85
|
+
```javascript
|
|
86
|
+
// Create directory
|
|
87
|
+
const dir = Ti.Filesystem.getFile(applicationDataDirectory, 'mysubdir');
|
|
88
|
+
dir.createDirectory();
|
|
89
|
+
|
|
90
|
+
// List contents
|
|
91
|
+
const listing = dir.getDirectoryListing();
|
|
92
|
+
|
|
93
|
+
// Move file into directory
|
|
94
|
+
const file = Ti.Filesystem.getFile(applicationDataDirectory, 'file.txt');
|
|
95
|
+
file.move('mysubdir/file.txt');
|
|
96
|
+
|
|
97
|
+
// Delete directory (must be empty or force recursive)
|
|
98
|
+
dir.deleteDirectory(false); // Fails if not empty
|
|
99
|
+
dir.deleteDirectory(true); // Recursive delete
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
### Case sensitivity warning
|
|
103
|
+
Android and Mobile Web use case-sensitive filesystems. File names referenced in code must match actual file names exactly. Recommendation: use lowercase file names.
|
|
104
|
+
|
|
105
|
+
## 2. SQLite database
|
|
106
|
+
|
|
107
|
+
### Installing a pre-populated database
|
|
108
|
+
Ship a database with your app and install it on first launch:
|
|
109
|
+
```javascript
|
|
110
|
+
// Copies db from Resources/ (or app/assets/) to applicationDataDirectory
|
|
111
|
+
const db = Ti.Database.install('seeds/mydata.sqlite', 'mydata');
|
|
112
|
+
// On subsequent launches, install() just opens the existing database
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
### Opening databases
|
|
116
|
+
|
|
117
|
+
```javascript
|
|
118
|
+
// Install (copies from Resources if first time)
|
|
119
|
+
const db = Ti.Database.install('mydb.sqlite', 'myInstalledDB');
|
|
120
|
+
|
|
121
|
+
// Or open existing database in applicationDataDirectory
|
|
122
|
+
const db = Ti.Database.open('myDatabase');
|
|
123
|
+
|
|
124
|
+
// For app data directory location:
|
|
125
|
+
const dbFile = Ti.Filesystem.getFile(
|
|
126
|
+
Ti.Filesystem.applicationDataDirectory,
|
|
127
|
+
'mydb.sqlite'
|
|
128
|
+
);
|
|
129
|
+
const db = Ti.Database.open(dbFile.nativePath);
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
### Querying data
|
|
133
|
+
|
|
134
|
+
```javascript
|
|
135
|
+
const rows = db.execute('SELECT * FROM users WHERE age > ?', [18]);
|
|
136
|
+
|
|
137
|
+
while (rows.isValidRow()) {
|
|
138
|
+
Ti.API.info(rows.fieldByName('name'));
|
|
139
|
+
Ti.API.info(rows.field(0)); // First column by index
|
|
140
|
+
rows.next();
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// Always close result set
|
|
144
|
+
rows.close();
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
### Parameterized queries
|
|
148
|
+
Always use parameters to prevent SQL injection:
|
|
149
|
+
|
|
150
|
+
```javascript
|
|
151
|
+
// Safe - parameterized
|
|
152
|
+
db.execute('INSERT INTO users (name, age) VALUES (?, ?)', ['John', 25]);
|
|
153
|
+
|
|
154
|
+
// Unsafe - never do this
|
|
155
|
+
db.execute(`INSERT INTO users (name, age) VALUES ('${name}', ${age})`);
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
### Data modification
|
|
159
|
+
|
|
160
|
+
```javascript
|
|
161
|
+
// INSERT
|
|
162
|
+
db.execute('INSERT INTO users (name, age) VALUES (?, ?)', ['Jane', 30]);
|
|
163
|
+
const lastId = db.lastInsertRowId; // ID of the last inserted row
|
|
164
|
+
const affected = db.rowsAffected; // number of rows changed by last statement
|
|
165
|
+
|
|
166
|
+
// UPDATE
|
|
167
|
+
db.execute('UPDATE users SET age = ? WHERE name = ?', [31, 'Jane']);
|
|
168
|
+
const rowsAffected = db.rowsAffected;
|
|
169
|
+
|
|
170
|
+
// DELETE
|
|
171
|
+
db.execute('DELETE FROM users WHERE age < ?', [18]);
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
### Transactions for batch operations
|
|
175
|
+
Use transactions to speed up multiple inserts or updates:
|
|
176
|
+
```javascript
|
|
177
|
+
const db = Ti.Database.open('mydb');
|
|
178
|
+
db.execute('BEGIN');
|
|
179
|
+
try {
|
|
180
|
+
for (let i = 0; i < items.length; i++) {
|
|
181
|
+
db.execute('INSERT INTO products (name, price) VALUES (?, ?)', items[i].name, items[i].price);
|
|
182
|
+
}
|
|
183
|
+
db.execute('COMMIT');
|
|
184
|
+
} catch (e) {
|
|
185
|
+
db.execute('ROLLBACK');
|
|
186
|
+
Ti.API.error(`Transaction failed: ${e.message}`);
|
|
187
|
+
}
|
|
188
|
+
db.close();
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
Performance: wrapping 1000 inserts in a transaction can be 10-100x faster than individual inserts.
|
|
192
|
+
|
|
193
|
+
### SQLite limitations
|
|
194
|
+
- No `FULL OUTER JOIN` support. Use `LEFT JOIN` with `UNION`.
|
|
195
|
+
- Limited `ALTER TABLE`. You can only `ADD COLUMN` or `RENAME TABLE`.
|
|
196
|
+
- No built-in referential integrity (foreign keys). Enable with `PRAGMA foreign_keys = ON`.
|
|
197
|
+
- No native boolean type. Use INTEGER (0/1).
|
|
198
|
+
|
|
199
|
+
### Disable iCloud backup for databases (iOS)
|
|
200
|
+
|
|
201
|
+
iOS backs up databases to iCloud by default. For large or recreatable databases, disable this:
|
|
202
|
+
```javascript
|
|
203
|
+
const db = Ti.Database.open('mydb');
|
|
204
|
+
db.file.setRemoteBackup(false);
|
|
205
|
+
db.close();
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
Important: Apple may reject apps that back up large recreatable data to iCloud.
|
|
209
|
+
|
|
210
|
+
### Always close connections
|
|
211
|
+
|
|
212
|
+
```javascript
|
|
213
|
+
try {
|
|
214
|
+
// Database operations
|
|
215
|
+
} finally {
|
|
216
|
+
// Always close, even on error
|
|
217
|
+
if (rows) rows.close();
|
|
218
|
+
if (db) db.close();
|
|
219
|
+
}
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
## 3. Properties API (Ti.App.Properties)
|
|
223
|
+
|
|
224
|
+
### Overview
|
|
225
|
+
Lightweight key-value storage for simple data types. Loaded into memory at launch for fast access.
|
|
226
|
+
|
|
227
|
+
Warning: there is no hard limit, but all properties load into memory. Avoid storing large data.
|
|
228
|
+
|
|
229
|
+
### Data type methods
|
|
230
|
+
|
|
231
|
+
| Type | Get method | Set method |
|
|
232
|
+
| ------ | -------------------------- | ------------------------ |
|
|
233
|
+
| String | `getString(name, default)` | `setString(name, value)` |
|
|
234
|
+
| Int | `getInt(name, default)` | `setInt(name, value)` |
|
|
235
|
+
| Double | `getDouble(name, default)` | `setDouble(name, value)` |
|
|
236
|
+
| Bool | `getBool(name, default)` | `setBool(name, value)` |
|
|
237
|
+
| List | `getList(name, default)` | `setList(name, value)` |
|
|
238
|
+
|
|
239
|
+
### Usage examples
|
|
240
|
+
|
|
241
|
+
```javascript
|
|
242
|
+
// Set values
|
|
243
|
+
Ti.App.Properties.setString('username', 'john');
|
|
244
|
+
Ti.App.Properties.setInt('loginCount', 5);
|
|
245
|
+
Ti.App.Properties.setBool('isLoggedIn', true);
|
|
246
|
+
Ti.App.Properties.setDouble('price', 19.99);
|
|
247
|
+
Ti.App.Properties.setList('favorites', ['item1', 'item2']);
|
|
248
|
+
|
|
249
|
+
// Get values (with defaults)
|
|
250
|
+
const username = Ti.App.Properties.getString('username', 'guest');
|
|
251
|
+
const count = Ti.App.Properties.getInt('loginCount', 0);
|
|
252
|
+
|
|
253
|
+
// Check if property exists
|
|
254
|
+
if (Ti.App.Properties.hasProperty('username')) {
|
|
255
|
+
// ...
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
// Remove property
|
|
259
|
+
Ti.App.Properties.removeProperty('username');
|
|
260
|
+
|
|
261
|
+
// List all properties
|
|
262
|
+
const allProps = Ti.App.Properties.listProperties();
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
### Storing complex objects as JSON
|
|
266
|
+
|
|
267
|
+
```javascript
|
|
268
|
+
// Store object as JSON string
|
|
269
|
+
const data = { city: 'Mountain View', temp: 72 };
|
|
270
|
+
Ti.App.Properties.setString('weatherData', JSON.stringify(data));
|
|
271
|
+
|
|
272
|
+
// Retrieve and parse
|
|
273
|
+
const stored = Ti.App.Properties.getString('weatherData', '{}');
|
|
274
|
+
const weather = JSON.parse(stored);
|
|
275
|
+
Ti.API.info(weather.city); // 'Mountain View'
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
### Platform storage
|
|
279
|
+
- iOS: `NSUserDefaults` in a `.plist` file
|
|
280
|
+
- Android: XML file at `/data/data/com.domain.app/shared_prefs/titanium.xml`
|
|
281
|
+
|
|
282
|
+
## 4. Advanced data manipulation (Buffer, Codec, and Streams)
|
|
283
|
+
|
|
284
|
+
For binary data handling, character encoding, and large file streams, see:
|
|
285
|
+
|
|
286
|
+
- Buffer, Codec, and Streams: `buffer-codec-streams.md`
|
|
287
|
+
|
|
288
|
+
## 5. Choosing a persistence strategy
|
|
289
|
+
|
|
290
|
+
### Decision guide
|
|
291
|
+
|
|
292
|
+
| Scenario | Recommended approach |
|
|
293
|
+
| ---------------------------------- | ---------------------------------------- |
|
|
294
|
+
| User settings/preferences | `Ti.App.Properties` |
|
|
295
|
+
| Small config data (< 100KB) | `Ti.App.Properties` with JSON |
|
|
296
|
+
| Structured relational data | SQLite |
|
|
297
|
+
| Large binary data (images, videos) | Filesystem |
|
|
298
|
+
| Downloaded content cache | Filesystem (`applicationCacheDirectory`) |
|
|
299
|
+
| Temporary processing data | Filesystem (`tempDirectory`) |
|
|
300
|
+
| User-generated files | Filesystem (`applicationDataDirectory`) |
|
|
301
|
+
| Offline-first app data | SQLite + Filesystem combo |
|
|
302
|
+
|
|
303
|
+
### Best practices
|
|
304
|
+
|
|
305
|
+
1. Properties API: use only for small, frequently accessed config data.
|
|
306
|
+
2. SQLite: always close connections and result sets; use parameterized queries.
|
|
307
|
+
3. Filesystem: check external storage availability on Android; handle case sensitivity.
|
|
308
|
+
4. Streams: use for large file operations to avoid memory issues.
|
|
309
|
+
5. Hybrid approach: store metadata in SQLite, file paths in records, actual files on filesystem.
|
|
310
|
+
6. Cleanup: implement cleanup for temp files and cache; do not let them accumulate.
|
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
# Location services and maps
|
|
2
|
+
|
|
3
|
+
## 1. GPS position tracking
|
|
4
|
+
|
|
5
|
+
### FusedLocationProvider (Android)
|
|
6
|
+
Since TiSDK 7.1.0, Titanium supports `FusedLocationProvider` for significant battery savings.
|
|
7
|
+
Requirement: include the `ti.playservices` module in your project.
|
|
8
|
+
|
|
9
|
+
### Accuracy configuration
|
|
10
|
+
|
|
11
|
+
iOS accuracy levels:
|
|
12
|
+
- `ACCURACY_BEST` - highest power (GPS)
|
|
13
|
+
- `ACCURACY_NEAREST_TEN_METERS` - medium-high power
|
|
14
|
+
- `ACCURACY_HUNDRED_METERS` - medium power
|
|
15
|
+
- `ACCURACY_KILOMETER` - low power
|
|
16
|
+
- `ACCURACY_THREE_KILOMETERS` - lowest power (cell/wifi)
|
|
17
|
+
|
|
18
|
+
Key properties:
|
|
19
|
+
```javascript
|
|
20
|
+
Ti.Geolocation.accuracy = Ti.Geolocation.ACCURACY_BEST;
|
|
21
|
+
Ti.Geolocation.distanceFilter = 10; // meters - only fire if moved X meters
|
|
22
|
+
Ti.Geolocation.headingFilter = 5; // degrees - only fire if heading changed X degrees
|
|
23
|
+
Ti.Geolocation.preferredProvider = Ti.Geolocation.PROVIDER_GPS; // or PROVIDER_NETWORK
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Note: on many Android devices, a low-precision passive location provider is always enabled, even when the user disables GPS and Network providers. `Ti.Geolocation.locationServicesEnabled` may always return `true` on those devices.
|
|
27
|
+
|
|
28
|
+
### Android configuration modes
|
|
29
|
+
|
|
30
|
+
Simple mode (ACCURACY_HIGH/LOW):
|
|
31
|
+
```javascript
|
|
32
|
+
Ti.Geolocation.accuracy = Ti.Geolocation.ACCURACY_HIGH;
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Manual mode (fine-grained control):
|
|
36
|
+
```javascript
|
|
37
|
+
const providerGps = Ti.Geolocation.Android.createLocationProvider({
|
|
38
|
+
name: Ti.Geolocation.PROVIDER_GPS,
|
|
39
|
+
minUpdateDistance: 0.0,
|
|
40
|
+
minUpdateTime: 0
|
|
41
|
+
});
|
|
42
|
+
Ti.Geolocation.Android.addLocationProvider(providerGps);
|
|
43
|
+
Ti.Geolocation.Android.manualMode = true;
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### Location permissions
|
|
47
|
+
|
|
48
|
+
```javascript
|
|
49
|
+
// Check permissions
|
|
50
|
+
if (Ti.Geolocation.hasLocationPermissions(Ti.Geolocation.AUTHORIZATION_WHEN_IN_USE)) {
|
|
51
|
+
startTracking();
|
|
52
|
+
} else {
|
|
53
|
+
Ti.Geolocation.requestLocationPermissions(Ti.Geolocation.AUTHORIZATION_WHEN_IN_USE, (e) => {
|
|
54
|
+
if (e.success) {
|
|
55
|
+
startTracking();
|
|
56
|
+
} else {
|
|
57
|
+
Ti.API.error(`Permission denied: ${e.error}`);
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
iOS plist keys (tiapp.xml):
|
|
64
|
+
```xml
|
|
65
|
+
<key>NSLocationWhenInUseUsageDescription</key>
|
|
66
|
+
<string>We need your location to show nearby places</string>
|
|
67
|
+
<!-- For background location: -->
|
|
68
|
+
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
|
|
69
|
+
<string>We need background location for navigation</string>
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
Note (iOS 11+): you must include `NSLocationAlwaysAndWhenInUseUsageDescription` even when requesting "Always" permission. Users can still choose "When in Use".
|
|
73
|
+
|
|
74
|
+
### One-time position
|
|
75
|
+
|
|
76
|
+
```javascript
|
|
77
|
+
if (Ti.Geolocation.locationServicesEnabled) {
|
|
78
|
+
Ti.Geolocation.getCurrentPosition((e) => {
|
|
79
|
+
if (e.error) {
|
|
80
|
+
Ti.API.error(`Error: ${e.error}`);
|
|
81
|
+
} else {
|
|
82
|
+
const coords = e.coords;
|
|
83
|
+
// { latitude, longitude, altitude, accuracy, heading, speed, timestamp }
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### Continuous monitoring
|
|
90
|
+
|
|
91
|
+
```javascript
|
|
92
|
+
Ti.Geolocation.addEventListener('location', (e) => {
|
|
93
|
+
if (e.error) {
|
|
94
|
+
Ti.API.error(`Error: ${e.error}`);
|
|
95
|
+
} else {
|
|
96
|
+
Ti.API.info(`${e.coords.latitude}, ${e.coords.longitude}`);
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
### Lifecycle management (critical for battery)
|
|
102
|
+
|
|
103
|
+
Android Activity events:
|
|
104
|
+
```javascript
|
|
105
|
+
let locationAdded = false;
|
|
106
|
+
const handleLocation = (e) => {
|
|
107
|
+
if (!e.error) {
|
|
108
|
+
Ti.API.info(e.coords);
|
|
109
|
+
}
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
function addHandler() {
|
|
113
|
+
if (!locationAdded) {
|
|
114
|
+
Ti.Geolocation.addEventListener('location', handleLocation);
|
|
115
|
+
locationAdded = true;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
function removeHandler() {
|
|
120
|
+
if (locationAdded) {
|
|
121
|
+
Ti.Geolocation.removeEventListener('location', handleLocation);
|
|
122
|
+
locationAdded = false;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// Add listeners
|
|
127
|
+
addHandler();
|
|
128
|
+
|
|
129
|
+
const activity = Ti.Android.currentActivity;
|
|
130
|
+
activity.addEventListener('destroy', removeHandler);
|
|
131
|
+
activity.addEventListener('pause', removeHandler); // Stop when in background
|
|
132
|
+
activity.addEventListener('resume', addHandler); // Resume when foreground
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
### Compass/heading
|
|
136
|
+
|
|
137
|
+
```javascript
|
|
138
|
+
// One-time heading
|
|
139
|
+
Ti.Geolocation.getCurrentHeading((e) => {
|
|
140
|
+
Ti.API.info(e.heading.magneticHeading); // degrees from magnetic north
|
|
141
|
+
Ti.API.info(e.heading.trueHeading); // degrees from true north
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
// Continuous heading monitoring
|
|
145
|
+
Ti.Geolocation.addEventListener('heading', (e) => {
|
|
146
|
+
if (!e.error) {
|
|
147
|
+
Ti.API.info(`Heading: ${e.heading.magneticHeading}`);
|
|
148
|
+
}
|
|
149
|
+
});
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
The heading event object includes:
|
|
153
|
+
- `heading.magneticHeading` - degrees relative to magnetic north
|
|
154
|
+
- `heading.trueHeading` - degrees relative to true north (requires location)
|
|
155
|
+
- `heading.accuracy` - deviation in degrees (lower is better)
|
|
156
|
+
- `heading.x`, `heading.y`, `heading.z` - raw magnetometer data (microteslas)
|
|
157
|
+
|
|
158
|
+
## Geocoding
|
|
159
|
+
|
|
160
|
+
### Forward geocoding (address → coordinates)
|
|
161
|
+
|
|
162
|
+
```javascript
|
|
163
|
+
Ti.Geolocation.forwardGeocoder('440 Bernardo Ave Mountain View CA', (e) => {
|
|
164
|
+
if (e.success) {
|
|
165
|
+
Ti.API.info(`Lat: ${e.latitude}, Lon: ${e.longitude}`);
|
|
166
|
+
}
|
|
167
|
+
});
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
With error handling:
|
|
171
|
+
```javascript
|
|
172
|
+
Ti.Geolocation.forwardGeocoder('1600 Amphitheatre Pkwy, Mountain View, CA', (e) => {
|
|
173
|
+
if (!e.success || e.error) {
|
|
174
|
+
Ti.API.error(`Geocoding failed: ${e.error}`);
|
|
175
|
+
return;
|
|
176
|
+
}
|
|
177
|
+
Ti.API.info(`Lat: ${e.latitude}, Lng: ${e.longitude}`);
|
|
178
|
+
});
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
### Reverse geocoding (coordinates → places)
|
|
182
|
+
|
|
183
|
+
```javascript
|
|
184
|
+
Ti.Geolocation.reverseGeocoder(37.389569, -122.050212, (e) => {
|
|
185
|
+
if (e.success) {
|
|
186
|
+
e.places.forEach((place) => {
|
|
187
|
+
Ti.API.info(place.address); // Full address
|
|
188
|
+
Ti.API.info(place.city); // City name
|
|
189
|
+
Ti.API.info(place.country); // Country
|
|
190
|
+
Ti.API.info(place.zipcode); // Postal code
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
});
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
## 2. Native maps (platform-specific details)
|
|
197
|
+
|
|
198
|
+
Due to the complexity of modern native maps, refer to the detailed guides:
|
|
199
|
+
|
|
200
|
+
- Google Maps v2 for Android: `google-maps-v2.md`
|
|
201
|
+
- iOS Map Kit: `ios-map-kit.md`
|
|
202
|
+
|
|
203
|
+
## Common map patterns
|
|
204
|
+
|
|
205
|
+
### Add annotation after map creation
|
|
206
|
+
|
|
207
|
+
```javascript
|
|
208
|
+
mapview.addAnnotation(annotation);
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
### Remove annotation
|
|
212
|
+
|
|
213
|
+
```javascript
|
|
214
|
+
mapview.removeAnnotation(annotation);
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
### Remove all annotations
|
|
218
|
+
|
|
219
|
+
```javascript
|
|
220
|
+
mapview.removeAllAnnotations();
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
### Select annotation programmatically
|
|
224
|
+
|
|
225
|
+
```javascript
|
|
226
|
+
mapview.selectAnnotation(annotation);
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
### Deselect annotation
|
|
230
|
+
|
|
231
|
+
```javascript
|
|
232
|
+
mapview.deselectAnnotation(annotation);
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
### Set region with animation
|
|
236
|
+
|
|
237
|
+
```javascript
|
|
238
|
+
mapview.setLocation({
|
|
239
|
+
latitude: 37.389569,
|
|
240
|
+
longitude: -122.050212,
|
|
241
|
+
animate: true
|
|
242
|
+
});
|
|
243
|
+
|
|
244
|
+
// Or for region
|
|
245
|
+
mapview.setRegion({
|
|
246
|
+
latitude: 37.389569,
|
|
247
|
+
longitude: -122.050212,
|
|
248
|
+
latitudeDelta: 0.05,
|
|
249
|
+
longitudeDelta: 0.05,
|
|
250
|
+
animate: true
|
|
251
|
+
});
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
### Zoom to annotations
|
|
255
|
+
|
|
256
|
+
```javascript
|
|
257
|
+
mapview.showAnnotations([annotation1, annotation2], true); // true = animate
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
### Best practices
|
|
261
|
+
|
|
262
|
+
1. Battery life: remove location listeners when not needed. Use `distanceFilter` to reduce updates.
|
|
263
|
+
2. Accuracy: use the lowest accuracy that meets your needs.
|
|
264
|
+
3. Permissions: check permissions before requesting location. Handle denial gracefully.
|
|
265
|
+
4. Maps on Android: only one map view per application (legacy). Use `ti.map` for multiple views.
|
|
266
|
+
5. API keys: Google Maps API key required for Android (debug and production).
|
|
267
|
+
6. User location: requires location permissions (`NSLocationWhenInUseUsageDescription` for iOS).
|