Compare commits

...

21 Commits

Author SHA1 Message Date
Yang 62dbb605bb Merge branch 'main' into release/v2
* main:
  Prepare for release 2.33.0.
  Fix avd path on ubuntu-24.04 - attempt 2 (#415)
  Revert creating avd directory. (#414)
  Fix SDK path issues with ubuntu-24.04 (#409)
  SDK build tools 35.0.0, command-line tools 16.0. (#408)
  Avoid changing the owner of unnecessary files (#406)
  Update npm packages. (#401)
2024-10-12 17:43:32 +11:00
Yang c77bfe7c0b Prepare for release 2.33.0. 2024-10-12 17:42:24 +11:00
Yang ead704cc5a Fix avd path on ubuntu-24.04 - attempt 2 (#415) 2024-10-12 17:26:36 +11:00
Yang e800ffffe6 Revert creating avd directory. (#414) 2024-10-11 13:55:44 +11:00
Yang 8c07710601 Fix SDK path issues with ubuntu-24.04 (#409) 2024-10-11 11:55:47 +11:00
Yang 3a18f50216 SDK build tools 35.0.0, command-line tools 16.0. (#408) 2024-10-07 00:50:35 +11:00
Justin Brooks 1b985f4c7a Avoid changing the owner of unnecessary files (#406)
* Avoid changing the owner of unnecessary files

Source files shouldn't matter for the purposes of this tool.
% ls -R $ANDROID_HOME/sources/android-34 | wc -l
   17750

* Remove non-existant directory

* Avoid another unnecessary chown

* Push js
2024-10-05 12:53:35 +10:00
Yang a3dcdb348b Update npm packages. (#401) 2024-07-09 16:23:18 +10:00
Yang f0d1ed2dca Merge branch 'main' into release/v2
* main:
  Prepare for release 2.32.0.
  Add missing compiled js files from #383.
  Support customizing emulator port (#383)
2024-07-09 12:55:08 +10:00
Yang 81f860b51a Prepare for release 2.32.0. 2024-07-09 12:53:57 +10:00
Yang e93b947104 Add missing compiled js files from #383. 2024-07-09 12:51:00 +10:00
Kamil Bąk 4b0628e9f8 Support customizing emulator port (#383)
* Add port parameter

* Fix a typo in test description

* Fix avd not being started with correct port

* Fix wrong port being used to kill an emulator if there was an exception
2024-07-02 22:42:44 +10:00
Yang 77986be265 Merge branch 'main' into release/v2
* main:
  Prepare for release 2.31.0.
  Install platforms for the specified api level (#384)
  Add api level `VanillaIceCream` support (#378)
  Bump Gradle wrapper validation from v1 to v2 to use Node 20 (#374)
  Migrate to Node 20 on CI via GitHub Actions major upgrades (#372)
2024-05-25 00:02:03 +10:00
Yang ca77a1081f Prepare for release 2.31.0. 2024-05-25 00:00:37 +10:00
Josh Lesch 1fef06a960 Install platforms for the specified api level (#384)
* Install platforms for the specified api level

* Fix typo
2024-03-28 09:40:07 +11:00
LoveSy d8da5b6410 Add api level VanillaIceCream support (#378) 2024-02-18 10:14:24 +11:00
Róbert Papp a0c0e7216b Bump Gradle wrapper validation from v1 to v2 to use Node 20 (#374) 2024-01-30 08:34:22 +11:00
Róbert Papp 9d5d6236f4 Migrate to Node 20 on CI via GitHub Actions major upgrades (#372)
* Update first party actions to Node 20 majors.

* Update Gradle cache actions to Node 20 majors.
2024-01-27 23:11:47 +11:00
Yang 6b0df4b0ef Merge branch 'main' into release/v2
* main:
  Prepare for release 2.30.1.
  Run the action on Node 20 (#371)
2024-01-26 23:28:10 +11:00
Yang bc2cd2aaea Prepare for release 2.30.1. 2024-01-26 23:26:22 +11:00
Róbert Papp 61a61f94a9 Run the action on Node 20 (#371) 2024-01-26 23:24:19 +11:00
20 changed files with 215 additions and 129 deletions
+1 -1
View File
@@ -9,5 +9,5 @@ jobs:
validate-typings: validate-typings:
runs-on: "ubuntu-latest" runs-on: "ubuntu-latest"
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v4
- uses: krzema12/github-actions-typing@v0 - uses: krzema12/github-actions-typing@v0
+21 -31
View File
@@ -18,41 +18,31 @@ jobs:
timeout-minutes: 15 timeout-minutes: 15
strategy: strategy:
matrix: matrix:
os: [ubuntu-latest]
api-level: [23, 29]
target: [default, google_apis]
arch: [x86]
exclude:
- target: google_apis
api-level: 16
- target: google_apis
api-level: 23
- target: google_apis
api-level: 29
include: include:
- os: ubuntu-latest - os: ubuntu-22.04
api-level: 23
target: default
arch: x86
- os: ubuntu-24.04
api-level: 24 api-level: 24
target: playstore target: playstore
arch: x86 arch: x86
- os: ubuntu-latest - os: macos-13
api-level: 30
target: aosp_atd
arch: x86
- os: macos-latest
api-level: 31 api-level: 31
target: google_apis target: default
arch: x86_64 arch: x86_64
- os: ubuntu-latest - os: ubuntu-24.04
api-level: 34 api-level: 34
target: aosp_atd target: aosp_atd
arch: x86_64 arch: x86_64
- os: ubuntu-lastest
api-level: 35
target: google_apis
arch: x86_64
steps: steps:
- name: checkout - name: checkout
uses: actions/checkout@v3 uses: actions/checkout@v4
- name: validate gradle wrapper
uses: gradle/wrapper-validation-action@v1
- name: build, test and lint - name: build, test and lint
run: | run: |
@@ -61,25 +51,25 @@ jobs:
npm run lint npm run lint
npm test npm test
- uses: actions/setup-java@v3 - uses: actions/setup-java@v4
with: with:
distribution: 'zulu' distribution: 'zulu'
java-version: 21 java-version: 23
- uses: actions/cache@v3 - uses: actions/cache@v4
id: avd-cache id: avd-cache
with: with:
path: | path: |
~/.android/avd/* ~/.android/avd/*
~/.android/adb* ~/.android/adb*
~/.android/debug.keystore ~/.android/debug.keystore
key: avd-${{ matrix.api-level }}-${{ matrix.os }}-${{ matrix.target }} key: avd-${{ matrix.api-level }}-${{ matrix.os }}-${{ matrix.target }}-${{ matrix.arch }}
- uses: gradle/actions/setup-gradle@v4
- name: assemble tests - name: assemble tests
uses: gradle/gradle-build-action@v2 working-directory: test-fixture
with: run: ./gradlew assembleAndroidTest
build-root-directory: test-fixture
arguments: assembleAndroidTest
- name: enable KVM for linux runners - name: enable KVM for linux runners
if: runner.os == 'Linux' if: runner.os == 'Linux'
+6 -11
View File
@@ -9,14 +9,14 @@ on:
api-level: api-level:
description: 'API level of the platform and system image' description: 'API level of the platform and system image'
required: true required: true
default: '30' default: '34'
target: target:
description: 'target of the system image - default, google_apis, google_apis_playstore, aosp_atd, google_atd, android-wear, android-wear-cn, android-tv or google-tv' description: 'target of the system image - default, google_apis, google_apis_playstore, aosp_atd, google_atd, android-wear, android-wear-cn, android-tv or google-tv'
required: true required: true
default: 'default' default: 'default'
arch: arch:
description: 'CPU architecture of the system image - x86, x86_64 or arm64-v8a' description: 'CPU architecture of the system image - x86, x86_64 or arm64-v8a'
default: 'x86' default: 'x86_64'
emulator-options: emulator-options:
description: 'command-line options used when launching the emulator' description: 'command-line options used when launching the emulator'
default: '-no-window -gpu swiftshader_indirect -no-snapshot -noaudio -no-boot-anim' default: '-no-window -gpu swiftshader_indirect -no-snapshot -noaudio -no-boot-anim'
@@ -39,10 +39,7 @@ jobs:
steps: steps:
- name: checkout - name: checkout
uses: actions/checkout@v3 uses: actions/checkout@v4
- name: validate gradle wrapper
uses: gradle/wrapper-validation-action@v1
- name: build, test and lint - name: build, test and lint
run: | run: |
@@ -51,14 +48,12 @@ jobs:
npm run lint npm run lint
npm test npm test
- uses: actions/setup-java@v3 - uses: actions/setup-java@v4
with: with:
distribution: 'zulu' distribution: 'zulu'
java-version: 21 java-version: 23
- uses: gradle/gradle-build-action@v2 - uses: gradle/actions/setup-gradle@v4
with:
gradle-home-cache-cleanup: true
- name: enable KVM for linux runners - name: enable KVM for linux runners
if: runner.os == 'Linux' if: runner.os == 'Linux'
+21
View File
@@ -1,5 +1,26 @@
# Change Log # Change Log
## v2.33.0
* Fix missing AVD directory in `ubuntu-24.04` runner. - [415](https://github.com/ReactiveCircus/android-emulator-runner/pull/415)
* Update SDK build tools to `35.0.0`, update SDK command-line tools to `16.0`. - [#356](https://github.com/ReactiveCircus/android-emulator-runner/pull/356)
* Stop changing owner of the SDK directory. - [406](https://github.com/ReactiveCircus/android-emulator-runner/pull/406) [#409](https://github.com/ReactiveCircus/android-emulator-runner/pull/409)
* Upgrade to latest npm dependencies. - [#401](https://github.com/ReactiveCircus/android-emulator-runner/pull/401)
## v2.32.0
* Add `port` parameter for customizing the emulator port to use. - [#383](https://github.com/ReactiveCircus/android-emulator-runner/pull/383)
## v2.31.0
* Support setting `VanillaIceCream` as `api-level`. - [#378](https://github.com/ReactiveCircus/android-emulator-runner/pull/378)
* Install `platforms` for the specified `api-level`. - [#384](https://github.com/ReactiveCircus/android-emulator-runner/pull/384)
## v2.30.1
* Run action on Node 20. - [#371](https://github.com/ReactiveCircus/android-emulator-runner/pull/371)
## v2.30.0 ## v2.30.0
* Update to Node 20. - [#369](https://github.com/ReactiveCircus/android-emulator-runner/pull/369) * Update to Node 20. - [#369](https://github.com/ReactiveCircus/android-emulator-runner/pull/369)
+9 -8
View File
@@ -49,7 +49,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: checkout - name: checkout
uses: actions/checkout@v3 uses: actions/checkout@v4
- name: Enable KVM - name: Enable KVM
run: | run: |
@@ -76,7 +76,7 @@ jobs:
target: [default, google_apis] target: [default, google_apis]
steps: steps:
- name: checkout - name: checkout
uses: actions/checkout@v3 uses: actions/checkout@v4
- name: Enable KVM - name: Enable KVM
run: | run: |
@@ -102,7 +102,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: checkout - name: checkout
uses: actions/checkout@v3 uses: actions/checkout@v4
- name: Enable KVM - name: Enable KVM
run: | run: |
@@ -121,8 +121,8 @@ jobs:
We can significantly reduce emulator startup time by setting up AVD snapshot caching: We can significantly reduce emulator startup time by setting up AVD snapshot caching:
1. add a `gradle/gradle-build-action@v2` step for caching Gradle, more details see [#229](https://github.com/ReactiveCircus/android-emulator-runner/issues/229) 1. add a `gradle/actions/setup-gradle@v4` step for caching Gradle, more details see [#229](https://github.com/ReactiveCircus/android-emulator-runner/issues/229)
2. add an `actions/cache@v3` step for caching the `avd` 2. add an `actions/cache@v4` step for caching the `avd`
3. add a `reactivecircus/android-emulator-runner@v2` step to generate a clean snapshot - specify `emulator-options` without `no-snapshot` 3. add a `reactivecircus/android-emulator-runner@v2` step to generate a clean snapshot - specify `emulator-options` without `no-snapshot`
4. add another `reactivecircus/android-emulator-runner@v2` step to run your tests using existing AVD / snapshot - specify `emulator-options` with `no-snapshot-save` 4. add another `reactivecircus/android-emulator-runner@v2` step to run your tests using existing AVD / snapshot - specify `emulator-options` with `no-snapshot-save`
@@ -135,7 +135,7 @@ jobs:
api-level: [21, 23, 29] api-level: [21, 23, 29]
steps: steps:
- name: checkout - name: checkout
uses: actions/checkout@v3 uses: actions/checkout@v4
- name: Enable KVM - name: Enable KVM
run: | run: |
@@ -144,10 +144,10 @@ jobs:
sudo udevadm trigger --name-match=kvm sudo udevadm trigger --name-match=kvm
- name: Gradle cache - name: Gradle cache
uses: gradle/gradle-build-action@v2 uses: gradle/actions/setup-gradle@v3
- name: AVD cache - name: AVD cache
uses: actions/cache@v3 uses: actions/cache@v4
id: avd-cache id: avd-cache
with: with:
path: | path: |
@@ -191,6 +191,7 @@ jobs:
| `avd-name` | Optional | `test` | Custom AVD name used for creating the Android Virtual Device. | | `avd-name` | Optional | `test` | Custom AVD name used for creating the Android Virtual Device. |
| `force-avd-creation` | Optional | `true` | Whether to force create the AVD by overwriting an existing AVD with the same name as `avd-name` - `true` or `false`. | | `force-avd-creation` | Optional | `true` | Whether to force create the AVD by overwriting an existing AVD with the same name as `avd-name` - `true` or `false`. |
| `emulator-boot-timeout` | Optional | `600` | Emulator boot timeout in seconds. If it takes longer to boot, the action would fail - e.g. `300` for 5 minutes. | | `emulator-boot-timeout` | Optional | `600` | Emulator boot timeout in seconds. If it takes longer to boot, the action would fail - e.g. `300` for 5 minutes. |
| `emulator-port` | Optional | `5554` | Emulator port to use. Allows to run this action on multiple workers on a single machine at the same time. This input is available for the script as `EMULATOR_PORT` enviromental variable. This port is automatically used by android device related tasks in gradle |
| `emulator-options` | Optional | See below | Command-line options used when launching the emulator (replacing all default options) - e.g. `-no-window -no-snapshot -camera-back emulated`. | | `emulator-options` | Optional | See below | Command-line options used when launching the emulator (replacing all default options) - e.g. `-no-window -no-snapshot -camera-back emulated`. |
| `disable-animations` | Optional | `true` | Whether to disable animations - `true` or `false`. | | `disable-animations` | Optional | `true` | Whether to disable animations - `true` or `false`. |
| `disable-spellchecker` | Optional | `false` | Whether to disable spellchecker - `true` or `false`. | | `disable-spellchecker` | Optional | `false` | Whether to disable spellchecker - `true` or `false`. |
+28
View File
@@ -1,4 +1,5 @@
import * as validator from '../src/input-validator'; import * as validator from '../src/input-validator';
import { MAX_PORT, MIN_PORT } from '../src/input-validator';
describe('api-level validator tests', () => { describe('api-level validator tests', () => {
it('Throws if api-level is not a number', () => { it('Throws if api-level is not a number', () => {
@@ -172,6 +173,33 @@ describe('force-avd-creation validator tests', () => {
}); });
}); });
describe('emulator-port validator tests', () => {
it('Validates if emulator-port is even and in range', () => {
const func = () => {
validator.checkPort(5554);
};
expect(func).not.toThrow();
});
it('Throws if emulator-port is lower than MIN_PORT', () => {
const func = () => {
validator.checkPort(MIN_PORT - 2);
};
expect(func).toThrow();
});
it('Throws if emulator-port is higher than MAX_PORT', () => {
const func = () => {
validator.checkPort(MAX_PORT + 2);
};
expect(func).toThrow();
});
it('Throws if emulator-port is odd', () => {
const func = () => {
validator.checkPort(5555);
};
expect(func).toThrow();
});
});
describe('disable-animations validator tests', () => { describe('disable-animations validator tests', () => {
it('Throws if disable-animations is not a boolean', () => { it('Throws if disable-animations is not a boolean', () => {
const func = () => { const func = () => {
+2
View File
@@ -37,6 +37,8 @@ inputs:
type: boolean type: boolean
emulator-boot-timeout: emulator-boot-timeout:
type: integer type: integer
emulator-port:
type: integer
emulator-options: emulator-options:
type: string type: string
disable-animations: disable-animations:
+4 -1
View File
@@ -36,6 +36,9 @@ inputs:
emulator-boot-timeout: emulator-boot-timeout:
description: 'Emulator boot timeout in seconds. If it takes longer to boot, the action would fail - e.g. `300` for 5 minutes' description: 'Emulator boot timeout in seconds. If it takes longer to boot, the action would fail - e.g. `300` for 5 minutes'
default: '600' default: '600'
emulator-port:
description: 'Port to run emulator on, allows to run multiple emulators on the same physical machine'
default: '5554'
emulator-options: emulator-options:
description: 'command-line options used when launching the emulator - e.g. `-no-window -no-snapshot -camera-back emulated`' description: 'command-line options used when launching the emulator - e.g. `-no-window -no-snapshot -camera-back emulated`'
default: '-no-window -gpu swiftshader_indirect -no-snapshot -noaudio -no-boot-anim' default: '-no-window -gpu swiftshader_indirect -no-snapshot -noaudio -no-boot-anim'
@@ -68,5 +71,5 @@ inputs:
pre-emulator-launch-script: pre-emulator-launch-script:
description: 'custom script to run after creating the AVD and before launching the emulator - e.g. `./adjust-emulator-configs.sh`' description: 'custom script to run after creating the AVD and before launching the emulator - e.g. `./adjust-emulator-configs.sh`'
runs: runs:
using: 'node16' using: 'node20'
main: 'lib/main.js' main: 'lib/main.js'
+18 -13
View File
@@ -38,7 +38,7 @@ const fs = __importStar(require("fs"));
/** /**
* Creates and launches a new AVD instance with the specified configurations. * Creates and launches a new AVD instance with the specified configurations.
*/ */
function launchEmulator(apiLevel, target, arch, profile, cores, ramSize, heapSize, sdcardPathOrSize, diskSize, avdName, forceAvdCreation, emulatorBootTimeout, emulatorOptions, disableAnimations, disableSpellChecker, disableLinuxHardwareAcceleration, enableHardwareKeyboard) { function launchEmulator(apiLevel, target, arch, profile, cores, ramSize, heapSize, sdcardPathOrSize, diskSize, avdName, forceAvdCreation, emulatorBootTimeout, port, emulatorOptions, disableAnimations, disableSpellChecker, disableLinuxHardwareAcceleration, enableHardwareKeyboard) {
return __awaiter(this, void 0, void 0, function* () { return __awaiter(this, void 0, void 0, function* () {
try { try {
console.log(`::group::Launch Emulator`); console.log(`::group::Launch Emulator`);
@@ -72,7 +72,7 @@ function launchEmulator(apiLevel, target, arch, profile, cores, ramSize, heapSiz
} }
// start emulator // start emulator
console.log('Starting emulator.'); console.log('Starting emulator.');
yield exec.exec(`sh -c \\"${process.env.ANDROID_HOME}/emulator/emulator -avd "${avdName}" ${emulatorOptions} &"`, [], { yield exec.exec(`sh -c \\"${process.env.ANDROID_HOME}/emulator/emulator -port ${port} -avd "${avdName}" ${emulatorOptions} &"`, [], {
listeners: { listeners: {
stderr: (data) => { stderr: (data) => {
if (data.toString().includes('invalid command-line parameter')) { if (data.toString().includes('invalid command-line parameter')) {
@@ -82,19 +82,19 @@ function launchEmulator(apiLevel, target, arch, profile, cores, ramSize, heapSiz
}, },
}); });
// wait for emulator to complete booting // wait for emulator to complete booting
yield waitForDevice(emulatorBootTimeout); yield waitForDevice(port, emulatorBootTimeout);
yield exec.exec(`adb shell input keyevent 82`); yield adb(port, `shell input keyevent 82`);
if (disableAnimations) { if (disableAnimations) {
console.log('Disabling animations.'); console.log('Disabling animations.');
yield exec.exec(`adb shell settings put global window_animation_scale 0.0`); yield adb(port, `shell settings put global window_animation_scale 0.0`);
yield exec.exec(`adb shell settings put global transition_animation_scale 0.0`); yield adb(port, `shell settings put global transition_animation_scale 0.0`);
yield exec.exec(`adb shell settings put global animator_duration_scale 0.0`); yield adb(port, `shell settings put global animator_duration_scale 0.0`);
} }
if (disableSpellChecker) { if (disableSpellChecker) {
yield exec.exec(`adb shell settings put secure spell_checker_enabled 0`); yield adb(port, `shell settings put secure spell_checker_enabled 0`);
} }
if (enableHardwareKeyboard) { if (enableHardwareKeyboard) {
yield exec.exec(`adb shell settings put secure show_ime_with_hard_keyboard 0`); yield adb(port, `shell settings put secure show_ime_with_hard_keyboard 0`);
} }
} }
finally { finally {
@@ -106,11 +106,11 @@ exports.launchEmulator = launchEmulator;
/** /**
* Kills the running emulator on the default port. * Kills the running emulator on the default port.
*/ */
function killEmulator() { function killEmulator(port) {
return __awaiter(this, void 0, void 0, function* () { return __awaiter(this, void 0, void 0, function* () {
try { try {
console.log(`::group::Terminate Emulator`); console.log(`::group::Terminate Emulator`);
yield exec.exec(`adb -s emulator-5554 emu kill`); yield adb(port, `emu kill`);
} }
catch (error) { catch (error) {
console.log(error instanceof Error ? error.message : error); console.log(error instanceof Error ? error.message : error);
@@ -121,10 +121,15 @@ function killEmulator() {
}); });
} }
exports.killEmulator = killEmulator; exports.killEmulator = killEmulator;
function adb(port, command) {
return __awaiter(this, void 0, void 0, function* () {
return yield exec.exec(`adb -s emulator-${port} ${command}`);
});
}
/** /**
* Wait for emulator to boot. * Wait for emulator to boot.
*/ */
function waitForDevice(emulatorBootTimeout) { function waitForDevice(port, emulatorBootTimeout) {
return __awaiter(this, void 0, void 0, function* () { return __awaiter(this, void 0, void 0, function* () {
let booted = false; let booted = false;
let attempts = 0; let attempts = 0;
@@ -133,7 +138,7 @@ function waitForDevice(emulatorBootTimeout) {
while (!booted) { while (!booted) {
try { try {
let result = ''; let result = '';
yield exec.exec(`adb shell getprop sys.boot_completed`, [], { yield exec.exec(`adb -s emulator-${port} shell getprop sys.boot_completed`, [], {
listeners: { listeners: {
stdout: (data) => { stdout: (data) => {
result += data.toString(); result += data.toString();
+14 -2
View File
@@ -1,12 +1,15 @@
"use strict"; "use strict";
Object.defineProperty(exports, "__esModule", { value: true }); Object.defineProperty(exports, "__esModule", { value: true });
exports.checkDiskSize = exports.checkEmulatorBuild = exports.checkEnableHardwareKeyboard = exports.checkDisableLinuxHardwareAcceleration = exports.checkDisableSpellchecker = exports.checkDisableAnimations = exports.checkForceAvdCreation = exports.checkChannel = exports.checkArch = exports.checkTarget = exports.checkApiLevel = exports.VALID_CHANNELS = exports.VALID_ARCHS = exports.VALID_TARGETS = exports.MIN_API_LEVEL = void 0; exports.checkDiskSize = exports.checkEmulatorBuild = exports.checkEnableHardwareKeyboard = exports.checkDisableLinuxHardwareAcceleration = exports.checkDisableSpellchecker = exports.checkDisableAnimations = exports.checkPort = exports.checkForceAvdCreation = exports.checkChannel = exports.checkArch = exports.checkTarget = exports.checkApiLevel = exports.PREVIEW_API_LEVELS = exports.MAX_PORT = exports.MIN_PORT = exports.VALID_CHANNELS = exports.VALID_ARCHS = exports.VALID_TARGETS = exports.MIN_API_LEVEL = void 0;
exports.MIN_API_LEVEL = 15; exports.MIN_API_LEVEL = 15;
exports.VALID_TARGETS = ['default', 'google_apis', 'aosp_atd', 'google_atd', 'google_apis_playstore', 'android-wear', 'android-wear-cn', 'android-tv', 'google-tv']; exports.VALID_TARGETS = ['default', 'google_apis', 'aosp_atd', 'google_atd', 'google_apis_playstore', 'android-wear', 'android-wear-cn', 'android-tv', 'google-tv'];
exports.VALID_ARCHS = ['x86', 'x86_64', 'arm64-v8a']; exports.VALID_ARCHS = ['x86', 'x86_64', 'arm64-v8a'];
exports.VALID_CHANNELS = ['stable', 'beta', 'dev', 'canary']; exports.VALID_CHANNELS = ['stable', 'beta', 'dev', 'canary'];
exports.MIN_PORT = 5554;
exports.MAX_PORT = 5584;
exports.PREVIEW_API_LEVELS = ['Tiramisu', 'UpsideDownCake', 'VanillaIceCream'];
function checkApiLevel(apiLevel) { function checkApiLevel(apiLevel) {
if (apiLevel.startsWith('UpsideDownCake') || apiLevel === 'TiramisuPrivacySandbox') if (exports.PREVIEW_API_LEVELS.some((previewLevel) => apiLevel.startsWith(previewLevel)))
return; return;
if (isNaN(Number(apiLevel)) || !Number.isInteger(Number(apiLevel))) { if (isNaN(Number(apiLevel)) || !Number.isInteger(Number(apiLevel))) {
throw new Error(`Unexpected API level: '${apiLevel}'.`); throw new Error(`Unexpected API level: '${apiLevel}'.`);
@@ -40,6 +43,15 @@ function checkForceAvdCreation(forceAvdCreation) {
} }
} }
exports.checkForceAvdCreation = checkForceAvdCreation; exports.checkForceAvdCreation = checkForceAvdCreation;
function checkPort(port) {
if (port < exports.MIN_PORT || port > exports.MAX_PORT) {
throw new Error(`Emulator port is outside of the supported port range [${exports.MIN_PORT}, ${exports.MAX_PORT}], was ${port}`);
}
if (port % 2 == 1) {
throw new Error(`Emulator port has to be even, was ${port}`);
}
}
exports.checkPort = checkPort;
function checkDisableAnimations(disableAnimations) { function checkDisableAnimations(disableAnimations) {
if (!isValidBoolean(disableAnimations)) { if (!isValidBoolean(disableAnimations)) {
throw new Error(`Input for input.disable-animations should be either 'true' or 'false'.`); throw new Error(`Input for input.disable-animations should be either 'true' or 'false'.`);
+11 -4
View File
@@ -42,6 +42,7 @@ const channel_id_mapper_1 = require("./channel-id-mapper");
const fs_1 = require("fs"); const fs_1 = require("fs");
function run() { function run() {
return __awaiter(this, void 0, void 0, function* () { return __awaiter(this, void 0, void 0, function* () {
let port = input_validator_1.MIN_PORT;
try { try {
console.log(`::group::Configure emulator`); console.log(`::group::Configure emulator`);
let linuxSupportKVM = false; let linuxSupportKVM = false;
@@ -102,6 +103,10 @@ function run() {
// Emulator boot timeout seconds // Emulator boot timeout seconds
const emulatorBootTimeout = parseInt(core.getInput('emulator-boot-timeout'), 10); const emulatorBootTimeout = parseInt(core.getInput('emulator-boot-timeout'), 10);
console.log(`Emulator boot timeout: ${emulatorBootTimeout}`); console.log(`Emulator boot timeout: ${emulatorBootTimeout}`);
// Emulator port to use
port = parseInt(core.getInput('emulator-port'), 10);
(0, input_validator_1.checkPort)(port);
console.log(`emulator port: ${port}`);
// emulator options // emulator options
const emulatorOptions = core.getInput('emulator-options').trim(); const emulatorOptions = core.getInput('emulator-options').trim();
console.log(`emulator options: ${emulatorOptions}`); console.log(`emulator options: ${emulatorOptions}`);
@@ -193,7 +198,7 @@ function run() {
console.log(`::endgroup::`); console.log(`::endgroup::`);
} }
// launch an emulator // launch an emulator
yield (0, emulator_manager_1.launchEmulator)(apiLevel, target, arch, profile, cores, ramSize, heapSize, sdcardPathOrSize, diskSize, avdName, forceAvdCreation, emulatorBootTimeout, emulatorOptions, disableAnimations, disableSpellchecker, disableLinuxHardwareAcceleration, enableHardwareKeyboard); yield (0, emulator_manager_1.launchEmulator)(apiLevel, target, arch, profile, cores, ramSize, heapSize, sdcardPathOrSize, diskSize, avdName, forceAvdCreation, emulatorBootTimeout, port, emulatorOptions, disableAnimations, disableSpellchecker, disableLinuxHardwareAcceleration, enableHardwareKeyboard);
// execute the custom script // execute the custom script
try { try {
// move to custom working directory if set // move to custom working directory if set
@@ -203,18 +208,20 @@ function run() {
for (const script of scripts) { for (const script of scripts) {
// use array form to avoid various quote escaping problems // use array form to avoid various quote escaping problems
// caused by exec(`sh -c "${script}"`) // caused by exec(`sh -c "${script}"`)
yield exec.exec('sh', ['-c', script]); yield exec.exec('sh', ['-c', script], {
env: Object.assign(Object.assign({}, process.env), { EMULATOR_PORT: `${port}`, ANDROID_SERIAL: `emulator-${port}` }),
});
} }
} }
catch (error) { catch (error) {
core.setFailed(error instanceof Error ? error.message : error); core.setFailed(error instanceof Error ? error.message : error);
} }
// finally kill the emulator // finally kill the emulator
yield (0, emulator_manager_1.killEmulator)(); yield (0, emulator_manager_1.killEmulator)(port);
} }
catch (error) { catch (error) {
// kill the emulator so the action can exit // kill the emulator so the action can exit
yield (0, emulator_manager_1.killEmulator)(); yield (0, emulator_manager_1.killEmulator)(port);
core.setFailed(error instanceof Error ? error.message : error); core.setFailed(error instanceof Error ? error.message : error);
} }
}); });
+6 -8
View File
@@ -38,10 +38,10 @@ const exec = __importStar(require("@actions/exec"));
const io = __importStar(require("@actions/io")); const io = __importStar(require("@actions/io"));
const tc = __importStar(require("@actions/tool-cache")); const tc = __importStar(require("@actions/tool-cache"));
const fs = __importStar(require("fs")); const fs = __importStar(require("fs"));
const BUILD_TOOLS_VERSION = '34.0.0'; const BUILD_TOOLS_VERSION = '35.0.0';
// SDK command-line tools 11.0 // SDK command-line tools 16.0
const CMDLINE_TOOLS_URL_MAC = 'https://dl.google.com/android/repository/commandlinetools-mac-10406996_latest.zip'; const CMDLINE_TOOLS_URL_MAC = 'https://dl.google.com/android/repository/commandlinetools-mac-12266719_latest.zip';
const CMDLINE_TOOLS_URL_LINUX = 'https://dl.google.com/android/repository/commandlinetools-linux-10406996_latest.zip'; const CMDLINE_TOOLS_URL_LINUX = 'https://dl.google.com/android/repository/commandlinetools-linux-12266719_latest.zip';
/** /**
* Installs & updates the Android SDK for the macOS platform, including SDK platform for the chosen API level, latest build tools, platform tools, Android Emulator, * Installs & updates the Android SDK for the macOS platform, including SDK platform for the chosen API level, latest build tools, platform tools, Android Emulator,
* and the system image for the chosen API level, CPU arch, and target. * and the system image for the chosen API level, CPU arch, and target.
@@ -52,9 +52,6 @@ function installAndroidSdk(apiLevel, target, arch, channelId, emulatorBuild, ndk
console.log(`::group::Install Android SDK`); console.log(`::group::Install Android SDK`);
const isOnMac = process.platform === 'darwin'; const isOnMac = process.platform === 'darwin';
const isArm = process.arch === 'arm64'; const isArm = process.arch === 'arm64';
if (!isOnMac) {
yield exec.exec(`sh -c \\"sudo chown $USER:$USER ${process.env.ANDROID_HOME} -R`);
}
const cmdlineToolsPath = `${process.env.ANDROID_HOME}/cmdline-tools`; const cmdlineToolsPath = `${process.env.ANDROID_HOME}/cmdline-tools`;
if (!fs.existsSync(cmdlineToolsPath)) { if (!fs.existsSync(cmdlineToolsPath)) {
console.log('Installing new cmdline-tools.'); console.log('Installing new cmdline-tools.');
@@ -66,11 +63,12 @@ function installAndroidSdk(apiLevel, target, arch, channelId, emulatorBuild, ndk
// add paths for commandline-tools and platform-tools // add paths for commandline-tools and platform-tools
core.addPath(`${cmdlineToolsPath}/latest:${cmdlineToolsPath}/latest/bin:${process.env.ANDROID_HOME}/platform-tools`); core.addPath(`${cmdlineToolsPath}/latest:${cmdlineToolsPath}/latest/bin:${process.env.ANDROID_HOME}/platform-tools`);
// set standard AVD path // set standard AVD path
yield io.mkdirP(`${process.env.HOME}/.android/avd`);
core.exportVariable('ANDROID_AVD_HOME', `${process.env.HOME}/.android/avd`); core.exportVariable('ANDROID_AVD_HOME', `${process.env.HOME}/.android/avd`);
// accept all Android SDK licenses // accept all Android SDK licenses
yield exec.exec(`sh -c \\"yes | sdkmanager --licenses > /dev/null"`); yield exec.exec(`sh -c \\"yes | sdkmanager --licenses > /dev/null"`);
console.log('Installing latest build tools, platform tools, and platform.'); console.log('Installing latest build tools, platform tools, and platform.');
yield exec.exec(`sh -c \\"sdkmanager --install 'build-tools;${BUILD_TOOLS_VERSION}' platform-tools > /dev/null"`); yield exec.exec(`sh -c \\"sdkmanager --install 'build-tools;${BUILD_TOOLS_VERSION}' platform-tools 'platforms;android-${apiLevel}'> /dev/null"`);
console.log('Installing latest emulator.'); console.log('Installing latest emulator.');
yield exec.exec(`sh -c \\"sdkmanager --install emulator --channel=${channelId} > /dev/null"`); yield exec.exec(`sh -c \\"sdkmanager --install emulator --channel=${channelId} > /dev/null"`);
if (emulatorBuild) { if (emulatorBuild) {
+14 -14
View File
@@ -2105,12 +2105,12 @@
} }
}, },
"node_modules/braces": { "node_modules/braces": {
"version": "3.0.2", "version": "3.0.3",
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
"integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"fill-range": "^7.0.1" "fill-range": "^7.1.1"
}, },
"engines": { "engines": {
"node": ">=8" "node": ">=8"
@@ -3053,9 +3053,9 @@
} }
}, },
"node_modules/fill-range": { "node_modules/fill-range": {
"version": "7.0.1", "version": "7.1.1",
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
"integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"to-regex-range": "^5.0.1" "to-regex-range": "^5.0.1"
@@ -7802,12 +7802,12 @@
} }
}, },
"braces": { "braces": {
"version": "3.0.2", "version": "3.0.3",
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
"integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
"dev": true, "dev": true,
"requires": { "requires": {
"fill-range": "^7.0.1" "fill-range": "^7.1.1"
} }
}, },
"browserslist": { "browserslist": {
@@ -8505,9 +8505,9 @@
} }
}, },
"fill-range": { "fill-range": {
"version": "7.0.1", "version": "7.1.1",
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
"integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
"dev": true, "dev": true,
"requires": { "requires": {
"to-regex-range": "^5.0.1" "to-regex-range": "^5.0.1"
+17 -12
View File
@@ -17,6 +17,7 @@ export async function launchEmulator(
avdName: string, avdName: string,
forceAvdCreation: boolean, forceAvdCreation: boolean,
emulatorBootTimeout: number, emulatorBootTimeout: number,
port: number,
emulatorOptions: string, emulatorOptions: string,
disableAnimations: boolean, disableAnimations: boolean,
disableSpellChecker: boolean, disableSpellChecker: boolean,
@@ -65,7 +66,7 @@ export async function launchEmulator(
// start emulator // start emulator
console.log('Starting emulator.'); console.log('Starting emulator.');
await exec.exec(`sh -c \\"${process.env.ANDROID_HOME}/emulator/emulator -avd "${avdName}" ${emulatorOptions} &"`, [], { await exec.exec(`sh -c \\"${process.env.ANDROID_HOME}/emulator/emulator -port ${port} -avd "${avdName}" ${emulatorOptions} &"`, [], {
listeners: { listeners: {
stderr: (data: Buffer) => { stderr: (data: Buffer) => {
if (data.toString().includes('invalid command-line parameter')) { if (data.toString().includes('invalid command-line parameter')) {
@@ -76,20 +77,20 @@ export async function launchEmulator(
}); });
// wait for emulator to complete booting // wait for emulator to complete booting
await waitForDevice(emulatorBootTimeout); await waitForDevice(port, emulatorBootTimeout);
await exec.exec(`adb shell input keyevent 82`); await adb(port, `shell input keyevent 82`);
if (disableAnimations) { if (disableAnimations) {
console.log('Disabling animations.'); console.log('Disabling animations.');
await exec.exec(`adb shell settings put global window_animation_scale 0.0`); await adb(port, `shell settings put global window_animation_scale 0.0`);
await exec.exec(`adb shell settings put global transition_animation_scale 0.0`); await adb(port, `shell settings put global transition_animation_scale 0.0`);
await exec.exec(`adb shell settings put global animator_duration_scale 0.0`); await adb(port, `shell settings put global animator_duration_scale 0.0`);
} }
if (disableSpellChecker) { if (disableSpellChecker) {
await exec.exec(`adb shell settings put secure spell_checker_enabled 0`); await adb(port, `shell settings put secure spell_checker_enabled 0`);
} }
if (enableHardwareKeyboard) { if (enableHardwareKeyboard) {
await exec.exec(`adb shell settings put secure show_ime_with_hard_keyboard 0`); await adb(port, `shell settings put secure show_ime_with_hard_keyboard 0`);
} }
} finally { } finally {
console.log(`::endgroup::`); console.log(`::endgroup::`);
@@ -99,10 +100,10 @@ export async function launchEmulator(
/** /**
* Kills the running emulator on the default port. * Kills the running emulator on the default port.
*/ */
export async function killEmulator(): Promise<void> { export async function killEmulator(port: number): Promise<void> {
try { try {
console.log(`::group::Terminate Emulator`); console.log(`::group::Terminate Emulator`);
await exec.exec(`adb -s emulator-5554 emu kill`); await adb(port, `emu kill`);
} catch (error) { } catch (error) {
console.log(error instanceof Error ? error.message : error); console.log(error instanceof Error ? error.message : error);
} finally { } finally {
@@ -110,10 +111,14 @@ export async function killEmulator(): Promise<void> {
} }
} }
async function adb(port: number, command: string): Promise<number> {
return await exec.exec(`adb -s emulator-${port} ${command}`);
}
/** /**
* Wait for emulator to boot. * Wait for emulator to boot.
*/ */
async function waitForDevice(emulatorBootTimeout: number): Promise<void> { async function waitForDevice(port: number, emulatorBootTimeout: number): Promise<void> {
let booted = false; let booted = false;
let attempts = 0; let attempts = 0;
const retryInterval = 2; // retry every 2 seconds const retryInterval = 2; // retry every 2 seconds
@@ -121,7 +126,7 @@ async function waitForDevice(emulatorBootTimeout: number): Promise<void> {
while (!booted) { while (!booted) {
try { try {
let result = ''; let result = '';
await exec.exec(`adb shell getprop sys.boot_completed`, [], { await exec.exec(`adb -s emulator-${port} shell getprop sys.boot_completed`, [], {
listeners: { listeners: {
stdout: (data: Buffer) => { stdout: (data: Buffer) => {
result += data.toString(); result += data.toString();
+13 -1
View File
@@ -2,9 +2,12 @@ export const MIN_API_LEVEL = 15;
export const VALID_TARGETS: Array<string> = ['default', 'google_apis', 'aosp_atd', 'google_atd', 'google_apis_playstore', 'android-wear', 'android-wear-cn', 'android-tv', 'google-tv']; export const VALID_TARGETS: Array<string> = ['default', 'google_apis', 'aosp_atd', 'google_atd', 'google_apis_playstore', 'android-wear', 'android-wear-cn', 'android-tv', 'google-tv'];
export const VALID_ARCHS: Array<string> = ['x86', 'x86_64', 'arm64-v8a']; export const VALID_ARCHS: Array<string> = ['x86', 'x86_64', 'arm64-v8a'];
export const VALID_CHANNELS: Array<string> = ['stable', 'beta', 'dev', 'canary']; export const VALID_CHANNELS: Array<string> = ['stable', 'beta', 'dev', 'canary'];
export const MIN_PORT = 5554;
export const MAX_PORT = 5584;
export const PREVIEW_API_LEVELS: Array<string> = ['Tiramisu', 'UpsideDownCake', 'VanillaIceCream'];
export function checkApiLevel(apiLevel: string): void { export function checkApiLevel(apiLevel: string): void {
if (apiLevel.startsWith('UpsideDownCake') || apiLevel === 'TiramisuPrivacySandbox') return; if (PREVIEW_API_LEVELS.some((previewLevel) => apiLevel.startsWith(previewLevel))) return;
if (isNaN(Number(apiLevel)) || !Number.isInteger(Number(apiLevel))) { if (isNaN(Number(apiLevel)) || !Number.isInteger(Number(apiLevel))) {
throw new Error(`Unexpected API level: '${apiLevel}'.`); throw new Error(`Unexpected API level: '${apiLevel}'.`);
} }
@@ -37,6 +40,15 @@ export function checkForceAvdCreation(forceAvdCreation: string): void {
} }
} }
export function checkPort(port: number): void {
if (port < MIN_PORT || port > MAX_PORT) {
throw new Error(`Emulator port is outside of the supported port range [${MIN_PORT}, ${MAX_PORT}], was ${port}`);
}
if (port % 2 == 1) {
throw new Error(`Emulator port has to be even, was ${port}`);
}
}
export function checkDisableAnimations(disableAnimations: string): void { export function checkDisableAnimations(disableAnimations: string): void {
if (!isValidBoolean(disableAnimations)) { if (!isValidBoolean(disableAnimations)) {
throw new Error(`Input for input.disable-animations should be either 'true' or 'false'.`); throw new Error(`Input for input.disable-animations should be either 'true' or 'false'.`);
+14 -3
View File
@@ -12,6 +12,8 @@ import {
checkChannel, checkChannel,
checkEnableHardwareKeyboard, checkEnableHardwareKeyboard,
checkDiskSize, checkDiskSize,
checkPort,
MIN_PORT,
} from './input-validator'; } from './input-validator';
import { launchEmulator, killEmulator } from './emulator-manager'; import { launchEmulator, killEmulator } from './emulator-manager';
import * as exec from '@actions/exec'; import * as exec from '@actions/exec';
@@ -20,6 +22,7 @@ import { getChannelId } from './channel-id-mapper';
import { accessSync, constants } from 'fs'; import { accessSync, constants } from 'fs';
async function run() { async function run() {
let port: number = MIN_PORT;
try { try {
console.log(`::group::Configure emulator`); console.log(`::group::Configure emulator`);
let linuxSupportKVM = false; let linuxSupportKVM = false;
@@ -93,6 +96,11 @@ async function run() {
const emulatorBootTimeout = parseInt(core.getInput('emulator-boot-timeout'), 10); const emulatorBootTimeout = parseInt(core.getInput('emulator-boot-timeout'), 10);
console.log(`Emulator boot timeout: ${emulatorBootTimeout}`); console.log(`Emulator boot timeout: ${emulatorBootTimeout}`);
// Emulator port to use
port = parseInt(core.getInput('emulator-port'), 10);
checkPort(port);
console.log(`emulator port: ${port}`);
// emulator options // emulator options
const emulatorOptions = core.getInput('emulator-options').trim(); const emulatorOptions = core.getInput('emulator-options').trim();
console.log(`emulator options: ${emulatorOptions}`); console.log(`emulator options: ${emulatorOptions}`);
@@ -210,6 +218,7 @@ async function run() {
avdName, avdName,
forceAvdCreation, forceAvdCreation,
emulatorBootTimeout, emulatorBootTimeout,
port,
emulatorOptions, emulatorOptions,
disableAnimations, disableAnimations,
disableSpellchecker, disableSpellchecker,
@@ -226,17 +235,19 @@ async function run() {
for (const script of scripts) { for (const script of scripts) {
// use array form to avoid various quote escaping problems // use array form to avoid various quote escaping problems
// caused by exec(`sh -c "${script}"`) // caused by exec(`sh -c "${script}"`)
await exec.exec('sh', ['-c', script]); await exec.exec('sh', ['-c', script], {
env: { ...process.env, EMULATOR_PORT: `${port}`, ANDROID_SERIAL: `emulator-${port}` },
});
} }
} catch (error) { } catch (error) {
core.setFailed(error instanceof Error ? error.message : (error as string)); core.setFailed(error instanceof Error ? error.message : (error as string));
} }
// finally kill the emulator // finally kill the emulator
await killEmulator(); await killEmulator(port);
} catch (error) { } catch (error) {
// kill the emulator so the action can exit // kill the emulator so the action can exit
await killEmulator(); await killEmulator(port);
core.setFailed(error instanceof Error ? error.message : (error as string)); core.setFailed(error instanceof Error ? error.message : (error as string));
} }
} }
+6 -9
View File
@@ -4,10 +4,10 @@ import * as io from '@actions/io';
import * as tc from '@actions/tool-cache'; import * as tc from '@actions/tool-cache';
import * as fs from 'fs'; import * as fs from 'fs';
const BUILD_TOOLS_VERSION = '34.0.0'; const BUILD_TOOLS_VERSION = '35.0.0';
// SDK command-line tools 11.0 // SDK command-line tools 16.0
const CMDLINE_TOOLS_URL_MAC = 'https://dl.google.com/android/repository/commandlinetools-mac-10406996_latest.zip'; const CMDLINE_TOOLS_URL_MAC = 'https://dl.google.com/android/repository/commandlinetools-mac-12266719_latest.zip';
const CMDLINE_TOOLS_URL_LINUX = 'https://dl.google.com/android/repository/commandlinetools-linux-10406996_latest.zip'; const CMDLINE_TOOLS_URL_LINUX = 'https://dl.google.com/android/repository/commandlinetools-linux-12266719_latest.zip';
/** /**
* Installs & updates the Android SDK for the macOS platform, including SDK platform for the chosen API level, latest build tools, platform tools, Android Emulator, * Installs & updates the Android SDK for the macOS platform, including SDK platform for the chosen API level, latest build tools, platform tools, Android Emulator,
@@ -19,10 +19,6 @@ export async function installAndroidSdk(apiLevel: string, target: string, arch:
const isOnMac = process.platform === 'darwin'; const isOnMac = process.platform === 'darwin';
const isArm = process.arch === 'arm64'; const isArm = process.arch === 'arm64';
if (!isOnMac) {
await exec.exec(`sh -c \\"sudo chown $USER:$USER ${process.env.ANDROID_HOME} -R`);
}
const cmdlineToolsPath = `${process.env.ANDROID_HOME}/cmdline-tools`; const cmdlineToolsPath = `${process.env.ANDROID_HOME}/cmdline-tools`;
if (!fs.existsSync(cmdlineToolsPath)) { if (!fs.existsSync(cmdlineToolsPath)) {
console.log('Installing new cmdline-tools.'); console.log('Installing new cmdline-tools.');
@@ -36,6 +32,7 @@ export async function installAndroidSdk(apiLevel: string, target: string, arch:
core.addPath(`${cmdlineToolsPath}/latest:${cmdlineToolsPath}/latest/bin:${process.env.ANDROID_HOME}/platform-tools`); core.addPath(`${cmdlineToolsPath}/latest:${cmdlineToolsPath}/latest/bin:${process.env.ANDROID_HOME}/platform-tools`);
// set standard AVD path // set standard AVD path
await io.mkdirP(`${process.env.HOME}/.android/avd`);
core.exportVariable('ANDROID_AVD_HOME', `${process.env.HOME}/.android/avd`); core.exportVariable('ANDROID_AVD_HOME', `${process.env.HOME}/.android/avd`);
// accept all Android SDK licenses // accept all Android SDK licenses
@@ -43,7 +40,7 @@ export async function installAndroidSdk(apiLevel: string, target: string, arch:
console.log('Installing latest build tools, platform tools, and platform.'); console.log('Installing latest build tools, platform tools, and platform.');
await exec.exec(`sh -c \\"sdkmanager --install 'build-tools;${BUILD_TOOLS_VERSION}' platform-tools > /dev/null"`); await exec.exec(`sh -c \\"sdkmanager --install 'build-tools;${BUILD_TOOLS_VERSION}' platform-tools 'platforms;android-${apiLevel}'> /dev/null"`);
console.log('Installing latest emulator.'); console.log('Installing latest emulator.');
await exec.exec(`sh -c \\"sdkmanager --install emulator --channel=${channelId} > /dev/null"`); await exec.exec(`sh -c \\"sdkmanager --install emulator --channel=${channelId} > /dev/null"`);
+7 -8
View File
@@ -4,13 +4,13 @@ apply plugin: 'kotlin-android'
android { android {
namespace = "com.example.testapp" namespace = "com.example.testapp"
compileSdkVersion 34 compileSdkVersion 35
buildToolsVersion "34.0.0" buildToolsVersion "35.0.0"
defaultConfig { defaultConfig {
applicationId "com.example.testapp" applicationId "com.example.testapp"
minSdkVersion 15 minSdkVersion 21
targetSdkVersion 34 targetSdkVersion 35
versionCode 1 versionCode 1
versionName "1.0" versionName "1.0"
@@ -30,8 +30,7 @@ tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).configureEach {
} }
dependencies { dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar']) implementation 'androidx.appcompat:appcompat:1.7.0'
implementation 'androidx.appcompat:appcompat:1.6.1' androidTestImplementation 'androidx.test.ext:junit:1.2.1'
androidTestImplementation 'androidx.test.ext:junit:1.1.5' androidTestImplementation 'androidx.test.espresso:espresso-core:3.6.1'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
} }
+2 -2
View File
@@ -6,8 +6,8 @@ buildscript {
mavenCentral() mavenCentral()
} }
dependencies { dependencies {
classpath 'com.android.tools.build:gradle:8.2.0' classpath 'com.android.tools.build:gradle:8.7.0'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.9.21" classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:2.0.20"
// NOTE: Do not place your application dependencies here; they belong // NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files // in the individual module build.gradle files
+1 -1
View File
@@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-bin.zip
networkTimeout=10000 networkTimeout=10000
validateDistributionUrl=true validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME