@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,155 +1,151 @@
1
- # Advanced database and image best practices
1
+ # Working with data
2
2
 
3
- ## 1. SQLite optimization
4
3
 
5
- - Close result sets and the database after each operation to avoid locks and memory growth. SQLite allows one writer at a time, and leaving a connection open after `INSERT` or `UPDATE` can trigger `DatabaseObjectNotClosed` on the next write.
6
- - Use transactions for batch inserts. If any statement fails, SQLite rolls back the entire batch.
7
- ```javascript
8
- const db = Ti.Database.open('myDatabase');
9
- db.execute('BEGIN');
10
- for (const item of playlist) {
11
- db.execute('INSERT INTO albums (disc, artist, rating) VALUES (?, ?, ?)', item.disc, item.artist, item.rating);
12
- }
13
- db.execute('COMMIT');
14
- db.close();
15
- ```
16
- - Do not ship large pre-populated databases. Ship a small skeleton and download data on first boot to reduce IPA/APK size. The `Resources` directory is read-only, so installing a database copies it to `applicationDataDirectory`, which creates two copies on the device.
17
- - Android note: in Android 2.2 and earlier, the installer could not uncompress assets over 1 MB. One workaround was to rename the file with a `.mp3` extension to prevent `aapt` compression.
18
- - Pattern for downloading a replacement database on first boot:
19
- ```javascript
20
- const updateDatabase = (newData) => {
21
- // delete existing content and rehydrate from downloaded JSON
22
- }
23
- downloadButton.addEventListener('click', () => {
24
- const client = Ti.Network.createHTTPClient({
25
- timeout: 10000,
26
- onload() {
27
- updateDatabase(this.responseData)
28
- Ti.UI.createAlertDialog({ title: 'Info', message: 'Database installed' }).show()
29
- },
30
- onerror(e) {
31
- Ti.UI.createAlertDialog({ title: 'Error', message: e.error }).show()
32
- }
33
- })
34
- client.open('GET', 'https://example.com/data.json')
35
- client.send()
36
- })
37
- ```
38
-
39
- ### Database version management
40
-
41
- Store a version number in your database so you can detect upgrades and run migrations. If you do not have a version table, use `PRAGMA TABLE_INFO` to detect column presence:
4
+ Titanium gives you three places to keep data on the device, and the whole
5
+ decision is how much of it there is and what shape it has.
42
6
 
43
- ```javascript
44
- const addColumn = (dbname, tblName, newFieldName, colSpec) => {
45
- const db = Ti.Database.open(dbname);
46
- let fieldExists = false;
47
- const resultSet = db.execute(`PRAGMA TABLE_INFO(${tblName})`);
48
- while (resultSet.isValidRow()) {
49
- if (resultSet.field(1) === newFieldName) {
50
- fieldExists = true;
51
- }
52
- resultSet.next();
53
- }
54
- resultSet.close();
55
- if (!fieldExists) {
56
- db.execute(`ALTER TABLE ${tblName} ADD COLUMN ${newFieldName} ${colSpec}`);
57
- }
58
- db.close();
59
- };
7
+ | Store | For | Survives an uninstall |
8
+ | ----- | --- | --------------------- |
9
+ | `Ti.App.Properties` | Settings and small values | No |
10
+ | `Ti.Filesystem` | Files, downloads, generated content | No |
11
+ | `Ti.Database` | Rows you query | No |
12
+
13
+ None of them survive an uninstall. Anything that must is on a server, and
14
+ [networking](https://titaniumsdk.com/docs/build/data/networking) is how it gets there.
15
+
16
+ ## Properties
17
+
18
+ Key-value storage for small things: the last tab, whether the user has
19
+ seen the tour. It is backed by `NSUserDefaults` on iOS and `SharedPreferences`
20
+ on Android, and it is read synchronously.
21
+
22
+ ```js
23
+ Ti.App.Properties.setString('lastTab', 'inbox');
24
+ Ti.App.Properties.setBool('seenTour', true);
25
+
26
+ const tab = Ti.App.Properties.getString('lastTab', 'inbox');
27
+ const seen = Ti.App.Properties.getBool('seenTour', false);
60
28
  ```
61
29
 
62
- ---
30
+ Every getter takes a default as its second argument. Use it rather than
31
+ checking `hasProperty` first, which is a second lookup for the same answer.
32
+
33
+ There is a setter and getter per type - `setString`, `setInt`, `setBool`,
34
+ `setDouble`, `setList`, `setObject` - and reading with the wrong one does not
35
+ convert. Store with `setInt` and read with `getString` and you get the default
36
+ back.
63
37
 
64
- ## 2. Image format selection
38
+ `setObject` and `setList` serialise to JSON, so they are for a handful of
39
+ values, not a collection you keep adding to.
65
40
 
66
- Choose the right format for each use case:
41
+ > [!WARNING]
42
+ > Properties are not secure storage. They are plain preferences, readable on a
43
+ > rooted or jailbroken device and included in an unencrypted device backup. A
44
+ > token you would mind losing belongs in the keychain or keystore, which is a
45
+ > native module rather than a core API.
67
46
 
68
- | Format | Compression | Best for | Avoid for |
69
- | ------ | --------------------- | ------------------------------ | ------------------------------------------------------------------ |
70
- | PNG | Lossless | Icons, text, line art, buttons | Photos (large files) |
71
- | JPG | Lossy | Photographs | Text, icons, line drawings (artifacts) |
72
- | GIF | Lossless (256 colors) | Rare cases | Most cases (limited colors, animated GIF not supported everywhere) |
47
+ ## Files
73
48
 
74
- For flip-book animations, use `ImageView.images` with an array of PNG or optimized JPG files instead of animated GIFs.
49
+ `Ti.Filesystem` addresses directories by purpose, and the purpose decides
50
+ whether the operating system may delete what you put there.
75
51
 
76
- ---
52
+ | Directory | Use for | Backed up |
53
+ | --------- | ------- | --------- |
54
+ | `applicationDataDirectory` | Content the app created and needs | Yes |
55
+ | `applicationCacheDirectory` | Anything re-downloadable | No, and may be purged |
56
+ | `tempDirectory` | Working files for right now | No |
57
+ | `resourcesDirectory` | What you shipped. **Read-only** | n/a |
77
58
 
78
- ## 3. Image memory management
59
+ ```js
60
+ const file = Ti.Filesystem.getFile(Ti.Filesystem.applicationDataDirectory, 'notes.txt');
61
+ file.write('written on ' + new Date().toISOString());
79
62
 
