@maccesar/titools 2.2.3 → 2.2.8
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 +28 -27
- package/lib/commands/update.js +80 -101
- package/package.json +1 -1
- package/skills/alloy-guides/SKILL.md +31 -31
- package/skills/alloy-guides/references/CONCEPTS.md +3 -3
- package/skills/alloy-guides/references/CONTROLLERS.md +1 -1
- package/skills/alloy-guides/references/MODELS.md +6 -6
- package/skills/alloy-guides/references/VIEWS_WITHOUT_CONTROLLERS.md +1 -1
- package/skills/alloy-guides/references/VIEWS_XML.md +1 -1
- package/skills/alloy-guides/references/WIDGETS.md +1 -1
- package/skills/alloy-howtos/SKILL.md +27 -27
- package/skills/alloy-howtos/references/best_practices.md +9 -9
- package/skills/alloy-howtos/references/cli_reference.md +14 -14
- package/skills/alloy-howtos/references/config_files.md +16 -16
- package/skills/alloy-howtos/references/custom_tags.md +16 -16
- package/skills/alloy-howtos/references/debugging_troubleshooting.md +11 -15
- package/skills/alloy-howtos/references/samples.md +19 -19
- package/skills/purgetss/SKILL.md +11 -1
- package/skills/purgetss/references/animation-system.md +1 -1
- package/skills/purgetss/references/cli-commands.md +3 -3
- package/skills/purgetss/references/customization-deep-dive.md +1 -1
- package/skills/purgetss/references/dynamic-component-creation.md +1 -1
- package/skills/purgetss/references/icon-fonts.md +4 -0
- package/skills/purgetss/references/installation-setup.md +8 -1
- package/skills/purgetss/references/migration-guide.md +4 -0
- package/skills/purgetss/references/tikit-components.md +193 -204
- package/skills/purgetss/references/ui-ux-design.md +1 -1
- package/skills/ti-expert/SKILL.md +78 -118
- package/skills/ti-expert/references/alloy-builtins.md +18 -18
- package/skills/ti-expert/references/alloy-structure.md +21 -21
- package/skills/ti-expert/references/anti-patterns.md +15 -15
- package/skills/ti-expert/references/cli-expert.md +15 -15
- package/skills/ti-expert/references/code-conventions.md +38 -38
- package/skills/ti-expert/references/contracts.md +8 -8
- package/skills/ti-expert/references/controller-patterns.md +14 -14
- package/skills/ti-expert/references/error-handling.md +11 -11
- package/skills/ti-expert/references/examples.md +12 -12
- package/skills/ti-expert/references/migration-patterns.md +24 -24
- package/skills/ti-expert/references/patterns.md +10 -10
- package/skills/ti-expert/references/performance-listview.md +16 -16
- package/skills/ti-expert/references/performance-optimization.md +41 -41
- package/skills/ti-expert/references/security-device.md +22 -22
- package/skills/ti-expert/references/security-fundamentals.md +19 -19
- package/skills/ti-expert/references/state-management.md +33 -33
- package/skills/ti-expert/references/testing-e2e-ci.md +25 -25
- package/skills/ti-expert/references/testing-unit.md +24 -24
- package/skills/ti-expert/references/theming.md +15 -15
- package/skills/ti-guides/SKILL.md +58 -60
- package/skills/ti-guides/references/advanced-data-and-images.md +33 -33
- package/skills/ti-guides/references/android-manifest.md +15 -15
- package/skills/ti-guides/references/app-distribution.md +70 -166
- package/skills/ti-guides/references/application-frameworks.md +96 -114
- package/skills/ti-guides/references/cli-reference.md +294 -294
- package/skills/ti-guides/references/coding-best-practices.md +42 -33
- package/skills/ti-guides/references/commonjs-advanced.md +57 -51
- package/skills/ti-guides/references/hello-world.md +36 -36
- package/skills/ti-guides/references/hyperloop-native-access.md +66 -66
- package/skills/ti-guides/references/javascript-primer.md +83 -101
- package/skills/ti-guides/references/reserved-words.md +9 -9
- package/skills/ti-guides/references/resources.md +75 -83
- package/skills/ti-guides/references/style-and-conventions.md +35 -28
- package/skills/ti-guides/references/tiapp-config.md +110 -74
- package/skills/ti-howtos/SKILL.md +88 -92
- package/skills/ti-howtos/references/android-platform-deep-dives.md +104 -104
- package/skills/ti-howtos/references/automation-fastlane-appium.md +39 -39
- package/skills/ti-howtos/references/buffer-codec-streams.md +60 -60
- package/skills/ti-howtos/references/cross-platform-development.md +115 -136
- package/skills/ti-howtos/references/debugging-profiling.md +167 -181
- package/skills/ti-howtos/references/extending-titanium.md +121 -121
- package/skills/ti-howtos/references/google-maps-v2.md +84 -82
- package/skills/ti-howtos/references/ios-map-kit.md +65 -60
- package/skills/ti-howtos/references/ios-platform-deep-dives.md +123 -123
- package/skills/ti-howtos/references/local-data-sources.md +79 -78
- package/skills/ti-howtos/references/location-and-maps.md +116 -120
- package/skills/ti-howtos/references/media-apis.md +87 -86
- package/skills/ti-howtos/references/notification-services.md +250 -260
- package/skills/ti-howtos/references/remote-data-sources.md +98 -93
- package/skills/ti-howtos/references/tutorials.md +226 -216
- package/skills/ti-howtos/references/using-modules.md +73 -102
- package/skills/ti-howtos/references/web-content-integration.md +101 -103
- package/skills/ti-howtos/references/webpack-build-pipeline.md +52 -44
- package/skills/ti-ui/SKILL.md +85 -85
- package/skills/ti-ui/references/accessibility-deep-dive.md +57 -57
- package/skills/ti-ui/references/animation-and-matrices.md +79 -79
- package/skills/ti-ui/references/application-structures.md +96 -99
- package/skills/ti-ui/references/custom-fonts-styling.md +99 -99
- package/skills/ti-ui/references/event-handling.md +58 -58
- package/skills/ti-ui/references/gestures.md +62 -64
- package/skills/ti-ui/references/icons-and-splash-screens.md +88 -88
- package/skills/ti-ui/references/layouts-and-positioning.md +87 -97
- package/skills/ti-ui/references/listviews-and-performance.md +107 -107
- package/skills/ti-ui/references/orientation.md +87 -88
- package/skills/ti-ui/references/platform-ui-android.md +87 -81
- package/skills/ti-ui/references/platform-ui-ios.md +63 -61
- package/skills/ti-ui/references/scrolling-views.md +29 -29
- package/skills/ti-ui/references/tableviews.md +56 -56
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
# Android
|
|
1
|
+
# Android platform deep dives
|
|
2
2
|
|
|
3
|
-
## 1. Android
|
|
3
|
+
## 1. Android intent filters (advanced)
|
|
4
4
|
|
|
5
|
-
To
|
|
5
|
+
To receive implicit intents (for example, opening a PDF file or a web link), register a filter in the manifest.
|
|
6
6
|
|
|
7
|
-
### Critical
|
|
8
|
-
Before declaring an `intent-filter`,
|
|
7
|
+
### Critical step: copy root activity
|
|
8
|
+
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`:
|
|
9
9
|
|
|
10
10
|
```xml
|
|
11
11
|
<android xmlns:android="http://schemas.android.com/apk/res/android">
|
|
@@ -30,28 +30,28 @@ Before declaring an `intent-filter`, you must copy the `<activity>` node of your
|
|
|
30
30
|
</android>
|
|
31
31
|
```
|
|
32
32
|
|
|
33
|
-
### Retrieving
|
|
33
|
+
### Retrieving intent data
|
|
34
34
|
```javascript
|
|
35
35
|
const intent = Ti.Android.currentActivity.getIntent();
|
|
36
36
|
if (intent.hasExtra(Ti.Android.EXTRA_TEXT)) {
|
|
37
|
-
|
|
37
|
+
const sharedText = intent.getStringExtra(Ti.Android.EXTRA_TEXT);
|
|
38
38
|
}
|
|
39
39
|
```
|
|
40
40
|
|
|
41
|
-
## 2. Broadcast
|
|
41
|
+
## 2. Broadcast intents with permissions
|
|
42
42
|
|
|
43
|
-
You can restrict
|
|
43
|
+
You can restrict which apps receive your broadcast messages.
|
|
44
44
|
|
|
45
|
-
### Sending with
|
|
45
|
+
### Sending with permission
|
|
46
46
|
```javascript
|
|
47
47
|
const intent = Ti.Android.createBroadcastIntent({
|
|
48
|
-
|
|
48
|
+
action: 'com.mycompany.SECURE_ACTION'
|
|
49
49
|
});
|
|
50
50
|
// Only apps with the permission 'com.mycompany.SPECIAL_PERMISSION' will receive it
|
|
51
51
|
Ti.Android.currentActivity.sendBroadcastWithPermission(intent, 'com.mycompany.SPECIAL_PERMISSION');
|
|
52
52
|
```
|
|
53
53
|
|
|
54
|
-
### Declaring
|
|
54
|
+
### Declaring permission in tiapp.xml
|
|
55
55
|
```xml
|
|
56
56
|
<android>
|
|
57
57
|
<manifest>
|
|
@@ -63,36 +63,36 @@ Ti.Android.currentActivity.sendBroadcastWithPermission(intent, 'com.mycompany.SP
|
|
|
63
63
|
|
|
64
64
|
## 3. FusedLocationProvider (TiSDK 7.1.0+)
|
|
65
65
|
|
|
66
|
-
For battery-efficient location tracking on Android, use the
|
|
66
|
+
For battery-efficient location tracking on Android, use the fused provider.
|
|
67
67
|
|
|
68
|
-
|
|
68
|
+
Requirement: include the `ti.playservices` module in your project.
|
|
69
69
|
```xml
|
|
70
70
|
<module platform="android">ti.playservices</module>
|
|
71
71
|
```
|
|
72
|
-
Titanium will
|
|
72
|
+
Titanium will switch to Google Play Services for geolocation, which reduces power consumption.
|
|
73
73
|
|
|
74
|
-
## 4. Android
|
|
74
|
+
## 4. Android intents
|
|
75
75
|
|
|
76
76
|
### Overview
|
|
77
77
|
Intents are message objects that specify actions to perform. They can start activities, broadcasts, or services.
|
|
78
78
|
|
|
79
|
-
### Intent
|
|
80
|
-
-
|
|
81
|
-
-
|
|
82
|
-
-
|
|
83
|
-
-
|
|
84
|
-
-
|
|
79
|
+
### Intent structure
|
|
80
|
+
- Action: what to do (for example, `ACTION_VIEW`, `ACTION_SEND`)
|
|
81
|
+
- Data: URI the intent operates on (URL, file path)
|
|
82
|
+
- Type: MIME type of data
|
|
83
|
+
- Category: additional categorization
|
|
84
|
+
- Extras: key-value pairs for additional data
|
|
85
85
|
|
|
86
|
-
### Creating
|
|
86
|
+
### Creating intents
|
|
87
87
|
|
|
88
|
-
#### Simple
|
|
88
|
+
#### Simple intent (action only)
|
|
89
89
|
```javascript
|
|
90
90
|
const intent = Ti.Android.createIntent({
|
|
91
91
|
action: Ti.Android.ACTION_VIEW
|
|
92
92
|
});
|
|
93
93
|
```
|
|
94
94
|
|
|
95
|
-
#### Intent with
|
|
95
|
+
#### Intent with action and data
|
|
96
96
|
```javascript
|
|
97
97
|
const intent = Ti.Android.createIntent({
|
|
98
98
|
action: Ti.Android.ACTION_VIEW,
|
|
@@ -101,7 +101,7 @@ const intent = Ti.Android.createIntent({
|
|
|
101
101
|
Ti.Android.currentActivity.startActivity(intent);
|
|
102
102
|
```
|
|
103
103
|
|
|
104
|
-
#### Intent with
|
|
104
|
+
#### Intent with extras
|
|
105
105
|
```javascript
|
|
106
106
|
const intent = Ti.Android.createIntent({
|
|
107
107
|
action: 'com.example.MY_ACTION',
|
|
@@ -111,9 +111,9 @@ intent.putExtra('message', 'Hello from Titanium');
|
|
|
111
111
|
intent.putExtra('count', 42);
|
|
112
112
|
```
|
|
113
113
|
|
|
114
|
-
### Common
|
|
114
|
+
### Common use cases
|
|
115
115
|
|
|
116
|
-
#### Open URL in
|
|
116
|
+
#### Open URL in browser
|
|
117
117
|
```javascript
|
|
118
118
|
const intent = Ti.Android.createIntent({
|
|
119
119
|
action: Ti.Android.ACTION_VIEW,
|
|
@@ -122,7 +122,7 @@ const intent = Ti.Android.createIntent({
|
|
|
122
122
|
Ti.Android.currentActivity.startActivity(intent);
|
|
123
123
|
```
|
|
124
124
|
|
|
125
|
-
#### Dial
|
|
125
|
+
#### Dial phone number
|
|
126
126
|
```javascript
|
|
127
127
|
const intent = Ti.Android.createIntent({
|
|
128
128
|
action: Ti.Android.ACTION_DIAL,
|
|
@@ -131,7 +131,7 @@ const intent = Ti.Android.createIntent({
|
|
|
131
131
|
Ti.Android.currentActivity.startActivity(intent);
|
|
132
132
|
```
|
|
133
133
|
|
|
134
|
-
#### Send
|
|
134
|
+
#### Send email
|
|
135
135
|
```javascript
|
|
136
136
|
const intent = Ti.Android.createIntent({
|
|
137
137
|
action: Ti.Android.ACTION_SENDTO,
|
|
@@ -142,7 +142,7 @@ intent.putExtra(Ti.Android.EXTRA_TEXT, 'Email body');
|
|
|
142
142
|
Ti.Android.currentActivity.startActivity(intent);
|
|
143
143
|
```
|
|
144
144
|
|
|
145
|
-
#### Share
|
|
145
|
+
#### Share content
|
|
146
146
|
```javascript
|
|
147
147
|
const intent = Ti.Android.createIntent({
|
|
148
148
|
action: Ti.Android.ACTION_SEND,
|
|
@@ -152,18 +152,18 @@ intent.putExtra(Ti.Android.EXTRA_TEXT, 'Check this out!');
|
|
|
152
152
|
Ti.Android.currentActivity.startActivity(intent);
|
|
153
153
|
```
|
|
154
154
|
|
|
155
|
-
#### Open PDF
|
|
155
|
+
#### Open PDF file
|
|
156
156
|
```javascript
|
|
157
157
|
const intent = Ti.Android.createIntent({
|
|
158
158
|
action: Ti.Android.ACTION_VIEW,
|
|
159
159
|
type: 'application/pdf',
|
|
160
|
-
data: file.nativePath
|
|
160
|
+
data: file.nativePath // Ti.Filesystem.File object
|
|
161
161
|
});
|
|
162
162
|
intent.addFlags(Ti.Android.FLAG_GRANT_READ_URI_PERMISSION);
|
|
163
163
|
Ti.Android.currentActivity.startActivity(intent);
|
|
164
164
|
```
|
|
165
165
|
|
|
166
|
-
### Starting
|
|
166
|
+
### Starting other apps
|
|
167
167
|
```javascript
|
|
168
168
|
// Open specific app by package name
|
|
169
169
|
const intent = Ti.Android.createIntent({
|
|
@@ -178,40 +178,40 @@ try {
|
|
|
178
178
|
}
|
|
179
179
|
```
|
|
180
180
|
|
|
181
|
-
### Intent
|
|
181
|
+
### Intent chooser
|
|
182
182
|
Force the system to show an app chooser dialog (even if a default is set):
|
|
183
183
|
```javascript
|
|
184
184
|
const intent = Ti.Android.createIntent({
|
|
185
|
-
|
|
186
|
-
|
|
185
|
+
action: Ti.Android.ACTION_SEND,
|
|
186
|
+
type: 'text/plain'
|
|
187
187
|
});
|
|
188
188
|
intent.putExtra(Ti.Android.EXTRA_TEXT, 'Share this text');
|
|
189
189
|
|
|
190
190
|
Ti.Android.currentActivity.startActivity(
|
|
191
|
-
|
|
191
|
+
Ti.Android.createIntentChooser(intent, 'Share via...')
|
|
192
192
|
);
|
|
193
193
|
```
|
|
194
194
|
|
|
195
|
-
### Getting
|
|
195
|
+
### Getting results from activities
|
|
196
196
|
```javascript
|
|
197
197
|
const intent = Ti.Android.createIntent({
|
|
198
|
-
|
|
198
|
+
action: 'android.media.action.IMAGE_CAPTURE'
|
|
199
199
|
});
|
|
200
200
|
|
|
201
201
|
Ti.Android.currentActivity.startActivityForResult(intent, (e) => {
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
202
|
+
if (e.resultCode === Ti.Android.RESULT_OK) {
|
|
203
|
+
const imageUri = e.intent.data;
|
|
204
|
+
Ti.API.info(`Captured image: ${imageUri}`);
|
|
205
|
+
} else if (e.resultCode === Ti.Android.RESULT_CANCELED) {
|
|
206
|
+
Ti.API.info('User canceled');
|
|
207
|
+
}
|
|
208
208
|
});
|
|
209
209
|
```
|
|
210
210
|
|
|
211
|
-
## 5. Intent
|
|
211
|
+
## 5. Intent filters
|
|
212
212
|
|
|
213
213
|
### Overview
|
|
214
|
-
Intent
|
|
214
|
+
Intent filters advertise your app's capability to handle certain actions and data types. They enable deep linking, file handling, and inter-app communication.
|
|
215
215
|
|
|
216
216
|
### Configuring in tiapp.xml
|
|
217
217
|
|
|
@@ -247,9 +247,9 @@ Intent Filters advertise your app's capability to handle certain actions and dat
|
|
|
247
247
|
</android>
|
|
248
248
|
```
|
|
249
249
|
|
|
250
|
-
### Handling
|
|
250
|
+
### Handling incoming intents
|
|
251
251
|
|
|
252
|
-
#### Get
|
|
252
|
+
#### Get intent data on startup
|
|
253
253
|
```javascript
|
|
254
254
|
const activity = Ti.Android.currentActivity;
|
|
255
255
|
const intent = activity.getIntent();
|
|
@@ -269,7 +269,7 @@ if (intent) {
|
|
|
269
269
|
}
|
|
270
270
|
```
|
|
271
271
|
|
|
272
|
-
#### Listen for
|
|
272
|
+
#### Listen for new intents (activity restart)
|
|
273
273
|
```javascript
|
|
274
274
|
Ti.Android.currentActivity.addEventListener('newintent', (e) => {
|
|
275
275
|
const intent = e.intent;
|
|
@@ -281,7 +281,7 @@ Ti.Android.currentActivity.addEventListener('newintent', (e) => {
|
|
|
281
281
|
});
|
|
282
282
|
```
|
|
283
283
|
|
|
284
|
-
### Deep
|
|
284
|
+
### Deep linking example
|
|
285
285
|
|
|
286
286
|
```xml
|
|
287
287
|
<!-- In tiapp.xml -->
|
|
@@ -310,26 +310,26 @@ if (intent && intent.getData()) {
|
|
|
310
310
|
}
|
|
311
311
|
```
|
|
312
312
|
|
|
313
|
-
## 6. Broadcast
|
|
313
|
+
## 6. Broadcast intents and receivers
|
|
314
314
|
|
|
315
315
|
### Overview
|
|
316
|
-
Broadcast
|
|
316
|
+
Broadcast intents allow system-wide or app-wide messaging. Apps can send broadcasts and register receivers to listen for them.
|
|
317
317
|
|
|
318
|
-
### System
|
|
318
|
+
### System broadcasts
|
|
319
319
|
|
|
320
320
|
Common system broadcasts:
|
|
321
|
-
- `android.intent.action.BATTERY_LOW` -
|
|
322
|
-
- `android.intent.action.BATTERY_CHANGED` -
|
|
323
|
-
- `android.intent.action.ACTION_POWER_CONNECTED` -
|
|
324
|
-
- `android.intent.action.ACTION_POWER_DISCONNECTED` -
|
|
325
|
-
- `android.intent.action.BOOT_COMPLETED` -
|
|
326
|
-
- `android.net.conn.CONNECTIVITY_CHANGE` -
|
|
327
|
-
- `android.intent.action.USER_PRESENT` -
|
|
328
|
-
- `android.intent.action.PACKAGE_INSTALL` / `PACKAGE_REMOVED` -
|
|
321
|
+
- `android.intent.action.BATTERY_LOW` - battery low warning
|
|
322
|
+
- `android.intent.action.BATTERY_CHANGED` - battery status changed
|
|
323
|
+
- `android.intent.action.ACTION_POWER_CONNECTED` - power connected
|
|
324
|
+
- `android.intent.action.ACTION_POWER_DISCONNECTED` - power disconnected
|
|
325
|
+
- `android.intent.action.BOOT_COMPLETED` - system boot completed
|
|
326
|
+
- `android.net.conn.CONNECTIVITY_CHANGE` - network connection changed
|
|
327
|
+
- `android.intent.action.USER_PRESENT` - user unlocked device
|
|
328
|
+
- `android.intent.action.PACKAGE_INSTALL` / `PACKAGE_REMOVED` - package changes
|
|
329
329
|
|
|
330
|
-
### Registering
|
|
330
|
+
### Registering broadcast receivers
|
|
331
331
|
|
|
332
|
-
#### Dynamic
|
|
332
|
+
#### Dynamic registration (in code)
|
|
333
333
|
|
|
334
334
|
```javascript
|
|
335
335
|
// Create receiver
|
|
@@ -349,11 +349,11 @@ Ti.Android.registerBroadcastReceiver(batteryReceiver, [
|
|
|
349
349
|
Ti.Android.ACTION_BATTERY_LOW
|
|
350
350
|
]);
|
|
351
351
|
|
|
352
|
-
// Later:
|
|
352
|
+
// Later: unregister when no longer needed
|
|
353
353
|
Ti.Android.unregisterBroadcastReceiver(batteryReceiver);
|
|
354
354
|
```
|
|
355
355
|
|
|
356
|
-
#### Network
|
|
356
|
+
#### Network change listener
|
|
357
357
|
|
|
358
358
|
```javascript
|
|
359
359
|
const networkReceiver = Ti.Android.createBroadcastReceiver({
|
|
@@ -378,7 +378,7 @@ Ti.Android.registerBroadcastReceiver(networkReceiver, [
|
|
|
378
378
|
]);
|
|
379
379
|
```
|
|
380
380
|
|
|
381
|
-
### Sending
|
|
381
|
+
### Sending custom broadcasts
|
|
382
382
|
|
|
383
383
|
```javascript
|
|
384
384
|
// Send broadcast within your app
|
|
@@ -389,7 +389,7 @@ intent.putExtra('data', 'Custom data here');
|
|
|
389
389
|
Ti.Android.currentActivity.sendBroadcast(intent);
|
|
390
390
|
```
|
|
391
391
|
|
|
392
|
-
#### Receiver for
|
|
392
|
+
#### Receiver for custom broadcast
|
|
393
393
|
|
|
394
394
|
```javascript
|
|
395
395
|
const customReceiver = Ti.Android.createBroadcastReceiver({
|
|
@@ -404,9 +404,9 @@ Ti.Android.registerBroadcastReceiver(customReceiver, [
|
|
|
404
404
|
]);
|
|
405
405
|
```
|
|
406
406
|
|
|
407
|
-
### Boot
|
|
407
|
+
### Boot receiver
|
|
408
408
|
|
|
409
|
-
|
|
409
|
+
In `tiapp.xml`:
|
|
410
410
|
```xml
|
|
411
411
|
<android>
|
|
412
412
|
<manifest>
|
|
@@ -424,24 +424,24 @@ Ti.Android.registerBroadcastReceiver(customReceiver, [
|
|
|
424
424
|
</android>
|
|
425
425
|
```
|
|
426
426
|
|
|
427
|
-
## 7. Android
|
|
427
|
+
## 7. Android services
|
|
428
428
|
|
|
429
429
|
### Overview
|
|
430
430
|
Services are background components that run independently of the UI. Useful for long-running operations like music playback, location tracking, or network polling.
|
|
431
431
|
|
|
432
|
-
### Service
|
|
432
|
+
### Service types
|
|
433
433
|
|
|
434
|
-
1.
|
|
435
|
-
2.
|
|
436
|
-
3.
|
|
434
|
+
1. Regular service: runs in background until stopped
|
|
435
|
+
2. IntentService: queues work requests and processes sequentially
|
|
436
|
+
3. Foreground service: shows persistent notification, higher priority
|
|
437
437
|
|
|
438
|
-
### Creating a
|
|
438
|
+
### Creating a service
|
|
439
439
|
|
|
440
440
|
```javascript
|
|
441
441
|
// Create service
|
|
442
442
|
const service = Ti.Android.createService({
|
|
443
443
|
url: 'myservice.js',
|
|
444
|
-
interval: 60000
|
|
444
|
+
interval: 60000 // Check every 60 seconds
|
|
445
445
|
});
|
|
446
446
|
|
|
447
447
|
// Start service
|
|
@@ -451,7 +451,7 @@ service.start();
|
|
|
451
451
|
service.stop();
|
|
452
452
|
```
|
|
453
453
|
|
|
454
|
-
|
|
454
|
+
`myservice.js`:
|
|
455
455
|
```javascript
|
|
456
456
|
Ti.API.info('Service running');
|
|
457
457
|
|
|
@@ -479,7 +479,7 @@ const intent = Ti.Android.createServiceIntent({
|
|
|
479
479
|
Ti.Android.startService(intent);
|
|
480
480
|
```
|
|
481
481
|
|
|
482
|
-
|
|
482
|
+
`backgroundtask.js`:
|
|
483
483
|
```javascript
|
|
484
484
|
// Do work
|
|
485
485
|
const result = processHeavyTask();
|
|
@@ -491,7 +491,7 @@ const broadcast = Ti.Android.createBroadcastReceiver({
|
|
|
491
491
|
// ...
|
|
492
492
|
```
|
|
493
493
|
|
|
494
|
-
### Foreground
|
|
494
|
+
### Foreground service
|
|
495
495
|
|
|
496
496
|
For critical, long-running operations (must show notification):
|
|
497
497
|
|
|
@@ -519,9 +519,9 @@ To stop:
|
|
|
519
519
|
Ti.Android.stopForegroundService(intent);
|
|
520
520
|
```
|
|
521
521
|
|
|
522
|
-
### Service
|
|
522
|
+
### Service lifecycle management
|
|
523
523
|
|
|
524
|
-
|
|
524
|
+
Important: always stop services when no longer needed to conserve resources.
|
|
525
525
|
|
|
526
526
|
```javascript
|
|
527
527
|
// In activity
|
|
@@ -538,7 +538,7 @@ Ti.Android.currentActivity.addEventListener('destroy', () => {
|
|
|
538
538
|
});
|
|
539
539
|
```
|
|
540
540
|
|
|
541
|
-
### Inter-
|
|
541
|
+
### Inter-service communication
|
|
542
542
|
|
|
543
543
|
```javascript
|
|
544
544
|
// From activity to service
|
|
@@ -555,11 +555,11 @@ if (command === 'pause') {
|
|
|
555
555
|
}
|
|
556
556
|
```
|
|
557
557
|
|
|
558
|
-
## 8. Android
|
|
558
|
+
## 8. Android permissions
|
|
559
559
|
|
|
560
|
-
### Runtime
|
|
560
|
+
### Runtime permissions (Android 6.0+)
|
|
561
561
|
|
|
562
|
-
Dangerous permissions require runtime request:
|
|
562
|
+
Dangerous permissions require a runtime request:
|
|
563
563
|
|
|
564
564
|
```javascript
|
|
565
565
|
function checkPermission() {
|
|
@@ -572,7 +572,7 @@ function checkPermission() {
|
|
|
572
572
|
} else {
|
|
573
573
|
Ti.Android.requestPermissions(
|
|
574
574
|
[Ti.Android.PERMISSION_ACCESS_FINE_LOCATION],
|
|
575
|
-
999,
|
|
575
|
+
999, // Request code
|
|
576
576
|
(e) => {
|
|
577
577
|
if (e.granted[0] === true) {
|
|
578
578
|
startLocationTracking();
|
|
@@ -587,23 +587,23 @@ function checkPermission() {
|
|
|
587
587
|
checkPermission();
|
|
588
588
|
```
|
|
589
589
|
|
|
590
|
-
### Common
|
|
590
|
+
### Common dangerous permissions
|
|
591
591
|
- `ACCESS_FINE_LOCATION` - GPS location
|
|
592
|
-
- `ACCESS_COARSE_LOCATION` -
|
|
593
|
-
- `CAMERA` -
|
|
594
|
-
- `READ_EXTERNAL_STORAGE` -
|
|
595
|
-
- `WRITE_EXTERNAL_STORAGE` -
|
|
596
|
-
- `RECORD_AUDIO` -
|
|
597
|
-
- `CALL_PHONE` -
|
|
592
|
+
- `ACCESS_COARSE_LOCATION` - network location
|
|
593
|
+
- `CAMERA` - camera access
|
|
594
|
+
- `READ_EXTERNAL_STORAGE` - read files
|
|
595
|
+
- `WRITE_EXTERNAL_STORAGE` - write files
|
|
596
|
+
- `RECORD_AUDIO` - microphone
|
|
597
|
+
- `CALL_PHONE` - make phone calls
|
|
598
598
|
- `SEND_SMS` / `READ_SMS` - SMS access
|
|
599
599
|
|
|
600
|
-
## Best
|
|
600
|
+
## Best practices
|
|
601
601
|
|
|
602
|
-
1.
|
|
603
|
-
2.
|
|
604
|
-
3.
|
|
605
|
-
4.
|
|
606
|
-
5.
|
|
607
|
-
6.
|
|
608
|
-
7.
|
|
609
|
-
8.
|
|
602
|
+
1. Always unregister broadcast receivers when no longer needed.
|
|
603
|
+
2. Stop services explicitly to conserve battery.
|
|
604
|
+
3. Use IntentService for one-off background tasks.
|
|
605
|
+
4. Use foreground services for user-visible long operations.
|
|
606
|
+
5. Handle runtime permissions gracefully on Android 6.0+.
|
|
607
|
+
6. Validate intent data before processing.
|
|
608
|
+
7. Use proper intent flags for navigation behavior.
|
|
609
|
+
8. Test intent filters with ADB: `adb shell am start -W -a android.intent.action.VIEW -d "myapp://path"`.
|
|
@@ -1,51 +1,51 @@
|
|
|
1
1
|
# Automation with Fastlane and Appium
|
|
2
2
|
|
|
3
|
-
Guide
|
|
3
|
+
Guide to setting up CI pipelines, automated testing, and deployment for Titanium.
|
|
4
4
|
|
|
5
|
-
## 1. UI
|
|
5
|
+
## 1. UI testing with Appium
|
|
6
6
|
|
|
7
|
-
Appium
|
|
7
|
+
Appium supports automated functional testing on real devices and simulators.
|
|
8
8
|
|
|
9
9
|
### Prerequisites
|
|
10
|
-
-
|
|
11
|
-
-
|
|
12
|
-
-
|
|
10
|
+
- Appium Desktop or CLI
|
|
11
|
+
- Mocha (test runner)
|
|
12
|
+
- WebdriverIO (recommended client)
|
|
13
13
|
|
|
14
|
-
### Test
|
|
14
|
+
### Test example (Mocha + WebdriverIO)
|
|
15
15
|
```javascript
|
|
16
16
|
const opts = {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
17
|
+
port: 4723,
|
|
18
|
+
capabilities: {
|
|
19
|
+
platformName: 'iOS',
|
|
20
|
+
deviceName: 'iPhone 15',
|
|
21
|
+
app: '/path/to/your/app.app',
|
|
22
|
+
automationName: 'XCUITest'
|
|
23
|
+
}
|
|
24
24
|
};
|
|
25
25
|
|
|
26
|
-
describe(
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
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
33
|
});
|
|
34
34
|
```
|
|
35
35
|
|
|
36
36
|
## 2. Automation with Fastlane
|
|
37
37
|
|
|
38
|
-
Fastlane automates
|
|
38
|
+
Fastlane automates building, signing, and uploading to the stores.
|
|
39
39
|
|
|
40
|
-
### Titanium
|
|
41
|
-
Install
|
|
40
|
+
### Titanium plugins
|
|
41
|
+
Install project plugins:
|
|
42
42
|
```bash
|
|
43
43
|
fastlane add_plugin ti_build_app
|
|
44
44
|
fastlane add_plugin mocha_run_tests
|
|
45
45
|
```
|
|
46
46
|
|
|
47
|
-
### Fastfile
|
|
48
|
-
Create
|
|
47
|
+
### Fastfile configuration
|
|
48
|
+
Create `fastlane/Fastfile` in the root:
|
|
49
49
|
|
|
50
50
|
```ruby
|
|
51
51
|
platform :ios do
|
|
@@ -74,23 +74,23 @@ platform :ios do
|
|
|
74
74
|
end
|
|
75
75
|
```
|
|
76
76
|
|
|
77
|
-
## 3. CI/CD
|
|
78
|
-
1.
|
|
79
|
-
2.
|
|
80
|
-
3.
|
|
81
|
-
4.
|
|
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
82
|
|
|
83
|
-
## 4. Unit
|
|
83
|
+
## 4. Unit testing with TiUnit
|
|
84
84
|
|
|
85
|
-
For
|
|
85
|
+
For non-UI tests, consider TiUnit (Jasmine-based):
|
|
86
86
|
- Runs tests inside the app context
|
|
87
87
|
- Supports standard Jasmine `describe`/`it`/`expect` syntax
|
|
88
|
-
-
|
|
88
|
+
- Integrates cleanly into CI pipelines
|
|
89
89
|
|
|
90
|
-
## 5. Broader CI/CD
|
|
90
|
+
## 5. Broader CI/CD options
|
|
91
91
|
|
|
92
92
|
Beyond Fastlane and Appium, Titanium apps can integrate with:
|
|
93
|
-
-
|
|
94
|
-
-
|
|
95
|
-
-
|
|
96
|
-
-
|
|
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
|