@craft-native/android 0.0.72
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 +606 -0
- package/dist/index.js +410 -0
- package/dist/index.js.map +10 -0
- package/package.json +38 -0
- package/templates/AndroidManifest.xml.template +43 -0
- package/templates/CraftBridge.kt.template +3880 -0
- package/templates/CraftBridgeExtensions.kt.template +383 -0
- package/templates/CraftHealthConnect.kt.template +200 -0
- package/templates/CraftHealthConnectStub.kt.template +28 -0
- package/templates/CraftWidgetProvider.kt.template +246 -0
- package/templates/LocationRecordingService.kt.template +160 -0
- package/templates/MainActivity.kt.template +230 -0
- package/templates/build.gradle.kts.app.template +102 -0
- package/templates/build.gradle.kts.project.template +6 -0
- package/templates/fastlane/Appfile +25 -0
- package/templates/fastlane/Fastfile +192 -0
- package/templates/fastlane/Gemfile +7 -0
- package/templates/github-workflow-android.yml +248 -0
- package/templates/github-workflow-test.yml +329 -0
- package/templates/proguard-rules.pro.template +9 -0
- package/templates/settings.gradle.kts.template +18 -0
- package/templates/test-bridges.html +1463 -0
|
@@ -0,0 +1,329 @@
|
|
|
1
|
+
# Android Test Workflow
|
|
2
|
+
# Runs unit tests, instrumented tests, and lint checks
|
|
3
|
+
# Supports multiple API levels and device configurations
|
|
4
|
+
|
|
5
|
+
name: Android Tests
|
|
6
|
+
|
|
7
|
+
on:
|
|
8
|
+
push:
|
|
9
|
+
branches: [main, develop]
|
|
10
|
+
paths:
|
|
11
|
+
- 'android/**'
|
|
12
|
+
- '.github/workflows/android-test.yml'
|
|
13
|
+
pull_request:
|
|
14
|
+
branches: [main, develop]
|
|
15
|
+
paths:
|
|
16
|
+
- 'android/**'
|
|
17
|
+
workflow_dispatch:
|
|
18
|
+
inputs:
|
|
19
|
+
api_level:
|
|
20
|
+
description: 'Android API level'
|
|
21
|
+
required: false
|
|
22
|
+
default: '34'
|
|
23
|
+
run_instrumented:
|
|
24
|
+
description: 'Run instrumented tests'
|
|
25
|
+
required: false
|
|
26
|
+
default: 'true'
|
|
27
|
+
type: boolean
|
|
28
|
+
|
|
29
|
+
env:
|
|
30
|
+
JAVA_VERSION: '17'
|
|
31
|
+
GRADLE_OPTS: "-Dorg.gradle.jvmargs=-Xmx4g -Dorg.gradle.daemon=false"
|
|
32
|
+
|
|
33
|
+
jobs:
|
|
34
|
+
lint:
|
|
35
|
+
name: Lint & Static Analysis
|
|
36
|
+
runs-on: ubuntu-latest
|
|
37
|
+
timeout-minutes: 15
|
|
38
|
+
|
|
39
|
+
steps:
|
|
40
|
+
- name: Checkout
|
|
41
|
+
uses: actions/checkout@v4
|
|
42
|
+
|
|
43
|
+
- name: Set up JDK
|
|
44
|
+
uses: actions/setup-java@v4
|
|
45
|
+
with:
|
|
46
|
+
java-version: ${{ env.JAVA_VERSION }}
|
|
47
|
+
distribution: 'temurin'
|
|
48
|
+
|
|
49
|
+
- name: Setup Gradle
|
|
50
|
+
uses: gradle/actions/setup-gradle@v3
|
|
51
|
+
with:
|
|
52
|
+
cache-read-only: ${{ github.ref != 'refs/heads/main' }}
|
|
53
|
+
|
|
54
|
+
- name: Run Lint
|
|
55
|
+
run: |
|
|
56
|
+
cd android
|
|
57
|
+
./gradlew lint
|
|
58
|
+
|
|
59
|
+
- name: Upload Lint Results
|
|
60
|
+
uses: actions/upload-artifact@v4
|
|
61
|
+
if: always()
|
|
62
|
+
with:
|
|
63
|
+
name: lint-results
|
|
64
|
+
path: |
|
|
65
|
+
android/app/build/reports/lint-results*.html
|
|
66
|
+
android/app/build/reports/lint-results*.xml
|
|
67
|
+
retention-days: 14
|
|
68
|
+
|
|
69
|
+
- name: Run Detekt (if configured)
|
|
70
|
+
continue-on-error: true
|
|
71
|
+
run: |
|
|
72
|
+
cd android
|
|
73
|
+
if ./gradlew tasks --all | grep -q "detekt"; then
|
|
74
|
+
./gradlew detekt
|
|
75
|
+
fi
|
|
76
|
+
|
|
77
|
+
- name: Comment on PR with Lint Results
|
|
78
|
+
uses: actions/github-script@v7
|
|
79
|
+
if: github.event_name == 'pull_request' && failure()
|
|
80
|
+
with:
|
|
81
|
+
script: |
|
|
82
|
+
const fs = require('fs');
|
|
83
|
+
const lintReport = 'android/app/build/reports/lint-results-debug.xml';
|
|
84
|
+
if (fs.existsSync(lintReport)) {
|
|
85
|
+
github.rest.issues.createComment({
|
|
86
|
+
issue_number: context.issue.number,
|
|
87
|
+
owner: context.repo.owner,
|
|
88
|
+
repo: context.repo.repo,
|
|
89
|
+
body: '⚠️ Lint checks found issues. Please review the artifacts for details.'
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
unit-tests:
|
|
94
|
+
name: Unit Tests
|
|
95
|
+
runs-on: ubuntu-latest
|
|
96
|
+
timeout-minutes: 20
|
|
97
|
+
|
|
98
|
+
steps:
|
|
99
|
+
- name: Checkout
|
|
100
|
+
uses: actions/checkout@v4
|
|
101
|
+
|
|
102
|
+
- name: Set up JDK
|
|
103
|
+
uses: actions/setup-java@v4
|
|
104
|
+
with:
|
|
105
|
+
java-version: ${{ env.JAVA_VERSION }}
|
|
106
|
+
distribution: 'temurin'
|
|
107
|
+
|
|
108
|
+
- name: Setup Gradle
|
|
109
|
+
uses: gradle/actions/setup-gradle@v3
|
|
110
|
+
with:
|
|
111
|
+
cache-read-only: ${{ github.ref != 'refs/heads/main' }}
|
|
112
|
+
|
|
113
|
+
- name: Run Unit Tests
|
|
114
|
+
run: |
|
|
115
|
+
cd android
|
|
116
|
+
./gradlew testDebugUnitTest
|
|
117
|
+
|
|
118
|
+
- name: Upload Test Results
|
|
119
|
+
uses: actions/upload-artifact@v4
|
|
120
|
+
if: always()
|
|
121
|
+
with:
|
|
122
|
+
name: unit-test-results
|
|
123
|
+
path: |
|
|
124
|
+
android/app/build/reports/tests/
|
|
125
|
+
android/app/build/test-results/
|
|
126
|
+
retention-days: 14
|
|
127
|
+
|
|
128
|
+
- name: Publish Test Report
|
|
129
|
+
uses: mikepenz/action-junit-report@v4
|
|
130
|
+
if: always()
|
|
131
|
+
with:
|
|
132
|
+
report_paths: 'android/app/build/test-results/**/TEST-*.xml'
|
|
133
|
+
check_name: 'Unit Test Results'
|
|
134
|
+
fail_on_failure: true
|
|
135
|
+
|
|
136
|
+
- name: Generate Coverage Report
|
|
137
|
+
run: |
|
|
138
|
+
cd android
|
|
139
|
+
./gradlew jacocoTestReport || true
|
|
140
|
+
|
|
141
|
+
- name: Upload Coverage
|
|
142
|
+
uses: actions/upload-artifact@v4
|
|
143
|
+
if: success()
|
|
144
|
+
with:
|
|
145
|
+
name: coverage-report
|
|
146
|
+
path: android/app/build/reports/jacoco/
|
|
147
|
+
retention-days: 14
|
|
148
|
+
|
|
149
|
+
instrumented-tests:
|
|
150
|
+
name: Instrumented Tests (API ${{ matrix.api-level }})
|
|
151
|
+
runs-on: ubuntu-latest
|
|
152
|
+
timeout-minutes: 45
|
|
153
|
+
needs: unit-tests
|
|
154
|
+
|
|
155
|
+
strategy:
|
|
156
|
+
fail-fast: false
|
|
157
|
+
matrix:
|
|
158
|
+
include:
|
|
159
|
+
- api-level: 34
|
|
160
|
+
target: google_apis
|
|
161
|
+
arch: x86_64
|
|
162
|
+
- api-level: 31
|
|
163
|
+
target: google_apis
|
|
164
|
+
arch: x86_64
|
|
165
|
+
- api-level: 28
|
|
166
|
+
target: google_apis
|
|
167
|
+
arch: x86_64
|
|
168
|
+
|
|
169
|
+
steps:
|
|
170
|
+
- name: Checkout
|
|
171
|
+
uses: actions/checkout@v4
|
|
172
|
+
|
|
173
|
+
- name: Set up JDK
|
|
174
|
+
uses: actions/setup-java@v4
|
|
175
|
+
with:
|
|
176
|
+
java-version: ${{ env.JAVA_VERSION }}
|
|
177
|
+
distribution: 'temurin'
|
|
178
|
+
|
|
179
|
+
- name: Setup Gradle
|
|
180
|
+
uses: gradle/actions/setup-gradle@v3
|
|
181
|
+
with:
|
|
182
|
+
cache-read-only: ${{ github.ref != 'refs/heads/main' }}
|
|
183
|
+
|
|
184
|
+
- name: Enable KVM group perms
|
|
185
|
+
run: |
|
|
186
|
+
echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | sudo tee /etc/udev/rules.d/99-kvm4all.rules
|
|
187
|
+
sudo udevadm control --reload-rules
|
|
188
|
+
sudo udevadm trigger --name-match=kvm
|
|
189
|
+
|
|
190
|
+
- name: AVD cache
|
|
191
|
+
uses: actions/cache@v4
|
|
192
|
+
id: avd-cache
|
|
193
|
+
with:
|
|
194
|
+
path: |
|
|
195
|
+
~/.android/avd/*
|
|
196
|
+
~/.android/adb*
|
|
197
|
+
key: avd-${{ matrix.api-level }}-${{ matrix.target }}-${{ matrix.arch }}
|
|
198
|
+
|
|
199
|
+
- name: Create AVD and generate snapshot for caching
|
|
200
|
+
if: steps.avd-cache.outputs.cache-hit != 'true'
|
|
201
|
+
uses: reactivecircus/android-emulator-runner@v2
|
|
202
|
+
with:
|
|
203
|
+
api-level: ${{ matrix.api-level }}
|
|
204
|
+
target: ${{ matrix.target }}
|
|
205
|
+
arch: ${{ matrix.arch }}
|
|
206
|
+
force-avd-creation: false
|
|
207
|
+
emulator-options: -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none
|
|
208
|
+
disable-animations: true
|
|
209
|
+
script: echo "Generated AVD snapshot for caching"
|
|
210
|
+
|
|
211
|
+
- name: Run Instrumented Tests
|
|
212
|
+
uses: reactivecircus/android-emulator-runner@v2
|
|
213
|
+
with:
|
|
214
|
+
api-level: ${{ matrix.api-level }}
|
|
215
|
+
target: ${{ matrix.target }}
|
|
216
|
+
arch: ${{ matrix.arch }}
|
|
217
|
+
force-avd-creation: false
|
|
218
|
+
emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none
|
|
219
|
+
disable-animations: true
|
|
220
|
+
script: |
|
|
221
|
+
cd android
|
|
222
|
+
./gradlew connectedDebugAndroidTest
|
|
223
|
+
|
|
224
|
+
- name: Upload Instrumented Test Results
|
|
225
|
+
uses: actions/upload-artifact@v4
|
|
226
|
+
if: always()
|
|
227
|
+
with:
|
|
228
|
+
name: instrumented-test-results-api${{ matrix.api-level }}
|
|
229
|
+
path: |
|
|
230
|
+
android/app/build/reports/androidTests/
|
|
231
|
+
android/app/build/outputs/androidTest-results/
|
|
232
|
+
retention-days: 14
|
|
233
|
+
|
|
234
|
+
- name: Publish Instrumented Test Report
|
|
235
|
+
uses: mikepenz/action-junit-report@v4
|
|
236
|
+
if: always()
|
|
237
|
+
with:
|
|
238
|
+
report_paths: 'android/app/build/outputs/androidTest-results/**/*.xml'
|
|
239
|
+
check_name: 'Instrumented Test Results (API ${{ matrix.api-level }})'
|
|
240
|
+
fail_on_failure: true
|
|
241
|
+
|
|
242
|
+
screenshot-tests:
|
|
243
|
+
name: Screenshot Tests
|
|
244
|
+
runs-on: ubuntu-latest
|
|
245
|
+
timeout-minutes: 30
|
|
246
|
+
if: github.event_name == 'pull_request'
|
|
247
|
+
|
|
248
|
+
steps:
|
|
249
|
+
- name: Checkout
|
|
250
|
+
uses: actions/checkout@v4
|
|
251
|
+
with:
|
|
252
|
+
fetch-depth: 0
|
|
253
|
+
|
|
254
|
+
- name: Set up JDK
|
|
255
|
+
uses: actions/setup-java@v4
|
|
256
|
+
with:
|
|
257
|
+
java-version: ${{ env.JAVA_VERSION }}
|
|
258
|
+
distribution: 'temurin'
|
|
259
|
+
|
|
260
|
+
- name: Setup Gradle
|
|
261
|
+
uses: gradle/actions/setup-gradle@v3
|
|
262
|
+
|
|
263
|
+
- name: Enable KVM
|
|
264
|
+
run: |
|
|
265
|
+
echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | sudo tee /etc/udev/rules.d/99-kvm4all.rules
|
|
266
|
+
sudo udevadm control --reload-rules
|
|
267
|
+
sudo udevadm trigger --name-match=kvm
|
|
268
|
+
|
|
269
|
+
- name: Run Screenshot Tests
|
|
270
|
+
uses: reactivecircus/android-emulator-runner@v2
|
|
271
|
+
with:
|
|
272
|
+
api-level: 34
|
|
273
|
+
target: google_apis
|
|
274
|
+
arch: x86_64
|
|
275
|
+
force-avd-creation: false
|
|
276
|
+
emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim
|
|
277
|
+
disable-animations: true
|
|
278
|
+
script: |
|
|
279
|
+
cd android
|
|
280
|
+
./gradlew verifyPaparazziDebug || ./gradlew recordPaparazziDebug
|
|
281
|
+
|
|
282
|
+
- name: Upload Screenshot Differences
|
|
283
|
+
uses: actions/upload-artifact@v4
|
|
284
|
+
if: failure()
|
|
285
|
+
with:
|
|
286
|
+
name: screenshot-differences
|
|
287
|
+
path: |
|
|
288
|
+
android/app/build/paparazzi/
|
|
289
|
+
android/app/out/failures/
|
|
290
|
+
retention-days: 14
|
|
291
|
+
|
|
292
|
+
test-summary:
|
|
293
|
+
name: Test Summary
|
|
294
|
+
runs-on: ubuntu-latest
|
|
295
|
+
needs: [lint, unit-tests, instrumented-tests]
|
|
296
|
+
if: always()
|
|
297
|
+
|
|
298
|
+
steps:
|
|
299
|
+
- name: Download all artifacts
|
|
300
|
+
uses: actions/download-artifact@v4
|
|
301
|
+
with:
|
|
302
|
+
path: artifacts
|
|
303
|
+
|
|
304
|
+
- name: Generate Summary
|
|
305
|
+
run: |
|
|
306
|
+
echo "## Android Test Results" >> $GITHUB_STEP_SUMMARY
|
|
307
|
+
echo "" >> $GITHUB_STEP_SUMMARY
|
|
308
|
+
|
|
309
|
+
echo "### Jobs Status" >> $GITHUB_STEP_SUMMARY
|
|
310
|
+
echo "| Job | Status |" >> $GITHUB_STEP_SUMMARY
|
|
311
|
+
echo "|-----|--------|" >> $GITHUB_STEP_SUMMARY
|
|
312
|
+
echo "| Lint | ${{ needs.lint.result }} |" >> $GITHUB_STEP_SUMMARY
|
|
313
|
+
echo "| Unit Tests | ${{ needs.unit-tests.result }} |" >> $GITHUB_STEP_SUMMARY
|
|
314
|
+
echo "| Instrumented Tests | ${{ needs.instrumented-tests.result }} |" >> $GITHUB_STEP_SUMMARY
|
|
315
|
+
|
|
316
|
+
echo "" >> $GITHUB_STEP_SUMMARY
|
|
317
|
+
echo "### Test Artifacts" >> $GITHUB_STEP_SUMMARY
|
|
318
|
+
|
|
319
|
+
if [ -d "artifacts" ]; then
|
|
320
|
+
find artifacts -type f -name "*.xml" -o -name "*.html" | head -20 | while read f; do
|
|
321
|
+
echo "- $f" >> $GITHUB_STEP_SUMMARY
|
|
322
|
+
done
|
|
323
|
+
fi
|
|
324
|
+
|
|
325
|
+
- name: Check for failures
|
|
326
|
+
if: needs.lint.result == 'failure' || needs.unit-tests.result == 'failure' || needs.instrumented-tests.result == 'failure'
|
|
327
|
+
run: |
|
|
328
|
+
echo "❌ Some tests failed. Please review the artifacts for details."
|
|
329
|
+
exit 1
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# Preserve the JavaScript bridge contract and its annotated methods when R8
|
|
2
|
+
# optimizes release builds. These classes are reached from WebView by name.
|
|
3
|
+
-keepattributes RuntimeVisibleAnnotations,RuntimeInvisibleAnnotations
|
|
4
|
+
-keepclassmembers class * {
|
|
5
|
+
@android.webkit.JavascriptInterface <methods>;
|
|
6
|
+
}
|
|
7
|
+
-keep class {{PACKAGE_NAME}}.CraftBridge { *; }
|
|
8
|
+
-keep class {{PACKAGE_NAME}}.CraftHealthConnect { *; }
|
|
9
|
+
-keep class {{PACKAGE_NAME}}.LocationRecordingService { *; }
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
pluginManagement {
|
|
2
|
+
repositories {
|
|
3
|
+
google()
|
|
4
|
+
mavenCentral()
|
|
5
|
+
gradlePluginPortal()
|
|
6
|
+
}
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
dependencyResolutionManagement {
|
|
10
|
+
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
|
|
11
|
+
repositories {
|
|
12
|
+
google()
|
|
13
|
+
mavenCentral()
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
rootProject.name = "{{APP_NAME}}"
|
|
18
|
+
include(":app")
|