80
- - A JPG is small on disk but expands to `width * height * 3 bytes` in RAM. Each pixel uses 24 bits (8 bits per R/G/B channel).
81
- - Example: `(640 × 480 × 3) / 1024 = 900 KB` in memory for a single image
82
- - Device RAM available to your app can be as low as 12 MB, shared with your code and the Titanium framework
83
- - Unloading:
84
- - `view.remove(imageView)` removes it from the view hierarchy and lets the OS free memory
85
- - `imageView = null` releases the native proxy object
86
- - Resizing: resize images to their display dimensions using `imageAsResized` or `imageAsCropped` (both on `Ti.Blob`) before setting the `image` property. Do not display a 1024×768 image on a 640×480 screen.
87
- - Placeholder: set `defaultImage` on ImageView to show a local placeholder while a remote image downloads:
88
- ```javascript
89
- const imageView = Ti.UI.createImageView({
90
- image: 'https://example.com/photo.jpg',
91
- defaultImage: '/images/placeholder.png',
92
- width: 300,
93
- height: 200
94
- });
95
- ```
63
+ if (file.exists()) {
64
+ Ti.API.info(file.read().text);
65
+ }
66
+ ```
67
+
68
+ `getFile` takes path segments and joins them, so pass the directory and the
69
+ name rather than concatenating with a separator yourself.
70
+
71
+ Putting a cache in `applicationDataDirectory` is the common mistake: it is
72
+ backed up, so a 200MB image cache goes into the user's iCloud backup.
73
+
74
+ ## A database
75
+
76
+ `Ti.Database` is SQLite. Open a database by name and it is created on first
77
+ use.
78
+
79
+ ```js
80
+ const db = Ti.Database.open('notes');
96
81
 
97
- ---
82
+ db.execute(`
83
+ CREATE TABLE IF NOT EXISTS notes (
84
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
85
+ body TEXT NOT NULL,
86
+ created TEXT NOT NULL
87
+ )
88
+ `);
98
89
 
99
- ## 4. Image optimization tools
90
+ db.execute('INSERT INTO notes (body, created) VALUES (?, ?)', 'First note', new Date().toISOString());
91
+ Ti.API.info(`inserted row ${db.lastInsertRowId}`);
100
92
 
