@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,624 +0,0 @@
1
- # Android platform deep dives
2
-
3
- <!-- TOC-START -->
4
- ## Contents
5
-
6
- - [1. Android intent filters (advanced)](#1-android-intent-filters-advanced)
7
- - [2. Broadcast intents with permissions](#2-broadcast-intents-with-permissions)
8
- - [3. FusedLocationProvider (TiSDK 7.1.0+)](#3-fusedlocationprovider-tisdk-710)
9
- - [4. Android intents](#4-android-intents)
10
- - [5. Intent filters](#5-intent-filters)
11
- - [6. Broadcast intents and receivers](#6-broadcast-intents-and-receivers)
12
- - [7. Android services](#7-android-services)
13
- - [8. Android permissions](#8-android-permissions)
14
- - [Best practices](#best-practices)
15
-
16
- <!-- TOC-END -->
17
-
18
- ## 1. Android intent filters (advanced)
19
-
20
- To receive implicit intents (for example, opening a PDF file or a web link), register a filter in the manifest.
21
-
22
- ### Critical step: copy root activity
23
- Before declaring an `intent-filter`, copy the `<activity>` node of your main activity from `build/android/AndroidManifest.xml` into the `<android>` section of your `tiapp.xml`:
24
-
25
- ```xml
26
- <android xmlns:android="http://schemas.android.com/apk/res/android">
27
- <manifest>
28
- <application>
29
- <!-- Copy this from build/android/AndroidManifest.xml -->
30
- <activity android:name=".YourAppActivity" android:label="My App" android:configChanges="keyboardHidden|orientation">
31
- <intent-filter>
32
- <action android:name="android.intent.action.MAIN" />
33
- <category android:name="android.intent.category.LAUNCHER" />
34
- </intent-filter>
35
-
36
- <!-- Your new filter here -->
37
- <intent-filter android:label="Open with My App">
38
- <action android:name="android.intent.action.VIEW" />
39
- <category android:name="android.intent.category.DEFAULT" />
40
- <data android:mimeType="application/pdf" />
41
- </intent-filter>
42
- </activity>
43
- </application>
44
- </manifest>
45
- </android>
46
- ```
47
-
48
- ### Retrieving intent data
49
- ```javascript
50
- const intent = Ti.Android.currentActivity.getIntent();
51
- if (intent.hasExtra(Ti.Android.EXTRA_TEXT)) {
52
- const sharedText = intent.getStringExtra(Ti.Android.EXTRA_TEXT);
53
- }
54
- ```
55
-
56
- ## 2. Broadcast intents with permissions
57
-
58
- You can restrict which apps receive your broadcast messages.
59
-
60
- ### Sending with permission
61
- ```javascript
62
- const intent = Ti.Android.createBroadcastIntent({
63
- action: 'com.mycompany.SECURE_ACTION'
64
- });
65
- // Only apps with the permission 'com.mycompany.SPECIAL_PERMISSION' will receive it
66
- Ti.Android.currentActivity.sendBroadcastWithPermission(intent, 'com.mycompany.SPECIAL_PERMISSION');
67
- ```
68
-
69
- ### Declaring permission in tiapp.xml
70
- ```xml
71
- <android>
72
- <manifest>
73
- <permission android:name="com.mycompany.SPECIAL_PERMISSION" />
74
- <uses-permission android:name="com.mycompany.SPECIAL_PERMISSION" />
75
- </manifest>
76
- </android>
77
- ```
78
-
79
- ## 3. FusedLocationProvider (TiSDK 7.1.0+)
80
-
81
- For battery-efficient location tracking on Android, use the fused provider.
82
-
83
- Requirement: include the `ti.playservices` module in your project.
84
- ```xml
85
- <module platform="android">ti.playservices</module>
86
- ```
87
- Titanium will switch to Google Play Services for geolocation, which reduces power consumption.
88
-
89
- ## 4. Android intents
90
-
91
- ### Overview
92
- Intents are message objects that specify actions to perform. They can start activities, broadcasts, or services.
93
-
94
- ### Intent structure
95
- - Action: what to do (for example, `ACTION_VIEW`, `ACTION_SEND`)
96
- - Data: URI the intent operates on (URL, file path)
97
- - Type: MIME type of data
98
- - Category: additional categorization
99
- - Extras: key-value pairs for additional data
100
-
101
- ### Creating intents
102
-
103
- #### Simple intent (action only)
104
- ```javascript
105
- const intent = Ti.Android.createIntent({
106
- action: Ti.Android.ACTION_VIEW
107
- });
108
- ```
109
-
110
- #### Intent with action and data
111
- ```javascript
112
- const intent = Ti.Android.createIntent({
113
- action: Ti.Android.ACTION_VIEW,
114
- data: 'https://titaniumsdk.com'
115
- });
116
- Ti.Android.currentActivity.startActivity(intent);
117
- ```
118
-
119
- #### Intent with extras
120
- ```javascript
121
- const intent = Ti.Android.createIntent({
122
- action: 'com.example.MY_ACTION',
123
- type: 'text/plain'
124
- });
125
- intent.putExtra('message', 'Hello from Titanium');
126
- intent.putExtra('count', 42);
127
- ```
128
-
129
- ### Common use cases
130
-
131
- #### Open URL in browser
132
- ```javascript
133
- const intent = Ti.Android.createIntent({
134
- action: Ti.Android.ACTION_VIEW,
135
- data: 'https://www.example.com'
136
- });
137
- Ti.Android.currentActivity.startActivity(intent);
138
- ```
139
-
140
- #### Dial phone number
141
- ```javascript
142
- const intent = Ti.Android.createIntent({
143
- action: Ti.Android.ACTION_DIAL,
144
- data: 'tel:5551234'
145
- });
146
- Ti.Android.currentActivity.startActivity(intent);
147
- ```
148
-
149
- #### Send email
150
- ```javascript
151
- const intent = Ti.Android.createIntent({
152
- action: Ti.Android.ACTION_SENDTO,
153
- data: 'mailto:user@example.com'
154
- });
155
- intent.putExtra(Ti.Android.EXTRA_SUBJECT, 'Hello');
156
- intent.putExtra(Ti.Android.EXTRA_TEXT, 'Email body');
157
- Ti.Android.currentActivity.startActivity(intent);
158
- ```
159
-
160
- #### Share content
161
- ```javascript
162
- const intent = Ti.Android.createIntent({
163
- action: Ti.Android.ACTION_SEND,
164
- type: 'text/plain'
165
- });
166
- intent.putExtra(Ti.Android.EXTRA_TEXT, 'Check this out!');
167
- Ti.Android.currentActivity.startActivity(intent);
168
- ```
169
-
170
- #### Open PDF file
171
- ```javascript
172
- const intent = Ti.Android.createIntent({
173
- action: Ti.Android.ACTION_VIEW,
174
- type: 'application/pdf',
175
- data: file.nativePath // Ti.Filesystem.File object
176
- });
177
- intent.addFlags(Ti.Android.FLAG_GRANT_READ_URI_PERMISSION);
178
- Ti.Android.currentActivity.startActivity(intent);
179
- ```
180
-
181
- ### Starting other apps
182
- ```javascript
183
- // Open specific app by package name
184
- const intent = Ti.Android.createIntent({
185
- action: Ti.Android.ACTION_MAIN,
186
- packageName: 'com.example.anotherapp',
187
- className: 'com.example.anotherapp.MainActivity'
188
- });
189
- try {
190
- Ti.Android.currentActivity.startActivity(intent);
191
- } catch (e) {
192
- Ti.API.error(`App not installed: ${e.message}`);
193
- }
194
- ```
195
-
196
- ### Intent chooser
197
- Force the system to show an app chooser dialog (even if a default is set):
198
- ```javascript
199
- const intent = Ti.Android.createIntent({
200
- action: Ti.Android.ACTION_SEND,
201
- type: 'text/plain'
202
- });
203
- intent.putExtra(Ti.Android.EXTRA_TEXT, 'Share this text');
204
-
205
- Ti.Android.currentActivity.startActivity(
206
- Ti.Android.createIntentChooser(intent, 'Share via...')
207
- );
208
- ```
209
-
210
- ### Getting results from activities
211
- ```javascript
212
- const intent = Ti.Android.createIntent({
213
- action: 'android.media.action.IMAGE_CAPTURE'
214
- });
215
-
216
- Ti.Android.currentActivity.startActivityForResult(intent, (e) => {
217
- if (e.resultCode === Ti.Android.RESULT_OK) {
218
- const imageUri = e.intent.data;
219
- Ti.API.info(`Captured image: ${imageUri}`);
220
- } else if (e.resultCode === Ti.Android.RESULT_CANCELED) {
221
- Ti.API.info('User canceled');
222
- }
223
- });
224
- ```
225
-
226
- ## 5. Intent filters
227
-
228
- ### Overview
229
- Intent filters advertise your app's capability to handle certain actions and data types. They enable deep linking, file handling, and inter-app communication.
230
-
231
- ### Configuring in tiapp.xml
232
-
233
- ```xml
234
- <android>
235
- <manifest>
236
- <application>
237
- <activity>
238
- <intent-filter>
239
- <action android:name="android.intent.action.VIEW"/>
240
- <category android:name="android.intent.category.DEFAULT"/>
241
- <category android:name="android.intent.category.BROWSABLE"/>
242
- <data android:scheme="myapp"/>
243
- </intent-filter>
244
-
245
- <!-- Handle PDF files -->
246
- <intent-filter>
247
- <action android:name="android.intent.action.VIEW"/>
248
- <category android:name="android.intent.category.DEFAULT"/>
249
- <data android:mimeType="application/pdf"/>
250
- </intent-filter>
251
-
252
- <!-- Handle HTTP URLs -->
253
- <intent-filter>
254
- <action android:name="android.intent.action.VIEW"/>
255
- <category android:name="android.intent.category.DEFAULT"/>
256
- <category android:name="android.intent.category.BROWSABLE"/>
257
- <data android:scheme="http" android:host="www.example.com"/>
258
- </intent-filter>
259
- </activity>
260
- </application>
261
- </manifest>
262
- </android>
263
- ```
264
-
265
- ### Handling incoming intents
266
-
267
- #### Get intent data on startup
268
- ```javascript
269
- const activity = Ti.Android.currentActivity;
270
- const intent = activity.getIntent();
271
-
272
- if (intent) {
273
- const action = intent.getAction();
274
- const data = intent.getData();
275
-
276
- if (data) {
277
- Ti.API.info(`Received data: ${data}`);
278
- // Handle URL or file path
279
- }
280
-
281
- // Get extras
282
- const extra = intent.getStringExtra('key');
283
- Ti.API.info(`Extra value: ${extra}`);
284
- }
285
- ```
286
-
287
- #### Listen for new intents (activity restart)
288
- ```javascript
289
- Ti.Android.currentActivity.addEventListener('newintent', (e) => {
290
- const intent = e.intent;
291
- const data = intent.getData();
292
- Ti.API.info(`New intent received: ${data}`);
293
-
294
- // Handle the new intent
295
- handleDeepLink(data);
296
- });
297
- ```
298
-
299
- ### Deep linking example
300
-
301
- ```xml
302
- <!-- In tiapp.xml -->
303
- <intent-filter>
304
- <action android:name="android.intent.action.VIEW"/>
305
- <category android:name="android.intent.category.DEFAULT"/>
306
- <category android:name="android.intent.category.BROWSABLE"/>
307
- <data android:scheme="myapp" android:host="product"/>
308
- </intent-filter>
309
- ```
310
-
311
- ```javascript
312
- // In app.js
313
- function handleDeepLink(url) {
314
- // Parse URL like: myapp://product/123
315
- const parts = url.split('/');
316
- const productId = parts[parts.length - 1];
317
- openProductScreen(productId);
318
- }
319
-
320
- // Check on startup
321
- const activity = Ti.Android.currentActivity;
322
- const intent = activity.getIntent();
323
- if (intent && intent.getData()) {
324
- handleDeepLink(intent.getData());
325
- }
326
- ```
327
-
328
- ## 6. Broadcast intents and receivers
329
-
330
- ### Overview
331
- Broadcast intents allow system-wide or app-wide messaging. Apps can send broadcasts and register receivers to listen for them.
332
-
333
- ### System broadcasts
334
-
335
- Common system broadcasts:
336
- - `android.intent.action.BATTERY_LOW` - battery low warning
337
- - `android.intent.action.BATTERY_CHANGED` - battery status changed
338
- - `android.intent.action.ACTION_POWER_CONNECTED` - power connected
339
- - `android.intent.action.ACTION_POWER_DISCONNECTED` - power disconnected
340
- - `android.intent.action.BOOT_COMPLETED` - system boot completed
341
- - `android.net.conn.CONNECTIVITY_CHANGE` - network connection changed
342
- - `android.intent.action.USER_PRESENT` - user unlocked device
343
- - `android.intent.action.PACKAGE_INSTALL` / `PACKAGE_REMOVED` - package changes
344
-
345
- ### Registering broadcast receivers
346
-
347
- #### Dynamic registration (in code)
348
-
349
- ```javascript
350
- // Create receiver
351
- const batteryReceiver = Ti.Android.createBroadcastReceiver({
352
- onReceived: (e) => {
353
- const level = e.intent.getIntExtra(Ti.Android.EXTRA_BATTERY_LEVEL, -1);
354
- Ti.API.info(`Battery level: ${level}%`);
355
-
356
- if (level < 20) {
357
- showLowBatteryWarning();
358
- }
359
- }
360
- });
361
-
362
- // Register for battery low
363
- Ti.Android.registerBroadcastReceiver(batteryReceiver, [
364
- Ti.Android.ACTION_BATTERY_LOW
365
- ]);
366
-
367
- // Later: unregister when no longer needed
368
- Ti.Android.unregisterBroadcastReceiver(batteryReceiver);
369
- ```
370
-
371
- #### Network change listener
372
-
373
- ```javascript
374
- const networkReceiver = Ti.Android.createBroadcastReceiver({
375
- onReceived: (e) => {
376
- const connectivityManager = Ti.Android.getSystemService(
377
- Ti.Android.CONNECTIVITY_SERVICE
378
- );
379
- const networkInfo = connectivityManager.getActiveNetworkInfo();
380
-
381
- if (networkInfo && networkInfo.isConnected()) {
382
- Ti.API.info(`Network connected: ${networkInfo.getTypeName()}`);
383
- // Retry pending operations
384
- } else {
385
- Ti.API.info('Network disconnected');
386
- // Show offline mode
387
- }
388
- }
389
- });
390
-
391
- Ti.Android.registerBroadcastReceiver(networkReceiver, [
392
- 'android.net.conn.CONNECTIVITY_CHANGE'
393
- ]);
394
- ```
395
-
396
- ### Sending custom broadcasts
397
-
398
- ```javascript
399
- // Send broadcast within your app
400
- const intent = Ti.Android.createIntent({
401
- action: 'com.myapp.CUSTOM_EVENT'
402
- });
403
- intent.putExtra('data', 'Custom data here');
404
- Ti.Android.currentActivity.sendBroadcast(intent);
405
- ```
406
-
407
- #### Receiver for custom broadcast
408
-
409
- ```javascript
410
- const customReceiver = Ti.Android.createBroadcastReceiver({
411
- onReceived: (e) => {
412
- const data = e.intent.getStringExtra('data');
413
- Ti.API.info(`Received custom event: ${data}`);
414
- }
415
- });
416
-
417
- Ti.Android.registerBroadcastReceiver(customReceiver, [
418
- 'com.myapp.CUSTOM_EVENT'
419
- ]);
420
- ```
421
-
422
- ### Boot receiver
423
-
424
- In `tiapp.xml`:
425
- ```xml
426
- <android>
427
- <manifest>
428
- <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
429
- <application>
430
- <receiver
431
- android:name="com.myapp.BootReceiver"
432
- android:enabled="true">
433
- <intent-filter>
434
- <action android:name="android.intent.action.BOOT_COMPLETED"/>
435
- </intent-filter>
436
- </receiver>
437
- </application>
438
- </manifest>
439
- </android>
440
- ```
441
-
442
- ## 7. Android services
443
-
444
- ### Overview
445
- Services are background components that run independently of the UI. Useful for long-running operations like music playback, location tracking, or network polling.
446
-
447
- ### Service types
448
-
449
- 1. Regular service: runs in background until stopped
450
- 2. IntentService: queues work requests and processes sequentially
451
- 3. Foreground service: shows persistent notification, higher priority
452
-
453
- ### Creating a service
454
-
455
- ```javascript
456
- // Create service
457
- const service = Ti.Android.createService({
458
- url: 'myservice.js',
459
- interval: 60000 // Check every 60 seconds
460
- });
461
-
462
- // Start service
463
- service.start();
464
-
465
- // Stop service when done
466
- service.stop();
467
- ```
468
-
469
- `myservice.js`:
470
- ```javascript
471
- Ti.API.info('Service running');
472
-
473
- // Perform work
474
- const xhr = Ti.Network.createHTTPClient({
475
- onload: () => {
476
- Ti.API.info('Data updated');
477
- // Send notification if needed
478
- }
479
- });
480
- xhr.open('GET', 'https://api.example.com/update');
481
- xhr.send();
482
- ```
483
-
484
- ### IntentService
485
-
486
- For one-off or queued work:
487
-
488
- ```javascript
489
- const intent = Ti.Android.createServiceIntent({
490
- url: 'backgroundtask.js'
491
- });
492
-
493
- // Start service (runs once and stops)
494
- Ti.Android.startService(intent);
495
- ```
496
-
497
- `backgroundtask.js`:
498
- ```javascript
499
- // Do work
500
- const result = processHeavyTask();
501
-
502
- // Optionally send result back to activity
503
- const broadcast = Ti.Android.createBroadcastReceiver({
504
- onReceived: () => { /* ... */ }
505
- });
506
- // ...
507
- ```
508
-
509
- ### Foreground service
510
-
511
- For critical, long-running operations (must show notification):
512
-
513
- ```javascript
514
- const notification = Ti.Android.createNotification({
515
- contentTitle: 'Service Running',
516
- contentText: 'Tracking location...',
517
- tickerText: 'Service started',
518
- icon: Ti.App.Android.R.drawable.app_icon
519
- });
520
-
521
- const intent = Ti.Android.createServiceIntent({
522
- url: 'trackingservice.js'
523
- });
524
-
525
- intent.addFlags(Ti.Android.FLAG_ACTIVITY_CLEAR_TOP);
526
- intent.addCategory(Ti.Android.CATEGORY_LAUNCHER);
527
-
528
- // Start as foreground service
529
- Ti.Android.startForegroundService(intent, 101, notification);
530
- ```
531
-
532
- To stop:
533
- ```javascript
534
- Ti.Android.stopForegroundService(intent);
535
- ```
536
-
537
- ### Service lifecycle management
538
-
539
- Important: always stop services when no longer needed to conserve resources.
540
-
541
- ```javascript
542
- // In activity
543
- Ti.Android.currentActivity.addEventListener('pause', () => {
544
- // Optionally pause service
545
- });
546
-
547
- Ti.Android.currentActivity.addEventListener('destroy', () => {
548
- // Always stop service
549
- if (service) {
550
- service.stop();
551
- service = null;
552
- }
553
- });
554
- ```
555
-
556
- ### Inter-service communication
557
-
558
- ```javascript
559
- // From activity to service
560
- const intent = Ti.Android.createServiceIntent({
561
- url: 'myservice.js'
562
- });
563
- intent.putExtra('command', 'pause');
564
- Ti.Android.startService(intent);
565
-
566
- // In service
567
- const command = intent.getStringExtra('command');
568
- if (command === 'pause') {
569
- // Handle pause command
570
- }
571
- ```
572
-
573
- ## 8. Android permissions
574
-
575
- ### Runtime permissions (Android 6.0+)
576
-
577
- Dangerous permissions require a runtime request:
578
-
579
- ```javascript
580
- function checkPermission() {
581
- const result = Ti.Android.checkSelfPermission(
582
- Ti.Android.PERMISSION_ACCESS_FINE_LOCATION
583
- );
584
-
585
- if (result === Ti.Android.RESULTS.GRANTED) {
586
- startLocationTracking();
587
- } else {
588
- Ti.Android.requestPermissions(
589
- [Ti.Android.PERMISSION_ACCESS_FINE_LOCATION],
590
- 999, // Request code
591
- (e) => {
592
- if (e.granted[0] === true) {
593
- startLocationTracking();
594
- } else {
595
- alert('Location permission denied');
596
- }
597
- }
598
- );
599
- }
600
- }
601
-
602
- checkPermission();
603
- ```
604
-
605
- ### Common dangerous permissions
606
- - `ACCESS_FINE_LOCATION` - GPS location
607
- - `ACCESS_COARSE_LOCATION` - network location
608
- - `CAMERA` - camera access
609
- - `READ_EXTERNAL_STORAGE` - read files
610
- - `WRITE_EXTERNAL_STORAGE` - write files
611
- - `RECORD_AUDIO` - microphone
612
- - `CALL_PHONE` - make phone calls
613
- - `SEND_SMS` / `READ_SMS` - SMS access
614
-
615
- ## Best practices
616
-
617
- 1. Always unregister broadcast receivers when no longer needed.
618
- 2. Stop services explicitly to conserve battery.
619
- 3. Use IntentService for one-off background tasks.
620
- 4. Use foreground services for user-visible long operations.
621
- 5. Handle runtime permissions gracefully on Android 6.0+.
622
- 6. Validate intent data before processing.
623
- 7. Use proper intent flags for navigation behavior.
624
- 8. Test intent filters with ADB: `adb shell am start -W -a android.intent.action.VIEW -d "myapp://path"`.
@@ -1,96 +0,0 @@
1
- # Automation with Fastlane and Appium
2
-
3
- Guide to setting up CI pipelines, automated testing, and deployment for Titanium.
4
-
5
- ## 1. UI testing with Appium
6
-
7
- Appium supports automated functional testing on real devices and simulators.
8
-
9
- ### Prerequisites
10
- - Appium Desktop or CLI
11
- - Mocha (test runner)
12
- - WebdriverIO (recommended client)
13
-
14
- ### Test example (Mocha + WebdriverIO)
15
- ```javascript
16
- const opts = {
17
- port: 4723,
18
- capabilities: {
19
- platformName: 'iOS',
20
- deviceName: 'iPhone 15',
21
- app: '/path/to/your/app.app',
22
- automationName: 'XCUITest'
23
- }
24
- };
25
-
26
- describe('Login Test', () => {
27
- it('Should login with valid credentials', async () => {
28
- const client = await wdio.remote(opts);
29
- const userField = await client.$('~Enter Username'); // Use Accessibility ID
30
- await userField.setValue('my_user');
31
- await client.deleteSession();
32
- });
33
- });
34
- ```
35
-
36
- ## 2. Automation with Fastlane
37
-
38
- Fastlane automates building, signing, and uploading to the stores.
39
-
40
- ### Titanium plugins
41
- Install project plugins:
42
- ```bash
43
- fastlane add_plugin ti_build_app
44
- fastlane add_plugin mocha_run_tests
45
- ```
46
-
47
- ### Fastfile configuration
48
- Create `fastlane/Fastfile` in the root:
49
-
50
- ```ruby
51
- platform :ios do
52
- desc "Build for Simulator Tests"
53
- lane :build_test do
54
- ti_build_app(
55
- appc_cli: "ti build -p ios -T simulator --build-only"
56
- )
57
- end
58
-
59
- desc "Run UI Tests"
60
- lane :test do
61
- build_test
62
- mocha_run_tests(
63
- mocha_js_file_name: 'tests/login_test.js'
64
- )
65
- end
66
-
67
- desc "Deploy to TestFlight"
68
- lane :release do
69
- ti_build_app(
70
- appc_cli: "ti build -p ios -T dist-appstore --distribution-name 'Your Company' --pp-uuid 'UUID-HERE' --output-dir /dist"
71
- )
72
- # Add fastlane pilot command here to upload the .ipa
73
- end
74
- end
75
- ```
76
-
77
- ## 3. CI/CD best practices
78
- 1. Accessibility IDs: assign `accessibilityLabel` in XML/TSS so Appium can find elements reliably.
79
- 2. Environment lanes: define separate lanes for `beta`, `production`, and `test`.
80
- 3. Profile management: use Fastlane Match to sync certs and provisioning profiles across the team.
81
- 4. Snapshots: use Fastlane `snapshot` to automate App Store screenshot generation.
82
-
83
- ## 4. Unit testing with TiUnit
84
-
85
- For non-UI tests, consider TiUnit (Jasmine-based):
86
- - Runs tests inside the app context
87
- - Supports standard Jasmine `describe`/`it`/`expect` syntax
88
- - Integrates cleanly into CI pipelines
89
-
90
- ## 5. Broader CI/CD options
91
-
92
- Beyond Fastlane and Appium, Titanium apps can integrate with:
93
- - Jenkins for build orchestration and pipeline management
94
- - SonarQube for code quality analysis
95
- - AWS Device Farm for testing on real devices in the cloud
96
- - Nexus/Artifactory for build artifact archiving and versioning