@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.
- package/CONTRIBUTING.md +1 -1
- package/README.md +31 -60
- package/agents/ti-pro.md +3 -1
- package/commands/ti-audit.md +6 -4
- package/docs/examples.md +9 -0
- package/docs/knowledge-index.md +2 -1
- package/lib/config.js +1 -0
- package/package.json +1 -1
- package/skills/alloy-guides/SKILL.md +18 -179
- package/skills/alloy-guides/references/CLI_TASKS.md +17 -216
- package/skills/alloy-guides/references/CONCEPTS.md +27 -162
- package/skills/alloy-guides/references/CONTROLLERS.md +38 -236
- package/skills/alloy-guides/references/MODELS.md +47 -723
- package/skills/alloy-guides/references/MODELS_ADVANCED.md +21 -482
- package/skills/alloy-guides/references/VIEWS_DYNAMIC.md +12 -222
- package/skills/alloy-guides/references/VIEWS_STYLES.md +39 -358
- package/skills/alloy-guides/references/VIEWS_XML.md +36 -552
- package/skills/alloy-guides/references/WIDGETS.md +49 -127
- package/skills/alloy-howtos/SKILL.md +14 -169
- package/skills/alloy-howtos/references/best_practices.md +9 -113
- package/skills/alloy-howtos/references/cli_reference.md +18 -223
- package/skills/alloy-howtos/references/config_files.md +50 -133
- package/skills/alloy-howtos/references/debugging_troubleshooting.md +19 -63
- package/skills/alloy-howtos/references/samples.md +21 -138
- package/skills/ti-api/SKILL.md +10 -2
- package/skills/ti-api/references/api-android.md +36 -2
- package/skills/ti-api/references/api-app-platform.md +39 -3
- package/skills/ti-api/references/api-core.md +50 -18
- package/skills/ti-api/references/api-data-network.md +49 -35
- package/skills/ti-api/references/api-media.md +45 -27
- package/skills/ti-api/references/api-services.md +39 -9
- package/skills/ti-api/references/api-ui-android.md +33 -13
- package/skills/ti-api/references/api-ui-extras.md +41 -15
- package/skills/ti-api/references/api-ui-ios-animator.md +42 -26
- package/skills/ti-api/references/api-ui-ios.md +74 -2
- package/skills/ti-api/references/api-ui-lists.md +32 -16
- package/skills/ti-api/references/api-ui-text-input.md +34 -17
- package/skills/ti-api/references/api-ui-views.md +27 -1
- package/skills/ti-api/references/api-ui-windows-navigation.md +32 -18
- package/skills/ti-api/references/api-xml-global.md +66 -16
- package/skills/ti-create-release/SKILL.md +98 -0
- package/skills/ti-create-release/references/module-discovery.md +69 -0
- package/skills/ti-expert/references/adaptive-layouts.md +1 -1
- package/skills/ti-guides/SKILL.md +37 -76
- package/skills/ti-guides/references/advanced-data-and-images.md +122 -126
- package/skills/ti-guides/references/android-manifest.md +24 -83
- package/skills/ti-guides/references/app-distribution.md +31 -377
- package/skills/ti-guides/references/application-frameworks.md +127 -335
- package/skills/ti-guides/references/cli-reference.md +184 -633
- package/skills/ti-guides/references/commonjs-advanced.md +81 -231
- package/skills/ti-guides/references/compatibility-matrix.md +36 -75
- package/skills/ti-guides/references/hello-world.md +95 -70
- package/skills/ti-guides/references/hyperloop-native-access.md +52 -448
- package/skills/ti-guides/references/resources.md +174 -142
- package/skills/ti-guides/references/sdk-release-notes.md +28 -71
- package/skills/ti-guides/references/tiapp-config.md +222 -598
- package/skills/ti-howtos/SKILL.md +23 -123
- package/skills/ti-howtos/references/cross-platform-development.md +119 -324
- package/skills/ti-howtos/references/debugging-profiling.md +77 -445
- package/skills/ti-howtos/references/extending-titanium.md +199 -673
- package/skills/ti-howtos/references/local-data-sources.md +87 -300
- package/skills/ti-howtos/references/location-and-maps.md +86 -213
- package/skills/ti-howtos/references/media-apis.md +103 -223
- package/skills/ti-howtos/references/notification-services.md +86 -506
- package/skills/ti-howtos/references/remote-data-sources.md +97 -316
- package/skills/ti-howtos/references/using-modules.md +77 -133
- package/skills/ti-ui/SKILL.md +28 -143
- package/skills/ti-ui/references/icons-and-splash-screens.md +74 -403
- package/skills/ti-ui/references/layouts-and-positioning.md +175 -402
- package/skills/ti-ui/references/listviews-and-performance.md +100 -703
- package/skills/ti-ui/references/platform-conventions.md +180 -0
- package/skills/ti-ui/references/user-interface.md +43 -0
- package/skills/alloy-guides/references/VIEWS_WITHOUT_CONTROLLERS.md +0 -102
- package/skills/alloy-howtos/references/custom_tags.md +0 -148
- package/skills/ti-guides/references/coding-best-practices.md +0 -149
- package/skills/ti-guides/references/javascript-primer.md +0 -414
- package/skills/ti-guides/references/reserved-words.md +0 -36
- package/skills/ti-guides/references/style-and-conventions.md +0 -103
- package/skills/ti-howtos/references/android-platform-deep-dives.md +0 -624
- package/skills/ti-howtos/references/automation-fastlane-appium.md +0 -96
- package/skills/ti-howtos/references/buffer-codec-streams.md +0 -162
- package/skills/ti-howtos/references/google-maps-v2.md +0 -172
- package/skills/ti-howtos/references/ios-map-kit.md +0 -149
- package/skills/ti-howtos/references/ios-platform-deep-dives.md +0 -611
- package/skills/ti-howtos/references/tutorials.md +0 -565
- package/skills/ti-howtos/references/web-content-integration.md +0 -287
- package/skills/ti-howtos/references/webpack-build-pipeline.md +0 -124
- package/skills/ti-ui/references/accessibility-deep-dive.md +0 -288
- package/skills/ti-ui/references/animation-and-matrices.md +0 -569
- package/skills/ti-ui/references/application-structures.md +0 -626
- package/skills/ti-ui/references/custom-fonts-styling.md +0 -549
- package/skills/ti-ui/references/event-handling.md +0 -401
- package/skills/ti-ui/references/gestures.md +0 -448
- package/skills/ti-ui/references/orientation.md +0 -374
- package/skills/ti-ui/references/platform-ui-android.md +0 -727
- package/skills/ti-ui/references/platform-ui-ios.md +0 -576
- package/skills/ti-ui/references/scrolling-views.md +0 -288
- package/skills/ti-ui/references/tableviews.md +0 -542
|
@@ -1,155 +1,151 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Working with data
|
|
2
2
|
|
|
3
|
-
## 1. SQLite optimization
|
|
4
3
|
|
|
5
|
-
|
|
6
|
-
|
|
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
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
59
|
+
```js
|
|
60
|
+
const file = Ti.Filesystem.getFile(Ti.Filesystem.applicationDataDirectory, 'notes.txt');
|
|
61
|
+
file.write('written on ' + new Date().toISOString());
|
|
79
62
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
104
|
-
|
|
105
|
-
|
|
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
|
-
|
|
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
|
-
|
|
118
|
+
```js
|
|
119
|
+
const db = Ti.Database.install('/data/seed.sqlite', 'notes');
|
|
120
|
+
```
|
|
115
121
|
|
|
116
|
-
|
|
117
|
-
|
|
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
|
-
|
|
125
|
+
## Next
|
|
121
126
|
|
|
122
|
-
|
|
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
|
-
|
|
130
|
+
## Close resources on failures
|
|
125
131
|
|
|
126
|
-
|
|
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
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
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
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
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
|
-
#
|
|
1
|
+
# Android manifest configuration
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
## Android
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
Children of `<android>`. As with `<ios>`, anything else is discarded. The
|
|
6
|
+
`xmlns:android` declaration belongs on the `<android>` element.
|
|
6
7
|
|
|
7
|
-
|
|
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
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
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
|
-
|
|
34
|
-
|
|
35
|
-
|
|
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
|
-
|
|
67
|
-
|
|
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
|
-
|
|
34
|
+
## Merge and inspect the release variant
|
|
92
35
|
|
|
93
|
-
|
|
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
|
-
|
|
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).
|