101
- Resize and compress images before including them in your app to reduce IPA/APK size and network usage.
93
+ const rows = db.execute('SELECT id, body FROM notes ORDER BY id DESC');
94
+ while (rows.isValidRow()) {
95
+ Ti.API.info(`${rows.fieldByName('id')}: ${rows.fieldByName('body')}`);
96
+ rows.next();
97
+ }
98
+ rows.close();
99
+ db.close();
100
+ ```
101
+
102
+ **Pass values as arguments, never by building the SQL string.** The `?`
103
+ placeholders are escaped for you; string concatenation is how an apostrophe in
104
+ a note becomes a syntax error and how a hostile value becomes an injection.
105
+
106
+ A result set is a cursor, not an array: walk it with `isValidRow()` and
107
+ `next()`, and close it. Close the database when you are done with it.
102
108
 
103
- | Platform | File types | Tool |
104
- | ------------------- | ------------- | ----------- |
105
- | Mac | PNG, JPG, GIF | ImageOptim |
106
- | Mac, Windows, Linux | PNG, JPG, GIF | ImageMagick |
107
- | Windows/DOS | PNG | PNGCrush |
108
- | Windows | JPG | Nikkho |
109
+ `executeAsync` and `executeAllAsync` run off the main thread and take a
110
+ callback. Use them for anything large enough to be noticeable, which on a
111
+ phone is sooner than you would guess.
109
112
 
110
- ---
113
+ ### Shipping a prepared database
111
114
 
112
- ## 5. Caching remote images
115
+ `Ti.Database.install` copies a `.sqlite` file out of your resources on first
116
+ run and opens it, so an app can ship with data already in it.
113
117
 
114
- Remote images are cached automatically on iOS, Android, and Windows.
118
+ ```js
119
+ const db = Ti.Database.install('/data/seed.sqlite', 'notes');
120
+ ```
115
121
 
116
- Platform differences:
117
- - Android: cache limited to 25 MB, persists for the lifetime of the app (while installed)
118
- - iOS: cache size not fixed, cleared by iOS when the device needs storage
122
+ The copy happens once. Changing the shipped file in a later release does not
123
+ replace a database the user already has, so version your schema and migrate.
119
124
 
120
- To manually clean the cache, delete files in `applicationCacheDirectory`.
125
+ ## Next
121
126
 
122
- Android 6+ requirement: call `Ti.Filesystem.requestStoragePermissions()` before loading remote images.
127
+ [Networking and remote data](https://titaniumsdk.com/docs/build/data/networking) is the other half:
128
+ getting data in and out over HTTP.
123
129
 
124
- ### Manual caching utility
130
+ ## Close resources on failures
125
131
 
126
- For critical assets, cache manually in `applicationDataDirectory` for more predictable behavior:
132
+ The cursor and database cleanup in the straight-line example must also run when query execution or processing throws. Put cursor cleanup in `finally`, then close the database. `executeAsync` and `executeAllAsync` also return Promises on SDK 10+; await completion before closing handles, and close every returned cursor, including partial results reported by a failed batch.
127
133
 
128
134
  ```javascript
129
- const CacheUtils = {
130
- getExtension: (fn) => {
131
- const match = /(?:\.([^.]+))?$/.exec(fn);
132
- return match[1] || '';
133
- },
134
-
135
- createCachedImageView: (options) => {
136
- const md5 = Ti.Utils.md5HexDigest(options.image) + CacheUtils.getExtension(options.image);
137
- const savedFile = Ti.Filesystem.getFile(Ti.Filesystem.applicationDataDirectory, md5);
138
-
139
- if (savedFile.exists()) {
140
- options.image = savedFile;
141
- return Ti.UI.createImageView(options);
135
+ async function readNotes() {
136
+ const db = Ti.Database.open('notes');
137
+ let rows;
138
+ try {
139
+ rows = await db.executeAsync('SELECT id, body FROM notes ORDER BY id DESC');
140
+ while (rows.isValidRow()) {
141
+ Ti.API.info(rows.fieldByName('body'));
142
+ rows.next();
142
143
  }
143
-
144
- const imageView = Ti.UI.createImageView(options);
145
- const saveImage = () => {
146
- imageView.removeEventListener('load', saveImage);
147
- savedFile.write(
148
- Ti.UI.createImageView({ image: imageView.image, width: Ti.UI.FILL, height: Ti.UI.FILL }).toImage()
149
- );
150
- };
151
- imageView.addEventListener('load', saveImage);
152
- return imageView;
144
+ } finally {
145
+ if (rows) {
146
+ rows.close();
147
+ }
148
+ db.close();
153
149
  }
154
- };
150
+ }
155
151
  ```
@@ -1,97 +1,38 @@
1
- # Custom AndroidManifest.xml
1
+ # Android manifest configuration
2
2
 
3
- For most Android manifest settings, use `tiapp.xml`. Only create a custom manifest when you really need it.
3
+ ## Android
4
4
 
5
- ## Preferred method: tiapp.xml
5
+ Children of `<android>`. As with `<ios>`, anything else is discarded. The
6
+ `xmlns:android` declaration belongs on the `<android>` element.
6
7
 
7
- Add manifest entries in `tiapp.xml` inside the `<android>` section:
8
+ | Element | Value | Effect |
9
+ | ---------------- | --------------- | ------------------------------------------------------------------- |
10
+ | `manifest` | XML | Merged into the generated `AndroidManifest.xml` |
11
+ | `tool-api-level` | int | The API level the app is compiled against |
12
+ | `abi` | comma-separated | Which ABIs to package. `all` packages every one |
13
+ | `activities` | element | Extra activities, each keyed by the JavaScript file it opens |
14
+ | `services` | element | Extra services. `type="quicksettings"` builds a quick settings tile |
8
15
 
9
16
  ```xml
10
17
  <android xmlns:android="http://schemas.android.com/apk/res/android">
11
- <manifest>
12
- <!-- SDK version -->
13
- <uses-sdk android:minSdkVersion="21" android:targetSdkVersion="34" />
14
-
15
- <!-- Screen support -->
16
- <supports-screens
17
- android:smallScreens="false"
18
- android:normalScreens="true"
19
- android:largeScreens="true"
20
- android:xlargeScreens="true"
21
- />
22
-
23
- <!-- Permissions -->
24
- <uses-permission android:name="android.permission.CAMERA" />
25
- <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
26
-
27
- <!-- Application attributes (merged, not replaced) -->
28
- <application android:debuggable="true" />
29
- </manifest>
18
+ <manifest android:versionCode="1">
19
+ <uses-permission android:name="android.permission.CAMERA"/>
20
+ <application android:icon="@mipmap/ic_launcher"/>
21
+ </manifest>
22
+ <abi>arm64-v8a,x86_64</abi>
30
23
  </android>
31
24
  ```
32
25
 
33
- ## How merging works
34
-
35
- - Most elements are replaced by your entry.
36
- - The `<application>` element is merged additively by attribute.
37
- - Activities and services are added to existing ones.
38
-
39
- ## Custom manifest (rare cases)
40
-
41
- If you need full control, create `platform/android/AndroidManifest.xml`:
42
-
43
- ```
44
- MyApp/
45
- ├── app/
46
- ├── platform/
47
- │ └── android/
48
- │ └── AndroidManifest.xml # Custom manifest
49
- └── tiapp.xml
50
- ```
51
-
52
- Warning: you must maintain this file manually through SDK updates.
53
-
54
- ## Common use cases
55
-
56
- ### Camera permission
57
- ```xml
58
- <uses-permission android:name="android.permission.CAMERA" />
59
- ```
60
-
61
- ### Hardware requirements
62
- ```xml
63
- <uses-feature android:name="android.hardware.camera" android:required="false" />
64
- ```
26
+ `android:versionCode` is the integer Google Play orders releases by, and it has
27
+ to increase on every upload. `<version>` above is the human one; these are
28
+ separate numbers and both matter.
65
29
 
66
- ### Launch mode
67
- ```xml
68
- <application android:launchMode="singleTask" />
69
- ```
30
+ Restricting `abi` shrinks the APK and is the usual reason to set it. An ABI you
31
+ drop is a device the app will not install on.
70
32
 
71
- ### Deep links
72
- ```xml
73
- <intent-filter>
74
- <action android:name="android.intent.action.VIEW" />
75
- <category android:name="android.intent.category.DEFAULT" />
76
- <category android:name="android.intent.category.BROWSABLE" />
77
- <data android:scheme="myapp" android:host="path" />
78
- </intent-filter>
79
- ```
80
-
81
- ## Debugging
82
-
83
- To see the generated manifest:
84
- ```bash
85
- ti build -p android
86
- # Check: build/android/AndroidManifest.xml.gen
87
- ```
88
-
89
- ## Enable manifest merge (CLI 7.0+)
90
33
 
91
- If you use a custom manifest, enable merge in `tiapp.xml`:
34
+ ## Merge and inspect the release variant
92
35
 
93
- ```bash
94
- ti config android.mergeCustomAndroidManifest true
95
- ```
36
+ SDK 13.4.1 generates a base `src/main/AndroidManifest.xml` plus variant overlays below `build/android/`; Gradle merges app, library and module manifests. Use Android manifest-merger rules and `tools:remove` when needed, then inspect the actual merged release manifest. The legacy `android.mergeCustomAndroidManifest=false` switch is unsupported and does not restore replacement mode. A declared permission still needs its runtime permission workflow where the OS requires it.
96
37
 
97
- This merges your custom manifest with the generated one instead of replacing it.
38
+ `<tool-api-level>` is the compile API. Manifest min/target APIs are different settings; use the released [compatibility baseline](compatibility-matrix.md). Do not force debuggable in distributed artifacts. For other XML elements see [tiapp.xml](tiapp-config.md).