Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c9108d8479 | ||
|
|
98bb8c2a6a |
@@ -1,3 +1,3 @@
|
||||
templates/project/assets/www/cordova.js
|
||||
bin/templates/project/assets/www/cordova.js
|
||||
test/android/app
|
||||
test/androidx/app
|
||||
|
||||
3
.gitattributes
vendored
@@ -23,7 +23,7 @@
|
||||
*.scm text
|
||||
*.sql text
|
||||
*.sh text
|
||||
*.bat text eol=crlf
|
||||
*.bat text
|
||||
|
||||
# templates
|
||||
*.ejs text
|
||||
@@ -92,4 +92,3 @@ AUTHORS text
|
||||
*.woff binary
|
||||
*.pyc binary
|
||||
*.pdf binary
|
||||
*.jar binary
|
||||
|
||||
38
.github/workflows/ci.yml
vendored
@@ -27,19 +27,21 @@ jobs:
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: [16.x, 18.x, 20.x, 22.x]
|
||||
node-version: [10.x, 12.x, 14.x]
|
||||
os: [ubuntu-latest, windows-latest, macos-latest]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Use Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
|
||||
- uses: actions/setup-java@v4
|
||||
- name: set up JDK 1.8
|
||||
uses: actions/setup-java@v1
|
||||
with:
|
||||
distribution: 'temurin'
|
||||
java-version: '17'
|
||||
java-version: 1.8
|
||||
|
||||
- name: Environment Information
|
||||
run: |
|
||||
@@ -47,21 +49,6 @@ jobs:
|
||||
npm --version
|
||||
gradle --version
|
||||
|
||||
# "bin/templates/platform_www/cordova.js" is ignored because it is a generated file.
|
||||
# It contains mixed content from the npm package "cordova-js" and "./cordova-js-src".
|
||||
# The report might not be resolvable because of the external package.
|
||||
# If the report is related to this repository, it would be detected when scanning "./cordova-js-src".
|
||||
- uses: github/codeql-action/init@v3
|
||||
with:
|
||||
languages: javascript, java-kotlin
|
||||
queries: security-and-quality
|
||||
config: |
|
||||
paths-ignore:
|
||||
- coverage
|
||||
- node_modules
|
||||
- templates/project/assets/www/cordova.js
|
||||
- test/androidx/app/src/main/assets/www/cordova.js
|
||||
|
||||
- name: npm install and test
|
||||
run: |
|
||||
npm i
|
||||
@@ -69,11 +56,6 @@ jobs:
|
||||
env:
|
||||
CI: true
|
||||
|
||||
- uses: github/codeql-action/analyze@v3
|
||||
|
||||
- uses: codecov/codecov-action@v4
|
||||
if: success()
|
||||
- uses: codecov/codecov-action@v1
|
||||
with:
|
||||
name: ${{ runner.os }} node.js ${{ matrix.node-version }}
|
||||
token: ${{ secrets.CORDOVA_CODECOV_TOKEN }}
|
||||
fail_ci_if_error: false
|
||||
fail_ci_if_error: true
|
||||
|
||||
45
.github/workflows/release-audit.yml
vendored
@@ -1,45 +0,0 @@
|
||||
# Licensed to the Apache Software Foundation (ASF) under one
|
||||
# or more contributor license agreements. See the NOTICE file
|
||||
# distributed with this work for additional information
|
||||
# regarding copyright ownership. The ASF licenses this file
|
||||
# to you under the Apache License, Version 2.0 (the
|
||||
# "License"); you may not use this file except in compliance
|
||||
# with the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing,
|
||||
# software distributed under the License is distributed on an
|
||||
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
# KIND, either express or implied. See the License for the
|
||||
# specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
name: Release Auditing
|
||||
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
test:
|
||||
name: Audit Licenses
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
# Checkout project
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
# Check license headers
|
||||
- uses: erisu/apache-rat-action@555ae80334a535eb6c1f8920b121563a5a985a75
|
||||
|
||||
# Setup environment with node
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 20
|
||||
|
||||
# Install node packages
|
||||
- name: npm install packages
|
||||
run: npm i
|
||||
|
||||
# Check node package licenses
|
||||
- uses: erisu/license-checker-action@e929758f9416f30234ac454fc9054ca4b803871d
|
||||
with:
|
||||
license-config: 'licence_checker.yml'
|
||||
13
.gitignore
vendored
@@ -25,12 +25,15 @@ example
|
||||
/framework/libs
|
||||
/framework/javadoc-public
|
||||
/framework/javadoc-private
|
||||
|
||||
**/assets/www/cordova.js
|
||||
|
||||
/test/.externalNativeBuild
|
||||
/test/androidx/cdv-gradle-config.json
|
||||
/test/androidx/tools
|
||||
|
||||
/test/android/gradle
|
||||
/test/android/gradlew
|
||||
/test/android/gradlew.bat
|
||||
/test/androidx/gradle
|
||||
/test/androidx/gradlew
|
||||
/test/androidx/gradlew.bat
|
||||
|
||||
/test/assets/www/.tmp*
|
||||
/test/assets/www/cordova.js
|
||||
/test/bin
|
||||
|
||||
@@ -3,4 +3,3 @@ coverage
|
||||
test
|
||||
spec
|
||||
framework/build
|
||||
cordova-js-src
|
||||
|
||||
21
.ratignore
@@ -1,13 +1,8 @@
|
||||
\.(.*)
|
||||
(.*).txt
|
||||
coverage
|
||||
fixtures
|
||||
generated
|
||||
gitignore
|
||||
intermediates
|
||||
reports
|
||||
test-results
|
||||
node_modules
|
||||
gradle
|
||||
gradlew
|
||||
gradlew.bat
|
||||
*.properties
|
||||
bin
|
||||
gen
|
||||
proguard-project.txt
|
||||
spec
|
||||
framework/build
|
||||
ic_launcher.png
|
||||
build
|
||||
|
||||
3
LICENSE
@@ -187,7 +187,7 @@
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright 2015-2024 Apache Cordova
|
||||
Copyright 2015-2020 Apache Cordova
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
@@ -200,4 +200,3 @@
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
|
||||
50
README.md
@@ -28,44 +28,36 @@
|
||||
|
||||
Cordova Android is an Android application library that allows for Cordova-based projects to be built for the Android Platform. Cordova based applications are, at the core, applications written with web technology: HTML, CSS and JavaScript.
|
||||
|
||||
[Apache Cordova](https://cordova.apache.org/) is a project of [The Apache Software Foundation (ASF)](https://apache.org/).
|
||||
[Apache Cordova](https://cordova.apache.org) is a project of The Apache Software Foundation (ASF).
|
||||
|
||||
## Requirements
|
||||
## Requires
|
||||
|
||||
* Java Development Kit (JDK) 11
|
||||
* [Android SDK](https://developer.android.com/)
|
||||
* [Node.js](https://nodejs.org)
|
||||
- Java JDK 1.8
|
||||
- Android SDK [http://developer.android.com](https://developer.android.com/)
|
||||
|
||||
## Create a Cordova project
|
||||
## Cordova Android Developer Tools
|
||||
|
||||
Follow the instructions in the [**Create your first Cordova app**](https://cordova.apache.org/docs/en/latest/guide/cli/index.html) section of [Apache Cordova Docs](https://cordova.apache.org/docs/en/latest/)
|
||||
We recommend using the [Cordova command-line tool](https://www.npmjs.com/package/cordova) to create projects and be able to easily install plugins.
|
||||
|
||||
To use a **shared framework**, for example in development, link the appropriate cordova-android platform folder path:
|
||||
However, the following scripts can be used instead:
|
||||
|
||||
```bash
|
||||
cordova platform add --link /path/to/cordova-android
|
||||
```
|
||||
./bin/create [path package activity] ... creates the ./example app or a cordova android project
|
||||
./bin/check_reqs ....................... checks that your environment is set up for cordova-android development
|
||||
./bin/update [path] .................... updates an existing cordova-android project to the version of the framework
|
||||
|
||||
## Updating a Cordova project
|
||||
These commands live in a generated Cordova Android project. Any interactions with the emulator require you to have an AVD defined.
|
||||
|
||||
When you install a new version of the [`Cordova CLI`](https://www.npmjs.com/package/cordova) that pins a new version of the [`Cordova-Android`](https://www.npmjs.com/package/cordova-android) platform, you can follow these simple upgrade steps within your project:
|
||||
./cordova/clean ........................ cleans the project
|
||||
./cordova/build ........................ calls `clean` then compiles the project
|
||||
./cordova/log ........................ streams device or emulator logs to STDOUT
|
||||
./cordova/run ........................ calls `build` then deploys to a connected Android device. If no Android device is detected, will launch an emulator and deploy to it.
|
||||
./cordova/version ...................... returns the cordova-android version of the current project
|
||||
|
||||
```bash
|
||||
cordova platform rm android
|
||||
cordova platform add android
|
||||
```
|
||||
## Using Android Studio
|
||||
|
||||
## Debugging in Android Studio
|
||||
1. Create a project
|
||||
2. Import it via "Non-Android Studio Project"
|
||||
|
||||
Import project in Android Studio through _File > Open_ and targeting `/path/to/your-cdv-project/platforms/android/`.
|
||||
## Running the Native Tests
|
||||
|
||||
## How to Test Repo Development
|
||||
|
||||
```bash
|
||||
npm install
|
||||
npm test
|
||||
```
|
||||
|
||||
## Further reading
|
||||
|
||||
* [Apache Cordova](https://cordova.apache.org/)
|
||||
The `test/` directory in this project contains an Android test project that can be used to run different kinds of native tests. Check out the [README contained therein](test/README.md) for more details!
|
||||
|
||||
294
RELEASENOTES.md
@@ -20,268 +20,6 @@
|
||||
-->
|
||||
## Release Notes for Cordova (Android)
|
||||
|
||||
### 13.0.0 (May 15, 2024)
|
||||
|
||||
**Breaking Changes:**
|
||||
|
||||
* [GH-1678](https://github.com/apache/cordova-android/pull/1678) feat!: API 34 Support
|
||||
* [GH-1543](https://github.com/apache/cordova-android/pull/1543) feat!: bump `kotlin@1.9.24` & drop `kotlin-android-extensions` when kotlin `>=1.8.0`
|
||||
|
||||
**Features:**
|
||||
|
||||
* [GH-1700](https://github.com/apache/cordova-android/pull/1700) feat(splash): Support `SplashScreenBackgroundColor` preference
|
||||
* [GH-1609](https://github.com/apache/cordova-android/pull/1609) feat: add camera intent with file input capture
|
||||
* [GH-1696](https://github.com/apache/cordova-android/pull/1696) feat: Add `ResolveServiceWorkerRequests` preference
|
||||
|
||||
**Chores, Dependencies & CI:**
|
||||
|
||||
* [GH-1677](https://github.com/apache/cordova-android/pull/1677) chore(deps-dev): bump `@babel/traverse` from `7.22.10` to `7.23.2`
|
||||
* [GH-1713](https://github.com/apache/cordova-android/pull/1713) dep: bump npm dependencies 20240515
|
||||
* `semver@7.6.2`
|
||||
* `rewire@7.0.0`
|
||||
* `nopt@7.2.1`
|
||||
* `jasmine@5.1.0`
|
||||
* `fs-extra@11.2.0`
|
||||
* `fast-glob@3.3.2`
|
||||
* `dedent@1.5.3`
|
||||
* `@cordova/eslint-config@5.1.0`
|
||||
* `which@4.0.0`
|
||||
* `properties-parser@0.6.0`
|
||||
* `android-versions@2.0.0`
|
||||
* [GH-1711](https://github.com/apache/cordova-android/pull/1711) ci: Set up CodeQL analysis w/ fixes
|
||||
* [GH-1687](https://github.com/apache/cordova-android/pull/1687) ci(release-audit): add license header and dependency checker
|
||||
* [GH-1703](https://github.com/apache/cordova-android/pull/1703) ci: update `codecov@v4` w/ token
|
||||
|
||||
### 12.0.1 (Aug 23, 2023)
|
||||
|
||||
* [GH-1632](https://github.com/apache/cordova-android/pull/1632) fix(android): `monochrome` checks
|
||||
* [GH-1649](https://github.com/apache/cordova-android/pull/1649) chore: rebuild `package-lock` w/ lint corrections
|
||||
|
||||
### 12.0.0 (May 20, 2023)
|
||||
|
||||
**Breaking:**
|
||||
|
||||
* [GH-1605](https://github.com/apache/cordova-android/pull/1605) fix!: Make `CoreAndroid` plugin instantiate on load
|
||||
* [GH-1539](https://github.com/apache/cordova-android/pull/1539) feat!: bump Gradle 7.6 & AGP 7.4.2
|
||||
* [GH-1571](https://github.com/apache/cordova-android/pull/1571) feat!: bump min SDK to 24
|
||||
* [GH-1538](https://github.com/apache/cordova-android/pull/1538) feat!: bump target sdk & build tools for SDK 33 support
|
||||
* [GH-1540](https://github.com/apache/cordova-android/pull/1540) feat!: bump node engine requirement `>=16.13.0`
|
||||
* [GH-1597](https://github.com/apache/cordova-android/pull/1597) deprecate: `CoreAndroid.getBuildConfigValue`
|
||||
* [GH-1541](https://github.com/apache/cordova-android/pull/1541) dep(npm)!: bump acceptable modules w/ rebuilt `package-lock`
|
||||
* [GH-1566](https://github.com/apache/cordova-android/pull/1566) dep(npm)!: bump `cordova-common@5.0.0`
|
||||
|
||||
**Features:**
|
||||
|
||||
* [GH-1602](https://github.com/apache/cordova-android/pull/1602) feat: add `listTarget` api
|
||||
* [GH-1574](https://github.com/apache/cordova-android/pull/1574) feat: add plugin hooks for `WebViewClient.onRenderProcessGone`
|
||||
* [GH-1594](https://github.com/apache/cordova-android/pull/1594) feat: bump default `kotlin` to version 1.7.21
|
||||
* [GH-1550](https://github.com/apache/cordova-android/pull/1550) feat: add `monochrome` app icon support
|
||||
* [GH-1589](https://github.com/apache/cordova-android/pull/1589) feat: `InspectableWebview` preference
|
||||
* [GH-1568](https://github.com/apache/cordova-android/pull/1568) feat: bump `androidx.appcompat.appcompat` 1.6.1
|
||||
* [GH-1567](https://github.com/apache/cordova-android/pull/1567) feat: bump `androidx.webkit.webkit` 1.6.0
|
||||
* [GH-1545](https://github.com/apache/cordova-android/pull/1545) feat: bump `androidx.webkit.webkit` 1.5.0
|
||||
* [GH-1547](https://github.com/apache/cordova-android/pull/1547) feat: bump `com.google.gms.google-services` 4.3.15
|
||||
* [GH-1546](https://github.com/apache/cordova-android/pull/1546) feat: bump `androidx.core.core-splashscreen` 1.0.0
|
||||
* [GH-1544](https://github.com/apache/cordova-android/pull/1544) feat: bump `androidx.appcompat.appcompat` 1.5.1
|
||||
|
||||
**Fixes:**
|
||||
|
||||
* [GH-1606](https://github.com/apache/cordova-android/pull/1606) fix: Gradle Args parsing
|
||||
* [GH-1575](https://github.com/apache/cordova-android/pull/1575) fix(`BuildHelper`): get package name from `ApplicationInfo`
|
||||
* [GH-1595](https://github.com/apache/cordova-android/pull/1595) fix(test): Native test namespace refactor
|
||||
* [GH-1471](https://github.com/apache/cordova-android/pull/1471) fix: `ANDROID_HOME` is the new default, to check first and give advice
|
||||
* [GH-1573](https://github.com/apache/cordova-android/pull/1573) fix(GH-1432): Default `content` `src` when content tag is missing
|
||||
* [GH-1506](https://github.com/apache/cordova-android/pull/1506) fix: only do fadeout animation if `FadeSplashScreen` is true
|
||||
* [GH-1505](https://github.com/apache/cordova-android/pull/1505) fix: correctly flag API dependency on `AppCompat` for Maven
|
||||
* [GH-1487](https://github.com/apache/cordova-android/pull/1487) fix: Add **Android** prefix to `WindowSplashScreenBrandingImage`
|
||||
* [GH-1489](https://github.com/apache/cordova-android/pull/1489) fix: import type definitions from obsolete `cordova-plugin-splashscreen`
|
||||
|
||||
**Chores, Refactor, Dependencies & CI:**
|
||||
|
||||
* [GH-1493](https://github.com/apache/cordova-android/pull/1493) chore: add `lint:fix` script for fixing lint errors
|
||||
* [GH-1491](https://github.com/apache/cordova-android/pull/1491) chore: Use gradle 7.4.2 distribution url
|
||||
* [GH-1588](https://github.com/apache/cordova-android/pull/1588) refactor: Removed obsolete version code checks
|
||||
* [GH-1492](https://github.com/apache/cordova-android/pull/1492) refactor: replace deprecated `Handler` constructor
|
||||
* [GH-1587](https://github.com/apache/cordova-android/pull/1587) dep: bump npm dependencies
|
||||
* `fs-extra@11.1.1`
|
||||
* `nopt@7.1.0`
|
||||
* `@cordova/eslint-config@5.0.0`
|
||||
* `jasmine@4.6.0`
|
||||
* [GH-1607](https://github.com/apache/cordova-android/pull/1607) ci: Added NodeJS 20.x to the workflow matrix
|
||||
* [GH-1542](https://github.com/apache/cordova-android/pull/1542) ci(workflow): update `codecov/codecov-action@v3`
|
||||
* [GH-1532](https://github.com/apache/cordova-android/pull/1532) ci: update `codecov/codecov-action` reporting format
|
||||
|
||||
### 11.0.0 (Jul 04, 2022)
|
||||
|
||||
**Breaking:**
|
||||
|
||||
* [GH-1441](https://github.com/apache/cordova-android/pull/1441) feat!: **Android** 12 splash screen
|
||||
* [GH-1427](https://github.com/apache/cordova-android/pull/1427) feat!: API 32 support
|
||||
* [GH-1410](https://github.com/apache/cordova-android/pull/1410) feat!: API 31 support
|
||||
* [GH-1444](https://github.com/apache/cordova-android/pull/1444) fix!: set & use `ANDROID_HOME` as default
|
||||
* [GH-1411](https://github.com/apache/cordova-android/pull/1411) chore!: Drop Node 12 support
|
||||
|
||||
**Features:**
|
||||
|
||||
* [GH-1448](https://github.com/apache/cordova-android/pull/1448) feat: Update `androidx.appcompat` version
|
||||
* [GH-1446](https://github.com/apache/cordova-android/pull/1446) feat: Update gradle plugin version
|
||||
* [GH-1447](https://github.com/apache/cordova-android/pull/1447) feat: Update google services pluging
|
||||
* [GH-1431](https://github.com/apache/cordova-android/pull/1431) feat: support custom `compileSdk` setting
|
||||
* [GH-1311](https://github.com/apache/cordova-android/pull/1311) feat: added support for BoM imports
|
||||
|
||||
**Fixes:**
|
||||
|
||||
* [GH-1455](https://github.com/apache/cordova-android/pull/1455) fix(`prepare`): `destFile` path separator
|
||||
* [GH-1453](https://github.com/apache/cordova-android/pull/1453) fix: support installing platfrom from local git checkout
|
||||
* [GH-1449](https://github.com/apache/cordova-android/pull/1449) fix: accept file cookies only if `AndroidInsecureFileModeEnabled`
|
||||
* [GH-1443](https://github.com/apache/cordova-android/pull/1443) fix: force `hostname` to lowercase
|
||||
* [GH-1434](https://github.com/apache/cordova-android/pull/1434) fix: restore `checkReqs` in `prepare.js`
|
||||
* [GH-1154](https://github.com/apache/cordova-android/pull/1154) fix: move `MainActivity.java` to folder that tracks the app package name (widget id)
|
||||
|
||||
**Chores, Dependencies & CI:**
|
||||
|
||||
* [GH-1451](https://github.com/apache/cordova-android/pull/1451) chore: display warning on deprecated `<splash>` tag usage
|
||||
* [GH-1430](https://github.com/apache/cordova-android/pull/1430) chore: remove unneeded deprecated annotation
|
||||
* [GH-1421](https://github.com/apache/cordova-android/pull/1421) chore(npm): bump `@cordova/eslint-config@^4.0.0`
|
||||
* [GH-1420](https://github.com/apache/cordova-android/pull/1420) chore(npm): bump dependencies
|
||||
* [GH-1452](https://github.com/apache/cordova-android/pull/1452) dep: bump `jasmine@4.2.1` w/ `package-lock` rebuild
|
||||
* [GH-1439](https://github.com/apache/cordova-android/pull/1439) ci: update github action workflow
|
||||
* [GH-1424](https://github.com/apache/cordova-android/pull/1424) ci: Added Node 18 to test matrix
|
||||
|
||||
### 10.1.2 (Apr 11, 2022)
|
||||
|
||||
**Fixes:**
|
||||
|
||||
* [GH-1372](https://github.com/apache/cordova-android/pull/1372) fix(`AndroidManifest`): explicitly define the `activity` attribute `android:exported`
|
||||
* [GH-1406](https://github.com/apache/cordova-android/pull/1406) fix: detect `JAVA_HOME` with Java 11
|
||||
* [GH-1401](https://github.com/apache/cordova-android/pull/1401) fix(GH-1391): Reword minimum build tools version to make it more clear what is actually required.
|
||||
* [GH-1384](https://github.com/apache/cordova-android/pull/1384) fix: escape `strings.xml` app name
|
||||
|
||||
**Chores:**
|
||||
|
||||
* [GH-1413](https://github.com/apache/cordova-android/pull/1413) chore: update `package-lock` to satisfy `npm audit`
|
||||
* [GH-1348](https://github.com/apache/cordova-android/pull/1348) chore: `npmrc`
|
||||
|
||||
### 10.1.1 (Sep 13, 2021)
|
||||
|
||||
**Fixes:**
|
||||
|
||||
* [GH-1349](https://github.com/apache/cordova-android/pull/1349) fix(`PluginManager`): `AllowNavigation` default policy to handle scheme & hostname
|
||||
* [GH-1342](https://github.com/apache/cordova-android/pull/1342) fix(`AllowListPlugin`): Safely handle default allow navigation policy in allow request
|
||||
* [GH-1332](https://github.com/apache/cordova-android/pull/1332) fix(`PluginManager`): `AllowBridgeAccess` default policy to handle scheme & hostname
|
||||
|
||||
### 10.1.0 (Aug 13, 2021)
|
||||
|
||||
**Features:**
|
||||
|
||||
* [GH-1213](https://github.com/apache/cordova-android/pull/1213) feat: unify `create` default values & stop project name transform
|
||||
* [GH-1306](https://github.com/apache/cordova-android/pull/1306) feat: bump `ANDROIDX_APP_COMPAT@1.3.1`
|
||||
* [GH-1303](https://github.com/apache/cordova-android/pull/1303) feat: bump `Google Services Gradle Plugin@4.3.8`
|
||||
* [GH-1302](https://github.com/apache/cordova-android/pull/1302) feat: bump `kotlin@1.5.21`
|
||||
* [GH-1298](https://github.com/apache/cordova-android/pull/1298) feat: support `http` w/ `content` `src` fix
|
||||
|
||||
**Fixes:**
|
||||
|
||||
* [GH-1214](https://github.com/apache/cordova-android/pull/1214) fix: display project name in Android Studio
|
||||
* [GH-1300](https://github.com/apache/cordova-android/pull/1300) fix: fall back to project root `repositories.gradle`
|
||||
|
||||
**Docs:**
|
||||
|
||||
* [GH-1308](https://github.com/apache/cordova-android/pull/1308) doc: update `README` about development & testing
|
||||
|
||||
### 10.0.1 (Jul 27, 2021)
|
||||
|
||||
**Fixes:**
|
||||
|
||||
* [GH-1295](https://github.com/apache/cordova-android/pull/1295) fix: `maven-publish` setup
|
||||
* [GH-1293](https://github.com/apache/cordova-android/pull/1293) fix: `gradle` build tools config
|
||||
* [GH-1294](https://github.com/apache/cordova-android/pull/1294) fix: automatic latest build tools finding
|
||||
* [GH-1287](https://github.com/apache/cordova-android/pull/1287) fix: Google Services Gradle Plugin version check failure
|
||||
|
||||
**Chores:**
|
||||
|
||||
* [GH-1291](https://github.com/apache/cordova-android/pull/1291) chore: add missing release notes
|
||||
* [GH-1286](https://github.com/apache/cordova-android/pull/1286) chore: update `README` requirements
|
||||
|
||||
### 10.0.0 (Jul 17, 2021)
|
||||
|
||||
**Breaking:**
|
||||
|
||||
* [GH-1052](https://github.com/apache/cordova-android/pull/1052) feat!: only support `AndroidX`
|
||||
* [GH-1137](https://github.com/apache/cordova-android/pull/1137) feat!: implement `WebViewAssetLoader`
|
||||
* [GH-1268](https://github.com/apache/cordova-android/pull/1268) feat!: release build defaults to `aab` package type
|
||||
* [GH-1182](https://github.com/apache/cordova-android/pull/1182) feat!: bump `target sdk@30` w/ `build-tool@30.0.3`
|
||||
* [GH-1257](https://github.com/apache/cordova-android/pull/1257) feat!: upgrade `gradle@7.1.1`
|
||||
* [GH-1197](https://github.com/apache/cordova-android/pull/1197) feat!: upgrade `gradle@6.8.3`
|
||||
* [GH-1256](https://github.com/apache/cordova-android/pull/1256) feat!: upgrade `kotlin@1.5.20`
|
||||
* [GH-1204](https://github.com/apache/cordova-android/pull/1204) feat!: upgrade `kotlin@1.4.32`
|
||||
* [GH-1200](https://github.com/apache/cordova-android/pull/1200) feat!: upgrade `kotlin@1.4.31`
|
||||
* [GH-1255](https://github.com/apache/cordova-android/pull/1255) feat!: upgrade `android-gradle-plugin@4.2.2`
|
||||
* [GH-1232](https://github.com/apache/cordova-android/pull/1232) feat!: upgrade `android-gradle-plugin@4.2.1`
|
||||
* [GH-1198](https://github.com/apache/cordova-android/pull/1198) feat!: upgrade `android-gradle-plugin@4.1.3`
|
||||
* [GH-1199](https://github.com/apache/cordova-android/pull/1199) feat!: upgrade `Google Services Gradle Plugin@4.3.5`
|
||||
* [GH-1262](https://github.com/apache/cordova-android/pull/1262) feat!: bump `appcompat@1.3.0`
|
||||
* [GH-1258](https://github.com/apache/cordova-android/pull/1258) feat!: bump `android.webkit@1.4.0`
|
||||
* [GH-1252](https://github.com/apache/cordova-android/pull/1252) feat!: drop abandoned `com.github.dcendents:android-maven-gradle-plugin`
|
||||
* [GH-1212](https://github.com/apache/cordova-android/pull/1212) feat!: unify & fix gradle library/tooling overrides
|
||||
* [GH-1138](https://github.com/apache/cordova-android/pull/1138) feat(allow-list)!: integrate and refactor core plugin
|
||||
* [GH-1201](https://github.com/apache/cordova-android/pull/1201) feat!: upgrade jfrog `gradle-bintray-plugin@1.8.5`
|
||||
* [GH-1279](https://github.com/apache/cordova-android/pull/1279) chore!: bump all dependencies
|
||||
* [GH-1278](https://github.com/apache/cordova-android/pull/1278) chore!: drop `node` 10 support
|
||||
* [GH-1205](https://github.com/apache/cordova-android/pull/1205) chore! (`npm`): update all dependencies
|
||||
* [GH-1274](https://github.com/apache/cordova-android/pull/1274) cleanup!: remove deprecated settings & add todo comments
|
||||
* [GH-1048](https://github.com/apache/cordova-android/pull/1048) cleanup!: remove `keystore` password prompt
|
||||
* [GH-1251](https://github.com/apache/cordova-android/pull/1251) cleanup!: drop `jcenter` & update dependencies
|
||||
* [GH-1269](https://github.com/apache/cordova-android/pull/1269) refactor!: do not copy JS lib to platform project
|
||||
* [GH-1270](https://github.com/apache/cordova-android/pull/1270) refactor(Api)!: use version from `package.json`
|
||||
* [GH-1266](https://github.com/apache/cordova-android/pull/1266) refactor(run)!: `run` method
|
||||
* [GH-1083](https://github.com/apache/cordova-android/pull/1083) refactor!: drop support for `android` SDK tool
|
||||
* [GH-1100](https://github.com/apache/cordova-android/pull/1100) refactor!: remove most platform binaries
|
||||
|
||||
**Features:**
|
||||
|
||||
* [GH-1241](https://github.com/apache/cordova-android/pull/1241) feat: remove `java` 1.8 version check
|
||||
* [GH-1254](https://github.com/apache/cordova-android/pull/1254) feat: support `webkit` version override
|
||||
* [GH-1229](https://github.com/apache/cordova-android/pull/1229) feat: `CORDOVA_JAVA_HOME` env variable
|
||||
* [GH-1222](https://github.com/apache/cordova-android/pull/1222) feat: add backwards compatibility mode for `WebViewAssetLoader`
|
||||
* [GH-1166](https://github.com/apache/cordova-android/pull/1166) feat: overload `PluginEntry` constructor to set onload property
|
||||
* [GH-1208](https://github.com/apache/cordova-android/pull/1208) feat: allow `appcompat` version to be configurable
|
||||
* [GH-1047](https://github.com/apache/cordova-android/pull/1047) feat: Deprecated `onRequestPermissionResult` in favour for `onRequestPermissionsResult` for consistency
|
||||
|
||||
**Fixes:**
|
||||
|
||||
* [GH-1283](https://github.com/apache/cordova-android/pull/1283) fix: add missing apache-license header to `getASPath.bat`
|
||||
* [GH-1275](https://github.com/apache/cordova-android/pull/1275) fix: add `WebViewAssetloader` to default allow list
|
||||
* [GH-1216](https://github.com/apache/cordova-android/pull/1216) fix: request focus after custom view hided
|
||||
* [GH-1264](https://github.com/apache/cordova-android/pull/1264) fix: missing `super.onRequestPermissionsResult` error (`MissingSuperCall`)
|
||||
* [GH-563](https://github.com/apache/cordova-android/pull/563) fix(build): support tilde expansion on Windows
|
||||
* [GH-1220](https://github.com/apache/cordova-android/pull/1220) fix(`requirements` check): use regex to get java version from javac output
|
||||
* [GH-1227](https://github.com/apache/cordova-android/pull/1227) fix(prepare): delete splash screens if none are used
|
||||
* [GH-1228](https://github.com/apache/cordova-android/pull/1228) fix: java checks
|
||||
* [GH-1276](https://github.com/apache/cordova-android/pull/1276) fix: remove forced default `gradle.daemon` setting
|
||||
|
||||
**Refactors:**
|
||||
|
||||
* [GH-1265](https://github.com/apache/cordova-android/pull/1265) refactor: do not infer project root from script location
|
||||
* [GH-1267](https://github.com/apache/cordova-android/pull/1267) refactor: use target SDK of built APK to determine best emulator
|
||||
* [GH-1253](https://github.com/apache/cordova-android/pull/1253) refactor: `gradle` cleanup
|
||||
* [GH-1260](https://github.com/apache/cordova-android/pull/1260) refactor(`check_reqs`): drop `originalError` param from `check_android_target`
|
||||
* [GH-1246](https://github.com/apache/cordova-android/pull/1246) refactor(`env/java`): improve tests and implementation
|
||||
|
||||
**Chores & Cleanup:**
|
||||
|
||||
* [GH-1273](https://github.com/apache/cordova-android/pull/1273) chore: remove old `VERSION` file
|
||||
* [GH-1272](https://github.com/apache/cordova-android/pull/1272) cleanup: delete old ANT & Eclipse files
|
||||
* [GH-1141](https://github.com/apache/cordova-android/pull/1141) cleanup: remove app cache settings
|
||||
|
||||
**CI, Build & Testing:**
|
||||
|
||||
* [GH-1218](https://github.com/apache/cordova-android/pull/1218) ci: Add `Node16` to CI matrix
|
||||
* [GH-1271](https://github.com/apache/cordova-android/pull/1271) build: build `cordova.js` during npm prepare
|
||||
* [GH-1207](https://github.com/apache/cordova-android/pull/1207) test(`AndroidManifest`): update theme to `Theme.AppCompat.NoActionBar`
|
||||
* [GH-1263](https://github.com/apache/cordova-android/pull/1263) test(`check_reqs`): do not hardcode `DEFAULT_TARGET_API`
|
||||
* [GH-1259](https://github.com/apache/cordova-android/pull/1259) test(`prepare`): factor out common vars
|
||||
|
||||
### 9.1.0 (Apr 09, 2021)
|
||||
|
||||
**Features:**
|
||||
@@ -495,38 +233,6 @@
|
||||
* [CB-13830](https://issues.apache.org/jira/browse/CB-13830) Add handlers for plugins that use non-Java source files, such as Camera
|
||||
* [CB-13923](https://issues.apache.org/jira/browse/CB-13923) Fix -1 length for compressed files
|
||||
|
||||
### 7.1.4 (Nov 22, 2018)
|
||||
|
||||
* Update android-versions to `1.4.0`, with added support for Android Pie ([#573](https://github.com/apache/cordova-android/pull/573))
|
||||
* Output current package name if package name can't be validated ([#567](https://github.com/apache/cordova-android/pull/567))
|
||||
* Resolve issue with plugin `target-dir="*app*"` subdirs ([#572](https://github.com/apache/cordova-android/pull/572))
|
||||
|
||||
### 7.1.3 (Nov 19, 2018)
|
||||
|
||||
* [GH-495](https://github.com/apache/cordova-android/pull/495) Incorrect default sdk version issue fix
|
||||
* [GH-496](https://github.com/apache/cordova-android/pull/496) update comments in `build.gradle`
|
||||
* [GH-539](https://github.com/apache/cordova-android/pull/539) Fix dest overwrite, in case of of plugin `source-file` element with `target-dir` that does not need remapping
|
||||
* [GH-540](https://github.com/apache/cordova-android/issues/540) support plugin `source-file` element with any app `target-dir` value
|
||||
* [GH-547](https://github.com/apache/cordova-android/issues/547) Compatibility of old plugins with non-Java `source-file` entries (individual files)
|
||||
* [GH-551](https://github.com/apache/cordova-android/pull/551) add missing cast for cdvMinSdkVersion to `build.gradle`
|
||||
* [GH-552](https://github.com/apache/cordova-android/issues/552) check for `build-extras.gradle` in the parent app directory
|
||||
|
||||
### 7.1.2 (Nov 08, 2018)
|
||||
* [CB-14127](https://issues.apache.org/jira/browse/CB-14127): Always put the Google repo above jcenter
|
||||
* [CB-14165](https://issues.apache.org/jira/browse/CB-14165): Emulator: handle "device still connecting" error (#457)
|
||||
* [CB-14125](https://issues.apache.org/jira/browse/CB-14125): Increase old plugin compatibility
|
||||
* [CB-13830](https://issues.apache.org/jira/browse/CB-13830): Add handlers for plugins that use non-Java source files, such as Camera
|
||||
* [CB-14038](https://issues.apache.org/jira/browse/CB-14038): fix false positive detecting project type
|
||||
|
||||
### 7.1.1 (Jul 11, 2018)
|
||||
* Fix unsafe property access in run.js (#445)
|
||||
* Emit log event instead of logging directly (#452)
|
||||
* [CB-14101](https://issues.apache.org/jira/browse/CB-14101) Fix Java version check for Java >= 9 (#446)
|
||||
* [CB-14127](https://issues.apache.org/jira/browse/CB-14127) (android) Move google maven repo ahead of jcenter
|
||||
* [CB-13923](https://issues.apache.org/jira/browse/CB-13923) (android) fix -1 length for compressed files
|
||||
* [CB-14145](https://issues.apache.org/jira/browse/CB-14145) use cordova-common@2.2.5 and update other dependencies to resolve `npm audit` warnings
|
||||
* [CB-9366](https://issues.apache.org/jira/browse/CB-9366) log error.stack in cordova.js
|
||||
|
||||
### 7.1.0 (Feb 20, 2018)
|
||||
* [CB-13879](https://issues.apache.org/jira/browse/CB-13879) updated gradle tools dependency to 3.0.1 for project template
|
||||
* [CB-13831](https://issues.apache.org/jira/browse/CB-13831) Update `android-versions` to 1.3.0 to support SDK 27.
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
under the License.
|
||||
*/
|
||||
|
||||
const android_sdk = require('cordova-android/lib/android_sdk');
|
||||
var android_sdk = require('./templates/cordova/lib/android_sdk');
|
||||
|
||||
android_sdk.print_newest_available_sdk_target().catch(err => {
|
||||
console.error(err);
|
||||
26
bin/android_sdk_version.bat
Normal file
@@ -0,0 +1,26 @@
|
||||
:: Licensed to the Apache Software Foundation (ASF) under one
|
||||
:: or more contributor license agreements. See the NOTICE file
|
||||
:: distributed with this work for additional information
|
||||
:: regarding copyright ownership. The ASF licenses this file
|
||||
:: to you under the Apache License, Version 2.0 (the
|
||||
:: "License"); you may not use this file except in compliance
|
||||
:: with the License. You may obtain a copy of the License at
|
||||
::
|
||||
:: http://www.apache.org/licenses/LICENSE-2.0
|
||||
::
|
||||
:: Unless required by applicable law or agreed to in writing,
|
||||
:: software distributed under the License is distributed on an
|
||||
:: "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
:: KIND, either express or implied. See the License for the
|
||||
:: specific language governing permissions and limitations
|
||||
:: under the License.
|
||||
|
||||
@ECHO OFF
|
||||
SET script_path="%~dp0android_sdk_version"
|
||||
IF EXIST %script_path% (
|
||||
node %script_path% %*
|
||||
) ELSE (
|
||||
ECHO.
|
||||
ECHO ERROR: Could not find 'android_sdk_version' script in 'bin' folder, aborting...>&2
|
||||
EXIT /B 1
|
||||
)
|
||||
23
templates/project/tools/settings.gradle → bin/check_reqs
Normal file → Executable file
@@ -1,3 +1,5 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
/*
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
@@ -17,13 +19,14 @@
|
||||
under the License.
|
||||
*/
|
||||
|
||||
// This is an empty project used to provide Gradle Tooling
|
||||
// Using the main project which loads AGP will enforce a minimum version
|
||||
// requirement on the end-user, requiring a gradle install that satisfies AGP
|
||||
// version requirements.
|
||||
// To avoid that, we utilise this empty project of which we can
|
||||
// freely run the gradle wrapper task against to obtain the
|
||||
// wrapper at the desired version, without being restricted by AGP's version
|
||||
// requirements.
|
||||
// Of course, the installed wrapper must still be of at least the minimum
|
||||
// required version of AGP for the build to work correctly.
|
||||
var check_reqs = require('./templates/cordova/lib/check_reqs');
|
||||
|
||||
check_reqs.run().then(
|
||||
function success () {
|
||||
console.log('Looks like your environment fully supports cordova-android development!');
|
||||
},
|
||||
function fail (err) {
|
||||
console.log(err);
|
||||
process.exit(2);
|
||||
}
|
||||
);
|
||||
26
bin/check_reqs.bat
Normal file
@@ -0,0 +1,26 @@
|
||||
:: Licensed to the Apache Software Foundation (ASF) under one
|
||||
:: or more contributor license agreements. See the NOTICE file
|
||||
:: distributed with this work for additional information
|
||||
:: regarding copyright ownership. The ASF licenses this file
|
||||
:: to you under the Apache License, Version 2.0 (the
|
||||
:: "License"); you may not use this file except in compliance
|
||||
:: with the License. You may obtain a copy of the License at
|
||||
::
|
||||
:: http://www.apache.org/licenses/LICENSE-2.0
|
||||
::
|
||||
:: Unless required by applicable law or agreed to in writing,
|
||||
:: software distributed under the License is distributed on an
|
||||
:: "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
:: KIND, either express or implied. See the License for the
|
||||
:: specific language governing permissions and limitations
|
||||
:: under the License.
|
||||
|
||||
@ECHO OFF
|
||||
SET script_path="%~dp0check_reqs"
|
||||
IF EXIST %script_path% (
|
||||
node %script_path% %*
|
||||
) ELSE (
|
||||
ECHO.
|
||||
ECHO ERROR: Could not find 'check_reqs' script in 'bin' folder, aborting...>&2
|
||||
EXIT /B 1
|
||||
)
|
||||
61
bin/create
Executable file
@@ -0,0 +1,61 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
/*
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
*/
|
||||
var path = require('path');
|
||||
var ConfigParser = require('cordova-common').ConfigParser;
|
||||
var Api = require('./templates/cordova/Api');
|
||||
|
||||
var argv = require('nopt')({
|
||||
help: Boolean,
|
||||
cli: Boolean,
|
||||
shared: Boolean,
|
||||
link: Boolean,
|
||||
'activity-name': [String, undefined]
|
||||
}, { d: '--verbose' });
|
||||
|
||||
if (argv.help || argv.argv.remain.length === 0) {
|
||||
console.log('Usage: ' + path.relative(process.cwd(), path.join(__dirname, 'create')) + ' <path_to_new_project> <package_name> <project_name> [<template_path>] [--activity-name <activity_name>] [--link]');
|
||||
console.log(' <path_to_new_project>: Path to your new Cordova Android project');
|
||||
console.log(' <package_name>: Package name, following reverse-domain style convention');
|
||||
console.log(' <project_name>: Project name');
|
||||
console.log(' <template_path>: Path to a custom application template to use');
|
||||
console.log(' --activity-name <activity_name>: Activity name');
|
||||
console.log(' --link will use the CordovaLib project directly instead of making a copy.');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
var config = new ConfigParser(path.resolve(__dirname, 'templates/project/res/xml/config.xml'));
|
||||
|
||||
if (argv.argv.remain[1]) config.setPackageName(argv.argv.remain[1]);
|
||||
if (argv.argv.remain[2]) config.setName(argv.argv.remain[2]);
|
||||
if (argv['activity-name']) config.setName(argv['activity-name']);
|
||||
|
||||
var options = {
|
||||
link: argv.link || argv.shared,
|
||||
customTemplate: argv.argv.remain[3],
|
||||
activityName: argv['activity-name']
|
||||
};
|
||||
|
||||
require('./templates/cordova/loggingHelper').adjustLoggerLevel(argv);
|
||||
|
||||
Api.createPlatform(argv.argv.remain[0], config, options).catch(err => {
|
||||
console.error(err);
|
||||
process.exitCode = 1;
|
||||
});
|
||||
@@ -16,5 +16,11 @@
|
||||
:: under the License.
|
||||
|
||||
@ECHO OFF
|
||||
for /f "tokens=2*" %%a in ('REG QUERY "HKEY_LOCAL_MACHINE\SOFTWARE\Android Studio" /v Path') do set "ASPath=%%~b"
|
||||
ECHO %ASPath%
|
||||
SET script_path="%~dp0create"
|
||||
IF EXIST %script_path% (
|
||||
node %script_path% %*
|
||||
) ELSE (
|
||||
ECHO.
|
||||
ECHO ERROR: Could not find 'create' script in 'bin' folder, aborting...>&2
|
||||
EXIT /B 1
|
||||
)
|
||||
@@ -17,16 +17,14 @@
|
||||
under the License.
|
||||
*/
|
||||
|
||||
const path = require('path');
|
||||
const fs = require('fs-extra');
|
||||
const utils = require('./utils');
|
||||
const check_reqs = require('./check_reqs');
|
||||
const ROOT = path.join(__dirname, '..');
|
||||
const { createEditor } = require('properties-parser');
|
||||
const CordovaGradleConfigParserFactory = require('./config/CordovaGradleConfigParserFactory');
|
||||
var path = require('path');
|
||||
var fs = require('fs-extra');
|
||||
var utils = require('../templates/cordova/lib/utils');
|
||||
var check_reqs = require('./../templates/cordova/lib/check_reqs');
|
||||
var ROOT = path.join(__dirname, '..', '..');
|
||||
|
||||
const CordovaError = require('cordova-common').CordovaError;
|
||||
const AndroidManifest = require('./AndroidManifest');
|
||||
var CordovaError = require('cordova-common').CordovaError;
|
||||
var AndroidManifest = require('../templates/cordova/lib/AndroidManifest');
|
||||
|
||||
// Export all helper functions, and make sure internally within this module, we
|
||||
// reference these methods via the `exports` object - this helps with testing
|
||||
@@ -38,17 +36,22 @@ exports.copyScripts = copyScripts;
|
||||
exports.copyBuildRules = copyBuildRules;
|
||||
exports.writeProjectProperties = writeProjectProperties;
|
||||
exports.prepBuildFiles = prepBuildFiles;
|
||||
exports.writeNameForAndroidStudio = writeNameForAndroidStudio;
|
||||
|
||||
function getFrameworkDir (projectPath, shared) {
|
||||
return shared ? path.join(ROOT, 'framework') : path.join(projectPath, 'CordovaLib');
|
||||
}
|
||||
|
||||
function copyJsAndLibrary (projectPath, shared, projectName, targetAPI) {
|
||||
const nestedCordovaLibPath = getFrameworkDir(projectPath, false);
|
||||
const srcCordovaJsPath = path.join(ROOT, 'templates', 'project', 'assets', 'www', 'cordova.js');
|
||||
const app_path = path.join(projectPath, 'app', 'src', 'main');
|
||||
function copyJsAndLibrary (projectPath, shared, projectName, isLegacy) {
|
||||
var nestedCordovaLibPath = getFrameworkDir(projectPath, false);
|
||||
var srcCordovaJsPath = path.join(ROOT, 'bin', 'templates', 'project', 'assets', 'www', 'cordova.js');
|
||||
var app_path = path.join(projectPath, 'app', 'src', 'main');
|
||||
const platform_www = path.join(projectPath, 'platform_www');
|
||||
|
||||
if (isLegacy) {
|
||||
app_path = projectPath;
|
||||
}
|
||||
|
||||
fs.copySync(srcCordovaJsPath, path.join(app_path, 'assets', 'www', 'cordova.js'));
|
||||
|
||||
// Copy the cordova.js file to platforms/<platform>/platform_www/
|
||||
@@ -56,27 +59,28 @@ function copyJsAndLibrary (projectPath, shared, projectName, targetAPI) {
|
||||
fs.ensureDirSync(platform_www);
|
||||
fs.copySync(srcCordovaJsPath, path.join(platform_www, 'cordova.js'));
|
||||
|
||||
// Copy cordova-js-src directory into platform_www directory.
|
||||
// We need these files to build cordova.js if using browserify method.
|
||||
fs.copySync(path.join(ROOT, 'cordova-js-src'), path.join(platform_www, 'cordova-js-src'));
|
||||
|
||||
if (shared) {
|
||||
const relativeFrameworkPath = path.relative(projectPath, getFrameworkDir(projectPath, true));
|
||||
var relativeFrameworkPath = path.relative(projectPath, getFrameworkDir(projectPath, true));
|
||||
fs.symlinkSync(relativeFrameworkPath, nestedCordovaLibPath, 'dir');
|
||||
} else {
|
||||
fs.ensureDirSync(nestedCordovaLibPath);
|
||||
fs.copySync(path.join(ROOT, 'framework', 'AndroidManifest.xml'), path.join(nestedCordovaLibPath, 'AndroidManifest.xml'));
|
||||
const propertiesEditor = createEditor(path.join(ROOT, 'framework', 'project.properties'));
|
||||
propertiesEditor.set('target', targetAPI);
|
||||
propertiesEditor.save(path.join(nestedCordovaLibPath, 'project.properties'));
|
||||
fs.copySync(path.join(ROOT, 'framework', 'project.properties'), path.join(nestedCordovaLibPath, 'project.properties'));
|
||||
fs.copySync(path.join(ROOT, 'framework', 'build.gradle'), path.join(nestedCordovaLibPath, 'build.gradle'));
|
||||
fs.copySync(path.join(ROOT, 'framework', 'cordova.gradle'), path.join(nestedCordovaLibPath, 'cordova.gradle'));
|
||||
fs.copySync(path.join(ROOT, 'framework', 'repositories.gradle'), path.join(nestedCordovaLibPath, 'repositories.gradle'));
|
||||
fs.copySync(path.join(ROOT, 'framework', 'src'), path.join(nestedCordovaLibPath, 'src'));
|
||||
fs.copySync(path.join(ROOT, 'framework', 'cdv-gradle-config-defaults.json'), path.join(projectPath, 'cdv-gradle-config.json'));
|
||||
}
|
||||
}
|
||||
|
||||
function extractSubProjectPaths (data) {
|
||||
const ret = {};
|
||||
const r = /^\s*android\.library\.reference\.\d+=(.*)(?:\s|$)/mg;
|
||||
let m;
|
||||
var ret = {};
|
||||
var r = /^\s*android\.library\.reference\.\d+=(.*)(?:\s|$)/mg;
|
||||
var m;
|
||||
while ((m = r.exec(data))) {
|
||||
ret[m[1]] = 1;
|
||||
}
|
||||
@@ -84,13 +88,13 @@ function extractSubProjectPaths (data) {
|
||||
}
|
||||
|
||||
function writeProjectProperties (projectPath, target_api) {
|
||||
const dstPath = path.join(projectPath, 'project.properties');
|
||||
const templatePath = path.join(ROOT, 'templates', 'project', 'project.properties');
|
||||
const srcPath = fs.existsSync(dstPath) ? dstPath : templatePath;
|
||||
var dstPath = path.join(projectPath, 'project.properties');
|
||||
var templatePath = path.join(ROOT, 'bin', 'templates', 'project', 'project.properties');
|
||||
var srcPath = fs.existsSync(dstPath) ? dstPath : templatePath;
|
||||
|
||||
let data = fs.readFileSync(srcPath, 'utf8');
|
||||
var data = fs.readFileSync(srcPath, 'utf8');
|
||||
data = data.replace(/^target=.*/m, 'target=' + target_api);
|
||||
let subProjects = extractSubProjectPaths(data);
|
||||
var subProjects = extractSubProjectPaths(data);
|
||||
subProjects = subProjects.filter(function (p) {
|
||||
return !(/^CordovaLib$/m.exec(p) ||
|
||||
/[\\/]cordova-android[\\/]framework$/m.exec(p) ||
|
||||
@@ -101,7 +105,7 @@ function writeProjectProperties (projectPath, target_api) {
|
||||
if (!/\n$/.exec(data)) {
|
||||
data += '\n';
|
||||
}
|
||||
for (let i = 0; i < subProjects.length; ++i) {
|
||||
for (var i = 0; i < subProjects.length; ++i) {
|
||||
data += 'android.library.reference.' + (i + 1) + '=' + subProjects[i] + '\n';
|
||||
}
|
||||
fs.writeFileSync(dstPath, data);
|
||||
@@ -109,28 +113,54 @@ function writeProjectProperties (projectPath, target_api) {
|
||||
|
||||
// This makes no sense, what if you're building with a different build system?
|
||||
function prepBuildFiles (projectPath) {
|
||||
const buildModule = require('./builders/builders');
|
||||
var buildModule = require('../templates/cordova/lib/builders/builders');
|
||||
buildModule.getBuilder(projectPath).prepBuildFiles();
|
||||
}
|
||||
|
||||
function copyBuildRules (projectPath) {
|
||||
const srcDir = path.join(ROOT, 'templates', 'project');
|
||||
function copyBuildRules (projectPath, isLegacy) {
|
||||
var srcDir = path.join(ROOT, 'bin', 'templates', 'project');
|
||||
|
||||
fs.copySync(path.join(srcDir, 'build.gradle'), path.join(projectPath, 'build.gradle'));
|
||||
fs.copySync(path.join(srcDir, 'app', 'build.gradle'), path.join(projectPath, 'app', 'build.gradle'));
|
||||
fs.copySync(path.join(srcDir, 'app', 'repositories.gradle'), path.join(projectPath, 'app', 'repositories.gradle'));
|
||||
fs.copySync(path.join(srcDir, 'repositories.gradle'), path.join(projectPath, 'repositories.gradle'));
|
||||
|
||||
copyGradleTools(projectPath);
|
||||
if (isLegacy) {
|
||||
// The project's build.gradle is identical to the earlier build.gradle, so it should still work
|
||||
fs.copySync(path.join(srcDir, 'legacy', 'build.gradle'), path.join(projectPath, 'legacy', 'build.gradle'));
|
||||
fs.copySync(path.join(srcDir, 'wrapper.gradle'), path.join(projectPath, 'wrapper.gradle'));
|
||||
} else {
|
||||
fs.copySync(path.join(srcDir, 'build.gradle'), path.join(projectPath, 'build.gradle'));
|
||||
fs.copySync(path.join(srcDir, 'app', 'build.gradle'), path.join(projectPath, 'app', 'build.gradle'));
|
||||
fs.copySync(path.join(srcDir, 'app', 'repositories.gradle'), path.join(projectPath, 'app', 'repositories.gradle'));
|
||||
fs.copySync(path.join(srcDir, 'repositories.gradle'), path.join(projectPath, 'repositories.gradle'));
|
||||
fs.copySync(path.join(srcDir, 'wrapper.gradle'), path.join(projectPath, 'wrapper.gradle'));
|
||||
}
|
||||
}
|
||||
|
||||
function copyScripts (projectPath) {
|
||||
const srcScriptsDir = path.join(ROOT, 'templates', 'cordova');
|
||||
const destScriptsDir = path.join(projectPath, 'cordova');
|
||||
var bin = path.join(ROOT, 'bin');
|
||||
var srcScriptsDir = path.join(bin, 'templates', 'cordova');
|
||||
var destScriptsDir = path.join(projectPath, 'cordova');
|
||||
// Delete old scripts directory if this is an update.
|
||||
fs.removeSync(destScriptsDir);
|
||||
// Copy in the new ones.
|
||||
fs.copySync(srcScriptsDir, destScriptsDir);
|
||||
|
||||
const nodeModulesDir = path.join(ROOT, 'node_modules');
|
||||
if (fs.existsSync(nodeModulesDir)) fs.copySync(nodeModulesDir, path.join(destScriptsDir, 'node_modules'));
|
||||
|
||||
fs.copySync(path.join(bin, 'check_reqs'), path.join(destScriptsDir, 'check_reqs'));
|
||||
fs.copySync(path.join(bin, 'check_reqs.bat'), path.join(destScriptsDir, 'check_reqs.bat'));
|
||||
fs.copySync(path.join(bin, 'android_sdk_version'), path.join(destScriptsDir, 'android_sdk_version'));
|
||||
fs.copySync(path.join(bin, 'android_sdk_version.bat'), path.join(destScriptsDir, 'android_sdk_version.bat'));
|
||||
|
||||
var check_reqs = path.join(destScriptsDir, 'check_reqs');
|
||||
var android_sdk_version = path.join(destScriptsDir, 'android_sdk_version');
|
||||
|
||||
// TODO: the two files being edited on-the-fly here are shared between
|
||||
// platform and project-level commands. the below is updating the
|
||||
// `require` path for the two libraries. if there's a better way to share
|
||||
// modules across both the repo and generated projects, we should make sure
|
||||
// to remove/update this.
|
||||
const templatesCordovaRegex = /templates\/cordova\//;
|
||||
utils.replaceFileContents(android_sdk_version, templatesCordovaRegex, '');
|
||||
utils.replaceFileContents(check_reqs, templatesCordovaRegex, '');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -142,7 +172,7 @@ function validatePackageName (package_name) {
|
||||
// Make the package conform to Java package types
|
||||
// http://developer.android.com/guide/topics/manifest/manifest-element.html#package
|
||||
// Enforce underscore limitation
|
||||
const msg = 'Error validating package name. ';
|
||||
var msg = 'Error validating package name. ';
|
||||
|
||||
if (!/^[a-zA-Z][a-zA-Z0-9_]+(\.[a-zA-Z][a-zA-Z0-9_]*)+$/.test(package_name)) {
|
||||
return Promise.reject(new CordovaError(msg + 'Must look like: `com.company.Name`. Currently is: `' + package_name + '`'));
|
||||
@@ -162,7 +192,7 @@ function validatePackageName (package_name) {
|
||||
* otherwise.
|
||||
*/
|
||||
function validateProjectName (project_name) {
|
||||
const msg = 'Error validating project name. ';
|
||||
var msg = 'Error validating project name. ';
|
||||
// Make sure there's something there
|
||||
if (project_name === '') {
|
||||
return Promise.reject(new CordovaError(msg + 'Project name cannot be empty'));
|
||||
@@ -171,10 +201,17 @@ function validateProjectName (project_name) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
function copyGradleTools (projectPath) {
|
||||
const srcDir = path.join(ROOT, 'templates', 'project');
|
||||
|
||||
fs.copySync(path.resolve(srcDir, 'tools'), path.resolve(projectPath, 'tools'));
|
||||
/**
|
||||
* Write the name of the app in "platforms/android/.idea/.name" so that Android Studio can show that name in the
|
||||
* project listing. This is helpful to quickly look in the Android Studio listing if there are so many projects in
|
||||
* Android Studio.
|
||||
*
|
||||
* https://github.com/apache/cordova-android/issues/1172
|
||||
*/
|
||||
function writeNameForAndroidStudio (project_path, project_name) {
|
||||
const ideaPath = path.join(project_path, '.idea');
|
||||
fs.ensureDirSync(ideaPath);
|
||||
fs.writeFileSync(path.join(ideaPath, '.name'), project_name);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -199,37 +236,36 @@ exports.create = function (project_path, config, options, events) {
|
||||
options = options || {};
|
||||
|
||||
// Set default values for path, package and name
|
||||
project_path = path.relative(process.cwd(), project_path);
|
||||
project_path = path.relative(process.cwd(), (project_path || 'CordovaExample'));
|
||||
// Check if project already exists
|
||||
if (fs.existsSync(project_path)) {
|
||||
return Promise.reject(new CordovaError('Project already exists! Delete and recreate'));
|
||||
}
|
||||
|
||||
const package_name = config.android_packageName() || config.packageName() || 'io.cordova.helloCordova';
|
||||
const project_name = config.name() || 'Hello Cordova';
|
||||
var package_name = config.android_packageName() || config.packageName() || 'my.cordova.project';
|
||||
var project_name = config.name()
|
||||
? config.name().replace(/[^\w.]/g, '_') : 'CordovaExample';
|
||||
|
||||
const safe_activity_name = config.android_activityName() || options.activityName || 'MainActivity';
|
||||
const target_api = check_reqs.get_target(project_path);
|
||||
const compile_api = check_reqs.get_compile(project_path);
|
||||
var safe_activity_name = config.android_activityName() || options.activityName || 'MainActivity';
|
||||
var target_api = check_reqs.get_target();
|
||||
|
||||
// Make the package conform to Java package types
|
||||
return exports.validatePackageName(package_name)
|
||||
.then(function () {
|
||||
return exports.validateProjectName(project_name);
|
||||
}).then(function () {
|
||||
// Log the given values for the project
|
||||
// Log the given values for the project
|
||||
events.emit('log', 'Creating Cordova project for the Android platform:');
|
||||
events.emit('log', '\tPath: ' + project_path);
|
||||
events.emit('log', '\tPackage: ' + package_name);
|
||||
events.emit('log', '\tName: ' + project_name);
|
||||
events.emit('log', '\tActivity: ' + safe_activity_name);
|
||||
events.emit('log', '\tAndroid Target SDK: ' + target_api);
|
||||
events.emit('log', '\tAndroid Compile SDK: ' + compile_api);
|
||||
events.emit('log', '\tAndroid target: ' + target_api);
|
||||
|
||||
events.emit('verbose', 'Copying android template project to ' + project_path);
|
||||
|
||||
const project_template_dir = options.customTemplate || path.join(ROOT, 'templates', 'project');
|
||||
const app_path = path.join(project_path, 'app', 'src', 'main');
|
||||
var project_template_dir = options.customTemplate || path.join(ROOT, 'bin', 'templates', 'project');
|
||||
var app_path = path.join(project_path, 'app', 'src', 'main');
|
||||
|
||||
// copy project template
|
||||
fs.ensureDirSync(app_path);
|
||||
@@ -241,36 +277,32 @@ exports.create = function (project_path, config, options, events) {
|
||||
fs.ensureDirSync(path.join(app_path, 'libs'));
|
||||
|
||||
// copy cordova.js, cordova.jar
|
||||
exports.copyJsAndLibrary(project_path, options.link, safe_activity_name, target_api);
|
||||
exports.copyJsAndLibrary(project_path, options.link, safe_activity_name);
|
||||
|
||||
// Set up ther Android Studio paths
|
||||
const java_path = path.join(app_path, 'java');
|
||||
const assets_path = path.join(app_path, 'assets');
|
||||
const resource_path = path.join(app_path, 'res');
|
||||
var java_path = path.join(app_path, 'java');
|
||||
var assets_path = path.join(app_path, 'assets');
|
||||
var resource_path = path.join(app_path, 'res');
|
||||
fs.ensureDirSync(java_path);
|
||||
fs.ensureDirSync(assets_path);
|
||||
fs.ensureDirSync(resource_path);
|
||||
|
||||
// store package name in cdv-gradle-config
|
||||
const cdvGradleConfig = CordovaGradleConfigParserFactory.create(project_path);
|
||||
cdvGradleConfig.setPackageName(package_name)
|
||||
.write();
|
||||
|
||||
// interpolate the activity name and package
|
||||
const packagePath = package_name.replace(/\./g, path.sep);
|
||||
const activity_dir = path.join(java_path, packagePath);
|
||||
const activity_path = path.join(activity_dir, safe_activity_name + '.java');
|
||||
var packagePath = package_name.replace(/\./g, path.sep);
|
||||
var activity_dir = path.join(java_path, packagePath);
|
||||
var activity_path = path.join(activity_dir, safe_activity_name + '.java');
|
||||
|
||||
fs.ensureDirSync(activity_dir);
|
||||
fs.copySync(path.join(project_template_dir, 'Activity.java'), activity_path);
|
||||
utils.replaceFileContents(activity_path, /__ACTIVITY__/, safe_activity_name);
|
||||
utils.replaceFileContents(path.join(app_path, 'res', 'values', 'strings.xml'), /__NAME__/, utils.escape(project_name));
|
||||
utils.replaceFileContents(path.join(app_path, 'res', 'values', 'strings.xml'), /__NAME__/, project_name);
|
||||
utils.replaceFileContents(activity_path, /__ID__/, package_name);
|
||||
|
||||
const manifest = new AndroidManifest(path.join(project_template_dir, 'AndroidManifest.xml'));
|
||||
manifest.getActivity().setName(safe_activity_name);
|
||||
var manifest = new AndroidManifest(path.join(project_template_dir, 'AndroidManifest.xml'));
|
||||
manifest.setPackageId(package_name)
|
||||
.getActivity().setName(safe_activity_name);
|
||||
|
||||
const manifest_path = path.join(app_path, 'AndroidManifest.xml');
|
||||
var manifest_path = path.join(app_path, 'AndroidManifest.xml');
|
||||
manifest.write(manifest_path);
|
||||
|
||||
exports.copyScripts(project_path);
|
||||
@@ -279,13 +311,14 @@ exports.create = function (project_path, config, options, events) {
|
||||
// Link it to local android install.
|
||||
exports.writeProjectProperties(project_path, target_api);
|
||||
exports.prepBuildFiles(project_path);
|
||||
exports.writeNameForAndroidStudio(project_path, project_name);
|
||||
events.emit('log', generateDoneMessage('create', options.link));
|
||||
}).then(() => project_path);
|
||||
};
|
||||
|
||||
function generateDoneMessage (type, link) {
|
||||
const pkg = require('../package');
|
||||
let msg = 'Android project ' + (type === 'update' ? 'updated ' : 'created ') + 'with ' + pkg.name + '@' + pkg.version;
|
||||
var pkg = require('../../package');
|
||||
var msg = 'Android project ' + (type === 'update' ? 'updated ' : 'created ') + 'with ' + pkg.name + '@' + pkg.version;
|
||||
if (link) {
|
||||
msg += ' and has a linked CordovaLib';
|
||||
}
|
||||
@@ -294,7 +327,7 @@ function generateDoneMessage (type, link) {
|
||||
|
||||
// Returns a promise.
|
||||
exports.update = function (projectPath, options, events) {
|
||||
const errorString =
|
||||
var errorString =
|
||||
'An in-place platform update is not supported. \n' +
|
||||
'The `platforms` folder is always treated as a build artifact in the CLI workflow.\n' +
|
||||
'To update your platform, you have to remove, then add your android platform again.\n' +
|
||||
74
lib/Api.js → bin/templates/cordova/Api.js
vendored
@@ -17,18 +17,26 @@
|
||||
under the License.
|
||||
*/
|
||||
|
||||
const path = require('path');
|
||||
/**
|
||||
* @todo update coho to update this line.
|
||||
* @todo use `package.json` instead but first
|
||||
* figure out how this fit in with the platform-centered workflow structure.
|
||||
* This workflow would not have the `package.json` file.
|
||||
*/
|
||||
// Coho updates this line
|
||||
const VERSION = '9.1.0';
|
||||
|
||||
const AndroidProject = require('./AndroidProject');
|
||||
const PluginManager = require('cordova-common').PluginManager;
|
||||
var path = require('path');
|
||||
|
||||
const CordovaLogger = require('cordova-common').CordovaLogger;
|
||||
const selfEvents = require('cordova-common').events;
|
||||
const ConfigParser = require('cordova-common').ConfigParser;
|
||||
const prepare = require('./prepare').prepare;
|
||||
var AndroidProject = require('./lib/AndroidProject');
|
||||
var PluginManager = require('cordova-common').PluginManager;
|
||||
|
||||
const PLATFORM = 'android';
|
||||
const VERSION = require('../package').version;
|
||||
var CordovaLogger = require('cordova-common').CordovaLogger;
|
||||
var selfEvents = require('cordova-common').events;
|
||||
var ConfigParser = require('cordova-common').ConfigParser;
|
||||
const prepare = require('./lib/prepare').prepare;
|
||||
|
||||
var PLATFORM = 'android';
|
||||
|
||||
function setupEvents (externalEventEmitter) {
|
||||
if (externalEventEmitter) {
|
||||
@@ -58,7 +66,7 @@ function setupEvents (externalEventEmitter) {
|
||||
class Api {
|
||||
constructor (platform, platformRootDir, events) {
|
||||
this.platform = PLATFORM;
|
||||
this.root = platformRootDir;
|
||||
this.root = path.resolve(__dirname, '..');
|
||||
|
||||
setupEvents(events);
|
||||
|
||||
@@ -73,14 +81,12 @@ class Api {
|
||||
configXml: path.join(appRes, 'xml', 'config.xml'),
|
||||
defaultConfigXml: path.join(this.root, 'cordova', 'defaults.xml'),
|
||||
strings: path.join(appRes, 'values', 'strings.xml'),
|
||||
themes: path.join(appRes, 'values', 'themes.xml'),
|
||||
colors: path.join(appRes, 'values', 'colors.xml'),
|
||||
manifest: path.join(appMain, 'AndroidManifest.xml'),
|
||||
build: path.join(this.root, 'build'),
|
||||
javaSrc: path.join(appMain, 'java')
|
||||
};
|
||||
|
||||
this._builder = require('./builders/builders').getBuilder(this.root);
|
||||
this._builder = require('./lib/builders/builders').getBuilder(this.root);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -90,7 +96,7 @@ class Api {
|
||||
* platform's file structure and other properties of platform.
|
||||
*/
|
||||
getPlatformInfo () {
|
||||
const result = {};
|
||||
var result = {};
|
||||
result.locations = this.locations;
|
||||
result.root = this.root;
|
||||
result.name = this.platform;
|
||||
@@ -141,8 +147,8 @@ class Api {
|
||||
* CordovaError instance.
|
||||
*/
|
||||
addPlugin (plugin, installOptions) {
|
||||
const project = AndroidProject.getProjectFile(this.root);
|
||||
const self = this;
|
||||
var project = AndroidProject.getProjectFile(this.root);
|
||||
var self = this;
|
||||
|
||||
installOptions = installOptions || {};
|
||||
installOptions.variables = installOptions.variables || {};
|
||||
@@ -177,7 +183,7 @@ class Api {
|
||||
* CordovaError instance.
|
||||
*/
|
||||
removePlugin (plugin, uninstallOptions) {
|
||||
const project = AndroidProject.getProjectFile(this.root);
|
||||
var project = AndroidProject.getProjectFile(this.root);
|
||||
|
||||
if (uninstallOptions && uninstallOptions.usePlatformWww === true) {
|
||||
uninstallOptions.usePlatformWww = false;
|
||||
@@ -241,10 +247,10 @@ class Api {
|
||||
* arhcitectures is specified.
|
||||
*/
|
||||
build (buildOptions) {
|
||||
const self = this;
|
||||
var self = this;
|
||||
|
||||
return require('./check_reqs').run().then(function () {
|
||||
return require('./build').run.call(self, buildOptions);
|
||||
return require('./lib/check_reqs').run().then(function () {
|
||||
return require('./lib/build').run.call(self, buildOptions);
|
||||
}).then(function (buildResults) {
|
||||
// Cast build result to array of build artifacts
|
||||
return buildResults.paths.map(function (apkPath) {
|
||||
@@ -271,15 +277,9 @@ class Api {
|
||||
* successfully, or rejected with CordovaError.
|
||||
*/
|
||||
run (runOptions) {
|
||||
const self = this;
|
||||
return require('./check_reqs').run().then(function () {
|
||||
return require('./run').run.call(self, runOptions);
|
||||
});
|
||||
}
|
||||
|
||||
listTargets (options) {
|
||||
return require('./check_reqs').check_android().then(() => {
|
||||
return require('./run').runListDevices.call(this, options);
|
||||
var self = this;
|
||||
return require('./lib/check_reqs').run().then(function () {
|
||||
return require('./lib/run').run.call(self, runOptions);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -291,16 +291,16 @@ class Api {
|
||||
* CordovaError.
|
||||
*/
|
||||
clean (cleanOptions) {
|
||||
const self = this;
|
||||
var self = this;
|
||||
// This will lint, checking for null won't
|
||||
if (typeof cleanOptions === 'undefined') {
|
||||
cleanOptions = {};
|
||||
}
|
||||
|
||||
return require('./check_reqs').run().then(function () {
|
||||
return require('./build').runClean.call(self, cleanOptions);
|
||||
return require('./lib/check_reqs').run().then(function () {
|
||||
return require('./lib/build').runClean.call(self, cleanOptions);
|
||||
}).then(function () {
|
||||
return require('./prepare').clean.call(self, cleanOptions);
|
||||
return require('./lib/prepare').clean.call(self, cleanOptions);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -313,7 +313,7 @@ class Api {
|
||||
* objects for current platform.
|
||||
*/
|
||||
requirements () {
|
||||
return require('./check_reqs').check_all(this.root);
|
||||
return require('./lib/check_reqs').check_all();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -336,9 +336,9 @@ class Api {
|
||||
*/
|
||||
static createPlatform (destination, config, options, events) {
|
||||
events = setupEvents(events);
|
||||
let result;
|
||||
var result;
|
||||
try {
|
||||
result = require('./create').create(destination, config, options, events).then(function (destination) {
|
||||
result = require('../../lib/create').create(destination, config, options, events).then(function (destination) {
|
||||
return new Api(PLATFORM, destination, events);
|
||||
});
|
||||
} catch (e) {
|
||||
@@ -366,7 +366,7 @@ class Api {
|
||||
*/
|
||||
static updatePlatform (destination, options, events) {
|
||||
events = setupEvents(events);
|
||||
let result;
|
||||
var result;
|
||||
try {
|
||||
result = require('../../lib/create').update(destination, options, events).then(function (destination) {
|
||||
return new Api(PLATFORM, destination, events);
|
||||
51
bin/templates/cordova/build
Executable file
@@ -0,0 +1,51 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
/*
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
*/
|
||||
|
||||
var args = process.argv;
|
||||
var Api = require('./Api');
|
||||
var nopt = require('nopt');
|
||||
var path = require('path');
|
||||
|
||||
// Support basic help commands
|
||||
if (['--help', '/?', '-h', 'help', '-help', '/help'].indexOf(args[2]) >= 0) {
|
||||
require('./lib/build').help();
|
||||
}
|
||||
|
||||
// Do some basic argument parsing
|
||||
var buildOpts = nopt({
|
||||
verbose: Boolean,
|
||||
silent: Boolean,
|
||||
debug: Boolean,
|
||||
release: Boolean,
|
||||
nobuild: Boolean,
|
||||
buildConfig: path
|
||||
}, { d: '--verbose' });
|
||||
|
||||
// Make buildOptions compatible with PlatformApi build method spec
|
||||
buildOpts.argv = buildOpts.argv.original;
|
||||
|
||||
require('./loggingHelper').adjustLoggerLevel(buildOpts);
|
||||
|
||||
new Api().build(buildOpts)
|
||||
.catch(function (err) {
|
||||
console.error(err.stack);
|
||||
process.exit(2);
|
||||
});
|
||||
26
bin/templates/cordova/build.bat
Normal file
@@ -0,0 +1,26 @@
|
||||
:: Licensed to the Apache Software Foundation (ASF) under one
|
||||
:: or more contributor license agreements. See the NOTICE file
|
||||
:: distributed with this work for additional information
|
||||
:: regarding copyright ownership. The ASF licenses this file
|
||||
:: to you under the Apache License, Version 2.0 (the
|
||||
:: "License"); you may not use this file except in compliance
|
||||
:: with the License. You may obtain a copy of the License at
|
||||
::
|
||||
:: http://www.apache.org/licenses/LICENSE-2.0
|
||||
::
|
||||
:: Unless required by applicable law or agreed to in writing,
|
||||
:: software distributed under the License is distributed on an
|
||||
:: "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
:: KIND, either express or implied. See the License for the
|
||||
:: specific language governing permissions and limitations
|
||||
:: under the License.
|
||||
|
||||
@ECHO OFF
|
||||
SET script_path="%~dp0build"
|
||||
IF EXIST %script_path% (
|
||||
node %script_path% %*
|
||||
) ELSE (
|
||||
ECHO.
|
||||
ECHO ERROR: Could not find 'build' script in 'cordova' folder, aborting...>&2
|
||||
EXIT /B 1
|
||||
)
|
||||
51
bin/templates/cordova/clean
Executable file
@@ -0,0 +1,51 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
/*
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
*/
|
||||
|
||||
var Api = require('./Api');
|
||||
var path = require('path');
|
||||
var nopt = require('nopt');
|
||||
|
||||
// Support basic help commands
|
||||
if (['--help', '/?', '-h', 'help', '-help', '/help'].indexOf(process.argv[2]) >= 0) {
|
||||
console.log('Usage: ' + path.relative(process.cwd(), process.argv[1]));
|
||||
console.log('Cleans the project directory.');
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
// Do some basic argument parsing
|
||||
var opts = nopt({
|
||||
verbose: Boolean,
|
||||
silent: Boolean
|
||||
}, { d: '--verbose' });
|
||||
|
||||
// Make buildOptions compatible with PlatformApi clean method spec
|
||||
opts.argv = opts.argv.original;
|
||||
|
||||
// Skip cleaning prepared files when not invoking via cordova CLI.
|
||||
opts.noPrepare = true;
|
||||
|
||||
require('./loggingHelper').adjustLoggerLevel(opts);
|
||||
|
||||
new Api().clean(opts)
|
||||
.catch(function (err) {
|
||||
console.error(err.stack);
|
||||
process.exit(2);
|
||||
});
|
||||
26
bin/templates/cordova/clean.bat
Normal file
@@ -0,0 +1,26 @@
|
||||
:: Licensed to the Apache Software Foundation (ASF) under one
|
||||
:: or more contributor license agreements. See the NOTICE file
|
||||
:: distributed with this work for additional information
|
||||
:: regarding copyright ownership. The ASF licenses this file
|
||||
:: to you under the Apache License, Version 2.0 (the
|
||||
:: "License"); you may not use this file except in compliance
|
||||
:: with the License. You may obtain a copy of the License at
|
||||
::
|
||||
:: http://www.apache.org/licenses/LICENSE-2.0
|
||||
::
|
||||
:: Unless required by applicable law or agreed to in writing,
|
||||
:: software distributed under the License is distributed on an
|
||||
:: "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
:: KIND, either express or implied. See the License for the
|
||||
:: specific language governing permissions and limitations
|
||||
:: under the License.
|
||||
|
||||
@ECHO OFF
|
||||
SET script_path="%~dp0clean"
|
||||
IF EXIST %script_path% (
|
||||
node %script_path% %*
|
||||
) ELSE (
|
||||
ECHO.
|
||||
ECHO ERROR: Could not find 'clean' script in 'cordova' folder, aborting...>&2
|
||||
EXIT /B 1
|
||||
)
|
||||
14
lib/Adb.js → bin/templates/cordova/lib/Adb.js
vendored
@@ -17,12 +17,12 @@
|
||||
under the License.
|
||||
*/
|
||||
|
||||
const os = require('os');
|
||||
const execa = require('execa');
|
||||
const events = require('cordova-common').events;
|
||||
const CordovaError = require('cordova-common').CordovaError;
|
||||
var os = require('os');
|
||||
var execa = require('execa');
|
||||
var events = require('cordova-common').events;
|
||||
var CordovaError = require('cordova-common').CordovaError;
|
||||
|
||||
const Adb = {};
|
||||
var Adb = {};
|
||||
|
||||
/**
|
||||
* Lists available/connected devices and emulators
|
||||
@@ -50,7 +50,7 @@ Adb.devices = async function () {
|
||||
Adb.install = function (target, packagePath, { replace = false, execOptions = {} } = {}) {
|
||||
events.emit('verbose', 'Installing apk ' + packagePath + ' on target ' + target + '...');
|
||||
|
||||
const args = ['-s', target, 'install'];
|
||||
var args = ['-s', target, 'install'];
|
||||
if (replace) args.push('-r');
|
||||
|
||||
const opts = { cwd: os.tmpdir(), ...execOptions };
|
||||
@@ -79,7 +79,7 @@ Adb.uninstall = function (target, packageId) {
|
||||
|
||||
Adb.shell = function (target, shellCommand) {
|
||||
events.emit('verbose', 'Running adb shell command "' + shellCommand + '" on target ' + target + '...');
|
||||
const args = ['-s', target, 'shell'];
|
||||
var args = ['-s', target, 'shell'];
|
||||
shellCommand = shellCommand.split(/\s+/);
|
||||
return execa('adb', args.concat(shellCommand), { cwd: os.tmpdir() })
|
||||
.then(({ stdout }) => stdout)
|
||||
@@ -17,10 +17,10 @@
|
||||
under the License.
|
||||
*/
|
||||
|
||||
const fs = require('fs');
|
||||
const xml = require('cordova-common').xmlHelpers;
|
||||
var fs = require('fs');
|
||||
var xml = require('cordova-common').xmlHelpers;
|
||||
|
||||
const DEFAULT_ORIENTATION = 'default';
|
||||
var DEFAULT_ORIENTATION = 'default';
|
||||
|
||||
/** Wraps an AndroidManifest file */
|
||||
class AndroidManifest {
|
||||
@@ -50,8 +50,17 @@ class AndroidManifest {
|
||||
return this;
|
||||
}
|
||||
|
||||
getPackageId () {
|
||||
return this.doc.getroot().attrib.package;
|
||||
}
|
||||
|
||||
setPackageId (pkgId) {
|
||||
this.doc.getroot().attrib.package = pkgId;
|
||||
return this;
|
||||
}
|
||||
|
||||
getActivity () {
|
||||
const activity = this.doc.getroot().find('./application/activity');
|
||||
var activity = this.doc.getroot().find('./application/activity');
|
||||
return {
|
||||
getName: function () {
|
||||
return activity.attrib['android:name'];
|
||||
@@ -94,7 +103,7 @@ class AndroidManifest {
|
||||
}
|
||||
|
||||
setDebuggable (value) {
|
||||
const application = this.doc.getroot().find('./application');
|
||||
var application = this.doc.getroot().find('./application');
|
||||
if (value) {
|
||||
application.attrib['android:debuggable'] = 'true';
|
||||
} else {
|
||||
@@ -17,16 +17,16 @@
|
||||
under the License.
|
||||
*/
|
||||
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const properties_parser = require('properties-parser');
|
||||
const pluginHandlers = require('./pluginHandlers');
|
||||
const CordovaGradleConfigParserFactory = require('./config/CordovaGradleConfigParserFactory');
|
||||
var fs = require('fs');
|
||||
var path = require('path');
|
||||
var properties_parser = require('properties-parser');
|
||||
var AndroidManifest = require('./AndroidManifest');
|
||||
var pluginHandlers = require('./pluginHandlers');
|
||||
|
||||
let projectFileCache = {};
|
||||
var projectFileCache = {};
|
||||
|
||||
function addToPropertyList (projectProperties, key, value) {
|
||||
let i = 1;
|
||||
var i = 1;
|
||||
while (projectProperties.get(key + '.' + i)) { i++; }
|
||||
|
||||
projectProperties.set(key + '.' + i, value);
|
||||
@@ -34,8 +34,8 @@ function addToPropertyList (projectProperties, key, value) {
|
||||
}
|
||||
|
||||
function removeFromPropertyList (projectProperties, key, value) {
|
||||
let i = 1;
|
||||
let currentValue;
|
||||
var i = 1;
|
||||
var currentValue;
|
||||
while ((currentValue = projectProperties.get(key + '.' + i))) {
|
||||
if (currentValue === value) {
|
||||
while ((currentValue = projectProperties.get(key + '.' + (i + 1)))) {
|
||||
@@ -51,7 +51,7 @@ function removeFromPropertyList (projectProperties, key, value) {
|
||||
}
|
||||
|
||||
function getRelativeLibraryPath (parentDir, subDir) {
|
||||
const libraryPath = path.relative(parentDir, subDir);
|
||||
var libraryPath = path.relative(parentDir, subDir);
|
||||
return (path.sep === '\\') ? libraryPath.replace(/\\/g, '/') : libraryPath;
|
||||
}
|
||||
|
||||
@@ -63,36 +63,36 @@ class AndroidProject {
|
||||
this.projectDir = projectDir;
|
||||
this.platformWww = path.join(this.projectDir, 'platform_www');
|
||||
this.www = path.join(this.projectDir, 'app/src/main/assets/www');
|
||||
this.cordovaGradleConfigParser = CordovaGradleConfigParserFactory.create(this.projectDir);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the package name out of the Cordova's Gradle Config file
|
||||
* Reads the package name out of the Android Manifest file
|
||||
*
|
||||
* @param {String} projectDir The absolute path to the directory containing the project
|
||||
* @return {String} The name of the package
|
||||
*/
|
||||
getPackageName () {
|
||||
return this.cordovaGradleConfigParser.getPackageName();
|
||||
var manifestPath = path.join(this.projectDir, 'app/src/main/AndroidManifest.xml');
|
||||
return new AndroidManifest(manifestPath).getPackageId();
|
||||
}
|
||||
|
||||
getCustomSubprojectRelativeDir (plugin_id, src) {
|
||||
// All custom subprojects are prefixed with the last portion of the package id.
|
||||
// This is to avoid collisions when opening multiple projects in Eclipse that have subprojects with the same name.
|
||||
const packageName = this.getPackageName();
|
||||
const lastDotIndex = packageName.lastIndexOf('.');
|
||||
const prefix = packageName.substring(lastDotIndex + 1);
|
||||
const subRelativeDir = path.join(plugin_id, prefix + '-' + path.basename(src));
|
||||
var packageName = this.getPackageName();
|
||||
var lastDotIndex = packageName.lastIndexOf('.');
|
||||
var prefix = packageName.substring(lastDotIndex + 1);
|
||||
var subRelativeDir = path.join(plugin_id, prefix + '-' + path.basename(src));
|
||||
return subRelativeDir;
|
||||
}
|
||||
|
||||
addSubProject (parentDir, subDir) {
|
||||
const parentProjectFile = path.resolve(parentDir, 'project.properties');
|
||||
const subProjectFile = path.resolve(subDir, 'project.properties');
|
||||
const parentProperties = this._getPropertiesFile(parentProjectFile);
|
||||
var parentProjectFile = path.resolve(parentDir, 'project.properties');
|
||||
var subProjectFile = path.resolve(subDir, 'project.properties');
|
||||
var parentProperties = this._getPropertiesFile(parentProjectFile);
|
||||
// TODO: Setting the target needs to happen only for pre-3.7.0 projects
|
||||
if (fs.existsSync(subProjectFile)) {
|
||||
const subProperties = this._getPropertiesFile(subProjectFile);
|
||||
var subProperties = this._getPropertiesFile(subProjectFile);
|
||||
subProperties.set('target', parentProperties.get('target'));
|
||||
subProperties.dirty = true;
|
||||
this._subProjectDirs[subDir] = true;
|
||||
@@ -103,37 +103,37 @@ class AndroidProject {
|
||||
}
|
||||
|
||||
removeSubProject (parentDir, subDir) {
|
||||
const parentProjectFile = path.resolve(parentDir, 'project.properties');
|
||||
const parentProperties = this._getPropertiesFile(parentProjectFile);
|
||||
var parentProjectFile = path.resolve(parentDir, 'project.properties');
|
||||
var parentProperties = this._getPropertiesFile(parentProjectFile);
|
||||
removeFromPropertyList(parentProperties, 'android.library.reference', getRelativeLibraryPath(parentDir, subDir));
|
||||
delete this._subProjectDirs[subDir];
|
||||
this._dirty = true;
|
||||
}
|
||||
|
||||
addGradleReference (parentDir, subDir) {
|
||||
const parentProjectFile = path.resolve(parentDir, 'project.properties');
|
||||
const parentProperties = this._getPropertiesFile(parentProjectFile);
|
||||
var parentProjectFile = path.resolve(parentDir, 'project.properties');
|
||||
var parentProperties = this._getPropertiesFile(parentProjectFile);
|
||||
addToPropertyList(parentProperties, 'cordova.gradle.include', getRelativeLibraryPath(parentDir, subDir));
|
||||
this._dirty = true;
|
||||
}
|
||||
|
||||
removeGradleReference (parentDir, subDir) {
|
||||
const parentProjectFile = path.resolve(parentDir, 'project.properties');
|
||||
const parentProperties = this._getPropertiesFile(parentProjectFile);
|
||||
var parentProjectFile = path.resolve(parentDir, 'project.properties');
|
||||
var parentProperties = this._getPropertiesFile(parentProjectFile);
|
||||
removeFromPropertyList(parentProperties, 'cordova.gradle.include', getRelativeLibraryPath(parentDir, subDir));
|
||||
this._dirty = true;
|
||||
}
|
||||
|
||||
addSystemLibrary (parentDir, value) {
|
||||
const parentProjectFile = path.resolve(parentDir, 'project.properties');
|
||||
const parentProperties = this._getPropertiesFile(parentProjectFile);
|
||||
var parentProjectFile = path.resolve(parentDir, 'project.properties');
|
||||
var parentProperties = this._getPropertiesFile(parentProjectFile);
|
||||
addToPropertyList(parentProperties, 'cordova.system.library', value);
|
||||
this._dirty = true;
|
||||
}
|
||||
|
||||
removeSystemLibrary (parentDir, value) {
|
||||
const parentProjectFile = path.resolve(parentDir, 'project.properties');
|
||||
const parentProperties = this._getPropertiesFile(parentProjectFile);
|
||||
var parentProjectFile = path.resolve(parentDir, 'project.properties');
|
||||
var parentProperties = this._getPropertiesFile(parentProjectFile);
|
||||
removeFromPropertyList(parentProperties, 'cordova.system.library', value);
|
||||
this._dirty = true;
|
||||
}
|
||||
@@ -144,8 +144,8 @@ class AndroidProject {
|
||||
}
|
||||
this._dirty = false;
|
||||
|
||||
for (const filename in this._propertiesEditors) {
|
||||
const editor = this._propertiesEditors[filename];
|
||||
for (var filename in this._propertiesEditors) {
|
||||
var editor = this._propertiesEditors[filename];
|
||||
if (editor.dirty) {
|
||||
fs.writeFileSync(filename, editor.toString());
|
||||
editor.dirty = false;
|
||||
@@ -165,7 +165,7 @@ class AndroidProject {
|
||||
* This checks if an Android project is clean or has old build artifacts
|
||||
*/
|
||||
isClean () {
|
||||
const build_path = path.join(this.projectDir, 'build');
|
||||
var build_path = path.join(this.projectDir, 'build');
|
||||
// If the build directory doesn't exist, it's clean
|
||||
return !(fs.existsSync(build_path));
|
||||
}
|
||||
@@ -19,7 +19,7 @@
|
||||
|
||||
const execa = require('execa');
|
||||
|
||||
const suffix_number_regex = /(\d+)$/;
|
||||
var suffix_number_regex = /(\d+)$/;
|
||||
// Used for sorting Android targets, example strings to sort:
|
||||
// android-19
|
||||
// android-L
|
||||
@@ -66,9 +66,9 @@ module.exports.version_string_to_api_level = {
|
||||
/* eslint-enable quote-props */
|
||||
|
||||
function parse_targets (output) {
|
||||
const target_out = output.split('\n');
|
||||
const targets = [];
|
||||
for (let i = target_out.length - 1; i >= 0; i--) {
|
||||
var target_out = output.split('\n');
|
||||
var targets = [];
|
||||
for (var i = target_out.length - 1; i >= 0; i--) {
|
||||
if (target_out[i].match(/id:/)) { // if "id:" is in the line...
|
||||
targets.push(target_out[i].match(/"(.+)"/)[1]); // .. match whatever is in quotes.
|
||||
}
|
||||
@@ -76,12 +76,23 @@ function parse_targets (output) {
|
||||
return targets;
|
||||
}
|
||||
|
||||
module.exports.list_targets_with_android = function () {
|
||||
return execa('android', ['list', 'target']).then(result => parse_targets(result.stdout));
|
||||
};
|
||||
|
||||
module.exports.list_targets_with_avdmanager = function () {
|
||||
return execa('avdmanager', ['list', 'target']).then(result => parse_targets(result.stdout));
|
||||
};
|
||||
|
||||
module.exports.list_targets = function () {
|
||||
return module.exports.list_targets_with_avdmanager().then(function (targets) {
|
||||
return module.exports.list_targets_with_avdmanager().catch(function (err) {
|
||||
// If there's an error, like avdmanager could not be found, we can try
|
||||
// as a last resort, to run `android`, in case this is a super old
|
||||
// SDK installation.
|
||||
if (err && (err.code === 'ENOENT' || (err.stderr && err.stderr.match(/not recognized/)))) {
|
||||
return module.exports.list_targets_with_android();
|
||||
} else throw err;
|
||||
}).then(function (targets) {
|
||||
if (targets.length === 0) {
|
||||
return Promise.reject(new Error('No android targets (SDKs) installed!'));
|
||||
}
|
||||
@@ -17,16 +17,14 @@
|
||||
under the License.
|
||||
*/
|
||||
|
||||
const path = require('path');
|
||||
const fs = require('fs');
|
||||
const nopt = require('nopt');
|
||||
const untildify = require('untildify');
|
||||
const { parseArgsStringToArgv } = require('string-argv');
|
||||
var path = require('path');
|
||||
var fs = require('fs');
|
||||
var nopt = require('nopt');
|
||||
|
||||
const Adb = require('./Adb');
|
||||
var Adb = require('./Adb');
|
||||
|
||||
const events = require('cordova-common').events;
|
||||
const PackageType = require('./PackageType');
|
||||
var events = require('cordova-common').events;
|
||||
var PackageType = require('./PackageType');
|
||||
|
||||
module.exports.parseBuildOptions = parseOpts;
|
||||
function parseOpts (options, resolvedTarget, projectRoot) {
|
||||
@@ -37,11 +35,7 @@ function parseOpts (options, resolvedTarget, projectRoot) {
|
||||
minSdkVersion: String,
|
||||
maxSdkVersion: String,
|
||||
targetSdkVersion: String,
|
||||
|
||||
// This needs to be an array since nopts will parse its entries as further options for this process
|
||||
// It will be an array of 1 string: [ "string args" ]
|
||||
gradleArg: [String, Array],
|
||||
|
||||
keystore: path,
|
||||
alias: String,
|
||||
storePassword: String,
|
||||
@@ -51,7 +45,7 @@ function parseOpts (options, resolvedTarget, projectRoot) {
|
||||
}, {}, options.argv, 0);
|
||||
|
||||
// Android Studio Build method is the default
|
||||
const ret = {
|
||||
var ret = {
|
||||
buildType: options.release ? 'release' : 'debug',
|
||||
prepEnv: options.argv.prepenv,
|
||||
arch: resolvedTarget && resolvedTarget.arch,
|
||||
@@ -63,11 +57,10 @@ function parseOpts (options, resolvedTarget, projectRoot) {
|
||||
if (options.argv.maxSdkVersion) { ret.extraArgs.push('-PcdvMaxSdkVersion=' + options.argv.maxSdkVersion); }
|
||||
if (options.argv.targetSdkVersion) { ret.extraArgs.push('-PcdvTargetSdkVersion=' + options.argv.targetSdkVersion); }
|
||||
if (options.argv.gradleArg) {
|
||||
const gradleArgs = parseArgsStringToArgv(options.argv.gradleArg[0]);
|
||||
ret.extraArgs = ret.extraArgs.concat(gradleArgs);
|
||||
ret.extraArgs = ret.extraArgs.concat(options.argv.gradleArg);
|
||||
}
|
||||
|
||||
const packageArgs = {};
|
||||
var packageArgs = {};
|
||||
|
||||
if (options.argv.keystore) { packageArgs.keystore = path.relative(projectRoot, path.resolve(options.argv.keystore)); }
|
||||
|
||||
@@ -75,7 +68,7 @@ function parseOpts (options, resolvedTarget, projectRoot) {
|
||||
if (options.argv[flagName]) { packageArgs[flagName] = options.argv[flagName]; }
|
||||
});
|
||||
|
||||
const buildConfig = options.buildConfig;
|
||||
var buildConfig = options.buildConfig;
|
||||
|
||||
// If some values are not specified as command line arguments - use build config to supplement them.
|
||||
// Command line arguments have precedence over build config.
|
||||
@@ -84,12 +77,14 @@ function parseOpts (options, resolvedTarget, projectRoot) {
|
||||
throw new Error('Specified build config file does not exist: ' + buildConfig);
|
||||
}
|
||||
events.emit('log', 'Reading build config file: ' + path.resolve(buildConfig));
|
||||
const buildjson = fs.readFileSync(buildConfig, 'utf8');
|
||||
const config = JSON.parse(buildjson.replace(/^\ufeff/, '')); // Remove BOM
|
||||
var buildjson = fs.readFileSync(buildConfig, 'utf8');
|
||||
var config = JSON.parse(buildjson.replace(/^\ufeff/, '')); // Remove BOM
|
||||
if (config.android && config.android[ret.buildType]) {
|
||||
const androidInfo = config.android[ret.buildType];
|
||||
var androidInfo = config.android[ret.buildType];
|
||||
if (androidInfo.keystore && !packageArgs.keystore) {
|
||||
androidInfo.keystore = untildify(androidInfo.keystore);
|
||||
if (androidInfo.keystore.substr(0, 1) === '~') {
|
||||
androidInfo.keystore = process.env.HOME + androidInfo.keystore.substr(1);
|
||||
}
|
||||
packageArgs.keystore = path.resolve(path.dirname(buildConfig), androidInfo.keystore);
|
||||
events.emit('log', 'Reading the keystore from: ' + packageArgs.keystore);
|
||||
}
|
||||
@@ -135,11 +130,7 @@ function parseOpts (options, resolvedTarget, projectRoot) {
|
||||
ret.packageType = packageArgs.packageType;
|
||||
}
|
||||
} else {
|
||||
if (ret.buildType === 'release') {
|
||||
ret.packageType = PackageType.BUNDLE;
|
||||
} else {
|
||||
ret.packageType = PackageType.APK;
|
||||
}
|
||||
ret.packageType = PackageType.APK;
|
||||
}
|
||||
|
||||
return ret;
|
||||
@@ -150,8 +141,8 @@ function parseOpts (options, resolvedTarget, projectRoot) {
|
||||
* Returns a promise.
|
||||
*/
|
||||
module.exports.runClean = function (options) {
|
||||
const opts = parseOpts(options, null, this.root);
|
||||
const builder = this._builder;
|
||||
var opts = parseOpts(options, null, this.root);
|
||||
var builder = this._builder;
|
||||
|
||||
return builder.prepEnv(opts).then(function () {
|
||||
return builder.clean(opts);
|
||||
@@ -171,8 +162,8 @@ module.exports.runClean = function (options) {
|
||||
* information.
|
||||
*/
|
||||
module.exports.run = function (options, optResolvedTarget) {
|
||||
const opts = parseOpts(options, optResolvedTarget, this.root);
|
||||
const builder = this._builder;
|
||||
var opts = parseOpts(options, optResolvedTarget, this.root);
|
||||
var builder = this._builder;
|
||||
|
||||
return builder.prepEnv(opts).then(function () {
|
||||
if (opts.prepEnv) {
|
||||
@@ -180,7 +171,7 @@ module.exports.run = function (options, optResolvedTarget) {
|
||||
return;
|
||||
}
|
||||
return builder.build(opts).then(function () {
|
||||
let paths;
|
||||
var paths;
|
||||
if (opts.packageType === PackageType.BUNDLE) {
|
||||
paths = builder.findOutputBundles(opts.buildType);
|
||||
events.emit('log', 'Built the following bundle(s): \n\t' + paths.join('\n\t'));
|
||||
@@ -190,7 +181,7 @@ module.exports.run = function (options, optResolvedTarget) {
|
||||
}
|
||||
|
||||
return {
|
||||
paths,
|
||||
paths: paths,
|
||||
buildType: opts.buildType
|
||||
};
|
||||
});
|
||||
@@ -208,17 +199,17 @@ module.exports.detectArchitecture = function (target) {
|
||||
};
|
||||
|
||||
module.exports.findBestApkForArchitecture = function (buildResults, arch) {
|
||||
const paths = buildResults.apkPaths.filter(function (p) {
|
||||
const apkName = path.basename(p);
|
||||
var paths = buildResults.apkPaths.filter(function (p) {
|
||||
var apkName = path.basename(p);
|
||||
if (buildResults.buildType === 'debug') {
|
||||
return /-debug/.exec(apkName);
|
||||
}
|
||||
return !/-debug/.exec(apkName);
|
||||
});
|
||||
const archPattern = new RegExp('-' + arch);
|
||||
const hasArchPattern = /-x86|-arm/;
|
||||
for (let i = 0; i < paths.length; ++i) {
|
||||
const apkName = path.basename(paths[i]);
|
||||
var archPattern = new RegExp('-' + arch);
|
||||
var hasArchPattern = /-x86|-arm/;
|
||||
for (var i = 0; i < paths.length; ++i) {
|
||||
var apkName = path.basename(paths[i]);
|
||||
if (hasArchPattern.exec(apkName)) {
|
||||
if (archPattern.exec(apkName)) {
|
||||
return paths[i];
|
||||
@@ -250,3 +241,26 @@ PackageInfo.prototype = {
|
||||
propertiesParser.save();
|
||||
}
|
||||
};
|
||||
|
||||
module.exports.help = function () {
|
||||
console.log('Usage: ' + path.relative(process.cwd(), path.join('../build')) + ' [flags] [Signed APK flags]');
|
||||
console.log('Flags:');
|
||||
console.log(' \'--debug\': will build project in debug mode (default)');
|
||||
console.log(' \'--release\': will build project for release');
|
||||
console.log(' \'--nobuild\': will skip build process (useful when using run command)');
|
||||
console.log(' \'--prepenv\': don\'t build, but copy in build scripts where necessary');
|
||||
console.log(' \'--versionCode=#\': Override versionCode for this build. Useful for uploading multiple APKs.');
|
||||
console.log(' \'--minSdkVersion=#\': Override minSdkVersion for this build.');
|
||||
console.log(' \'--maxSdkVersion=#\': Override maxSdkVersion for this build. (Not Recommended)');
|
||||
console.log(' \'--targetSdkVersion=#\': Override targetSdkVersion for this build.');
|
||||
console.log(' \'--gradleArg=<gradle command line arg>\': Extra args to pass to the gradle command. Use one flag per arg. Ex. --gradleArg=-PcdvBuildMultipleApks=true');
|
||||
console.log(' \'--packageType=<apk|bundle>\': Builds an APK or a bundle');
|
||||
console.log('');
|
||||
console.log('Signed APK flags (overwrites debug/release-signing.proprties) :');
|
||||
console.log(' \'--keystore=<path to keystore>\': Key store used to build a signed archive. (Required)');
|
||||
console.log(' \'--alias=\': Alias for the key store. (Required)');
|
||||
console.log(' \'--storePassword=\': Password for the key store. (Optional - prompted)');
|
||||
console.log(' \'--password=\': Password for the key. (Optional - prompted)');
|
||||
console.log(' \'--keystoreType\': Type of the keystore. (Optional)');
|
||||
process.exit(0);
|
||||
};
|
||||
@@ -17,17 +17,16 @@
|
||||
under the License.
|
||||
*/
|
||||
|
||||
const fs = require('fs-extra');
|
||||
const path = require('path');
|
||||
var fs = require('fs-extra');
|
||||
var path = require('path');
|
||||
const execa = require('execa');
|
||||
const glob = require('fast-glob');
|
||||
const events = require('cordova-common').events;
|
||||
const CordovaError = require('cordova-common').CordovaError;
|
||||
const check_reqs = require('../check_reqs');
|
||||
const PackageType = require('../PackageType');
|
||||
const { compareByAll, isWindows } = require('../utils');
|
||||
var events = require('cordova-common').events;
|
||||
var CordovaError = require('cordova-common').CordovaError;
|
||||
var check_reqs = require('../check_reqs');
|
||||
var PackageType = require('../PackageType');
|
||||
const { compareByAll } = require('../utils');
|
||||
const { createEditor } = require('properties-parser');
|
||||
const CordovaGradleConfigParserFactory = require('../config/CordovaGradleConfigParserFactory');
|
||||
|
||||
const MARKER = 'YOUR CHANGES WILL BE ERASED!';
|
||||
const SIGNING_PROPERTIES = '-signing.properties';
|
||||
@@ -79,17 +78,13 @@ function findOutputFiles (bundleType, buildType, { arch } = {}) {
|
||||
|
||||
class ProjectBuilder {
|
||||
constructor (rootDirectory) {
|
||||
this.root = rootDirectory;
|
||||
this.root = rootDirectory || path.resolve(__dirname, '../../..');
|
||||
this.apkDir = path.join(this.root, 'app', 'build', 'outputs', 'apk');
|
||||
this.aabDir = path.join(this.root, 'app', 'build', 'outputs', 'bundle');
|
||||
}
|
||||
|
||||
getArgs (cmd, opts) {
|
||||
let args = [];
|
||||
if (opts.extraArgs) {
|
||||
args = args.concat(opts.extraArgs);
|
||||
}
|
||||
|
||||
let args;
|
||||
let buildCmd = cmd;
|
||||
if (opts.packageType === PackageType.BUNDLE) {
|
||||
if (cmd === 'release') {
|
||||
@@ -97,6 +92,8 @@ class ProjectBuilder {
|
||||
} else if (cmd === 'debug') {
|
||||
buildCmd = ':app:bundleDebug';
|
||||
}
|
||||
|
||||
args = [buildCmd, '-b', path.join(this.root, 'build.gradle')];
|
||||
} else {
|
||||
if (cmd === 'release') {
|
||||
buildCmd = 'cdvBuildRelease';
|
||||
@@ -104,71 +101,74 @@ class ProjectBuilder {
|
||||
buildCmd = 'cdvBuildDebug';
|
||||
}
|
||||
|
||||
args = [buildCmd, '-b', path.join(this.root, 'build.gradle')];
|
||||
|
||||
if (opts.arch) {
|
||||
args.push('-PcdvBuildArch=' + opts.arch);
|
||||
}
|
||||
}
|
||||
|
||||
args.push(buildCmd);
|
||||
args.push.apply(args, opts.extraArgs);
|
||||
|
||||
return args;
|
||||
}
|
||||
|
||||
getGradleWrapperPath () {
|
||||
let wrapper = path.join(this.root, 'tools', 'gradlew');
|
||||
|
||||
if (isWindows()) {
|
||||
wrapper += '.bat';
|
||||
}
|
||||
|
||||
return wrapper;
|
||||
}
|
||||
|
||||
/**
|
||||
* Installs/updates the gradle wrapper
|
||||
* @param {string} gradleVersion The gradle version to install. Ignored if CORDOVA_ANDROID_GRADLE_DISTRIBUTION_URL environment variable is defined
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
async installGradleWrapper (gradleVersion) {
|
||||
if (process.env.CORDOVA_ANDROID_GRADLE_DISTRIBUTION_URL) {
|
||||
events.emit('verbose', `Overriding Gradle Version via CORDOVA_ANDROID_GRADLE_DISTRIBUTION_URL (${process.env.CORDOVA_ANDROID_GRADLE_DISTRIBUTION_URL})`);
|
||||
await execa('gradle', ['-p', path.join(this.root, 'tools'), 'wrapper', '--gradle-distribution-url', process.env.CORDOVA_ANDROID_GRADLE_DISTRIBUTION_URL], { stdio: 'inherit' });
|
||||
/*
|
||||
* This returns a promise
|
||||
*/
|
||||
runGradleWrapper (gradle_cmd) {
|
||||
var gradlePath = path.join(this.root, 'gradlew');
|
||||
var wrapperGradle = path.join(this.root, 'wrapper.gradle');
|
||||
if (fs.existsSync(gradlePath)) {
|
||||
// Literally do nothing, for some reason this works, while !fs.existsSync didn't on Windows
|
||||
} else {
|
||||
await execa('gradle', ['-p', path.join(this.root, 'tools'), 'wrapper', '--gradle-version', gradleVersion], { stdio: 'inherit' });
|
||||
return execa(gradle_cmd, ['-p', this.root, 'wrapper', '-b', wrapperGradle], { stdio: 'inherit' });
|
||||
}
|
||||
}
|
||||
|
||||
readProjectProperties () {
|
||||
function findAllUniq (data, r) {
|
||||
const s = {};
|
||||
let m;
|
||||
var s = {};
|
||||
var m;
|
||||
while ((m = r.exec(data))) {
|
||||
s[m[1]] = 1;
|
||||
}
|
||||
return Object.keys(s);
|
||||
}
|
||||
|
||||
const data = fs.readFileSync(path.join(this.root, 'project.properties'), 'utf8');
|
||||
var data = fs.readFileSync(path.join(this.root, 'project.properties'), 'utf8');
|
||||
return {
|
||||
libs: findAllUniq(data, /^\s*android\.library\.reference\.\d+=(.*)(?:\s|$)/mg),
|
||||
gradleIncludes: findAllUniq(data, /^\s*cordova\.gradle\.include\.\d+=(.*)(?:\s|$)/mg),
|
||||
systemLibs: findAllUniq(data, /^\s*cordova\.system\.library\.\d+=((?!.*\().*)(?:\s|$)/mg),
|
||||
bomPlatforms: findAllUniq(data, /^\s*cordova\.system\.library\.\d+=platform\((?:'|")(.*)(?:'|")\)/mg)
|
||||
systemLibs: findAllUniq(data, /^\s*cordova\.system\.library\.\d+=(.*)(?:\s|$)/mg)
|
||||
};
|
||||
}
|
||||
|
||||
extractRealProjectNameFromManifest () {
|
||||
var manifestPath = path.join(this.root, 'app', 'src', 'main', 'AndroidManifest.xml');
|
||||
var manifestData = fs.readFileSync(manifestPath, 'utf8');
|
||||
var m = /<manifest[\s\S]*?package\s*=\s*"(.*?)"/i.exec(manifestData);
|
||||
if (!m) {
|
||||
throw new CordovaError('Could not find package name in ' + manifestPath);
|
||||
}
|
||||
|
||||
var packageName = m[1];
|
||||
var lastDotIndex = packageName.lastIndexOf('.');
|
||||
return packageName.substring(lastDotIndex + 1);
|
||||
}
|
||||
|
||||
// Makes the project buildable, minus the gradle wrapper.
|
||||
prepBuildFiles () {
|
||||
// Update the version of build.gradle in each dependent library.
|
||||
const pluginBuildGradle = path.join(__dirname, 'plugin-build.gradle');
|
||||
const propertiesObj = this.readProjectProperties();
|
||||
const subProjects = propertiesObj.libs;
|
||||
var pluginBuildGradle = path.join(this.root, 'cordova', 'lib', 'plugin-build.gradle');
|
||||
var propertiesObj = this.readProjectProperties();
|
||||
var subProjects = propertiesObj.libs;
|
||||
|
||||
// Check and copy the gradle file into the subproject
|
||||
// Called by the loop before this function def
|
||||
|
||||
const checkAndCopy = function (subProject, root) {
|
||||
const subProjectGradle = path.join(root, subProject, 'build.gradle');
|
||||
var checkAndCopy = function (subProject, root) {
|
||||
var subProjectGradle = path.join(root, subProject, 'build.gradle');
|
||||
// This is the future-proof way of checking if a file exists
|
||||
// This must be synchronous to satisfy a Travis test
|
||||
try {
|
||||
@@ -178,46 +178,34 @@ class ProjectBuilder {
|
||||
}
|
||||
};
|
||||
|
||||
for (let i = 0; i < subProjects.length; ++i) {
|
||||
for (var i = 0; i < subProjects.length; ++i) {
|
||||
if (subProjects[i] !== 'CordovaLib') {
|
||||
checkAndCopy(subProjects[i], this.root);
|
||||
}
|
||||
}
|
||||
|
||||
// get project name cdv-gradle-config.
|
||||
const cdvGradleConfig = CordovaGradleConfigParserFactory.create(this.root);
|
||||
const projectName = cdvGradleConfig.getProjectNameFromPackageName();
|
||||
|
||||
var name = this.extractRealProjectNameFromManifest();
|
||||
// Remove the proj.id/name- prefix from projects: https://issues.apache.org/jira/browse/CB-9149
|
||||
const settingsGradlePaths = subProjects.map(function (p) {
|
||||
const realDir = p.replace(/[/\\]/g, ':');
|
||||
const libName = realDir.replace(projectName + '-', '');
|
||||
let str = 'include ":' + libName + '"\n';
|
||||
if (realDir.indexOf(projectName + '-') !== -1) {
|
||||
var settingsGradlePaths = subProjects.map(function (p) {
|
||||
var realDir = p.replace(/[/\\]/g, ':');
|
||||
var libName = realDir.replace(name + '-', '');
|
||||
var str = 'include ":' + libName + '"\n';
|
||||
if (realDir.indexOf(name + '-') !== -1) {
|
||||
str += 'project(":' + libName + '").projectDir = new File("' + p + '")\n';
|
||||
}
|
||||
return str;
|
||||
});
|
||||
|
||||
// Update subprojects within settings.gradle.
|
||||
fs.writeFileSync(path.join(this.root, 'settings.gradle'),
|
||||
'// GENERATED FILE - DO NOT EDIT\n' +
|
||||
'apply from: "cdv-gradle-name.gradle"\n' +
|
||||
'include ":"\n' +
|
||||
settingsGradlePaths.join(''));
|
||||
|
||||
// Touch empty cdv-gradle-name.gradle file if missing.
|
||||
if (!fs.pathExistsSync(path.join(this.root, 'cdv-gradle-name.gradle'))) {
|
||||
fs.writeFileSync(path.join(this.root, 'cdv-gradle-name.gradle'), '');
|
||||
}
|
||||
'include ":"\n' + settingsGradlePaths.join(''));
|
||||
|
||||
// Update dependencies within build.gradle.
|
||||
let buildGradle = fs.readFileSync(path.join(this.root, 'app', 'build.gradle'), 'utf8');
|
||||
let depsList = '';
|
||||
const root = this.root;
|
||||
const insertExclude = function (p) {
|
||||
const gradlePath = path.join(root, p, 'build.gradle');
|
||||
const projectGradleFile = fs.readFileSync(gradlePath, 'utf-8');
|
||||
var buildGradle = fs.readFileSync(path.join(this.root, 'app', 'build.gradle'), 'utf8');
|
||||
var depsList = '';
|
||||
var root = this.root;
|
||||
var insertExclude = function (p) {
|
||||
var gradlePath = path.join(root, p, 'build.gradle');
|
||||
var projectGradleFile = fs.readFileSync(gradlePath, 'utf-8');
|
||||
if (projectGradleFile.indexOf('CordovaLib') !== -1) {
|
||||
depsList += '{\n exclude module:("CordovaLib")\n }\n';
|
||||
} else {
|
||||
@@ -226,39 +214,26 @@ class ProjectBuilder {
|
||||
};
|
||||
subProjects.forEach(function (p) {
|
||||
events.emit('log', 'Subproject Path: ' + p);
|
||||
const libName = p.replace(/[/\\]/g, ':').replace(projectName + '-', '');
|
||||
var libName = p.replace(/[/\\]/g, ':').replace(name + '-', '');
|
||||
if (libName !== 'app') {
|
||||
depsList += ' implementation(project(path: ":' + libName + '"))';
|
||||
insertExclude(p);
|
||||
}
|
||||
});
|
||||
// For why we do this mapping: https://issues.apache.org/jira/browse/CB-8390
|
||||
const SYSTEM_LIBRARY_MAPPINGS = [
|
||||
var SYSTEM_LIBRARY_MAPPINGS = [
|
||||
[/^\/?extras\/android\/support\/(.*)$/, 'com.android.support:support-$1:+'],
|
||||
[/^\/?google\/google_play_services\/libproject\/google-play-services_lib\/?$/, 'com.google.android.gms:play-services:+']
|
||||
];
|
||||
|
||||
propertiesObj.bomPlatforms.forEach(function (p) {
|
||||
if (!/:.*:/.exec(p)) {
|
||||
throw new CordovaError('Malformed BoM platform: ' + p);
|
||||
}
|
||||
|
||||
// Add bom platform
|
||||
depsList += ' implementation platform("' + p + '")\n';
|
||||
});
|
||||
|
||||
propertiesObj.systemLibs.forEach(function (p) {
|
||||
let mavenRef;
|
||||
var mavenRef;
|
||||
// It's already in gradle form if it has two ':'s
|
||||
if (/:.*:/.exec(p)) {
|
||||
mavenRef = p;
|
||||
} else if (/:.*/.exec(p)) {
|
||||
// Support BoM imports
|
||||
mavenRef = p;
|
||||
events.emit('warn', 'Library expects a BoM package: ' + p);
|
||||
} else {
|
||||
for (let i = 0; i < SYSTEM_LIBRARY_MAPPINGS.length; ++i) {
|
||||
const pair = SYSTEM_LIBRARY_MAPPINGS[i];
|
||||
for (var i = 0; i < SYSTEM_LIBRARY_MAPPINGS.length; ++i) {
|
||||
var pair = SYSTEM_LIBRARY_MAPPINGS[i];
|
||||
if (pair[0].exec(p)) {
|
||||
mavenRef = p.replace(pair[0], pair[1]);
|
||||
break;
|
||||
@@ -272,7 +247,7 @@ class ProjectBuilder {
|
||||
});
|
||||
|
||||
buildGradle = buildGradle.replace(/(SUB-PROJECT DEPENDENCIES START)[\s\S]*(\/\/ SUB-PROJECT DEPENDENCIES END)/, '$1\n' + depsList + ' $2');
|
||||
let includeList = '';
|
||||
var includeList = '';
|
||||
|
||||
propertiesObj.gradleIncludes.forEach(function (includePath) {
|
||||
includeList += 'apply from: "../' + includePath + '"\n';
|
||||
@@ -283,15 +258,23 @@ class ProjectBuilder {
|
||||
}
|
||||
|
||||
prepEnv (opts) {
|
||||
const self = this;
|
||||
const config = this._getCordovaConfig();
|
||||
var self = this;
|
||||
return check_reqs.check_gradle()
|
||||
.then(function () {
|
||||
events.emit('verbose', `Using Gradle: ${config.GRADLE_VERSION}`);
|
||||
return self.installGradleWrapper(config.GRADLE_VERSION);
|
||||
.then(function (gradlePath) {
|
||||
return self.runGradleWrapper(gradlePath);
|
||||
}).then(function () {
|
||||
return self.prepBuildFiles();
|
||||
}).then(() => {
|
||||
// update/set the distributionUrl in the gradle-wrapper.properties
|
||||
const gradleWrapperPropertiesPath = path.join(self.root, 'gradle/wrapper/gradle-wrapper.properties');
|
||||
const gradleWrapperProperties = createEditor(gradleWrapperPropertiesPath);
|
||||
const distributionUrl = process.env.CORDOVA_ANDROID_GRADLE_DISTRIBUTION_URL || 'https://services.gradle.org/distributions/gradle-6.5-all.zip';
|
||||
gradleWrapperProperties.set('distributionUrl', distributionUrl);
|
||||
gradleWrapperProperties.save();
|
||||
|
||||
events.emit('verbose', `Gradle Distribution URL: ${distributionUrl}`);
|
||||
})
|
||||
.then(() => {
|
||||
const signingPropertiesPath = path.join(self.root, `${opts.buildType}${SIGNING_PROPERTIES}`);
|
||||
|
||||
if (fs.existsSync(signingPropertiesPath)) fs.removeSync(signingPropertiesPath);
|
||||
@@ -304,41 +287,29 @@ class ProjectBuilder {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @returns The user defined configs
|
||||
*/
|
||||
_getCordovaConfig () {
|
||||
return fs.readJSONSync(path.join(this.root, 'cdv-gradle-config.json'));
|
||||
}
|
||||
|
||||
/*
|
||||
* Builds the project with gradle.
|
||||
* Returns a promise.
|
||||
*/
|
||||
async build (opts) {
|
||||
const wrapper = this.getGradleWrapperPath();
|
||||
const args = this.getArgs(opts.buildType === 'debug' ? 'debug' : 'release', opts);
|
||||
build (opts) {
|
||||
var wrapper = path.join(this.root, 'gradlew');
|
||||
var args = this.getArgs(opts.buildType === 'debug' ? 'debug' : 'release', opts);
|
||||
|
||||
events.emit('verbose', `Running Gradle Build: ${wrapper} ${args.join(' ')}`);
|
||||
|
||||
try {
|
||||
return await execa(wrapper, args, { stdio: 'inherit', cwd: path.resolve(this.root) });
|
||||
} catch (error) {
|
||||
if (error.toString().includes('failed to find target with hash string')) {
|
||||
// Add hint from check_android_target to error message
|
||||
try {
|
||||
await check_reqs.check_android_target(this.root);
|
||||
} catch (checkAndroidTargetError) {
|
||||
error.message += '\n' + checkAndroidTargetError.message;
|
||||
return execa(wrapper, args, { stdio: 'inherit', cwd: path.resolve(this.root) })
|
||||
.catch(function (error) {
|
||||
if (error.toString().indexOf('failed to find target with hash string') >= 0) {
|
||||
return check_reqs.check_android_target(error).then(function () {
|
||||
// If due to some odd reason - check_android_target succeeds
|
||||
// we should still fail here.
|
||||
throw error;
|
||||
});
|
||||
}
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
throw error;
|
||||
});
|
||||
}
|
||||
|
||||
clean (opts) {
|
||||
const wrapper = this.getGradleWrapperPath();
|
||||
const wrapper = path.join(this.root, 'gradlew');
|
||||
const args = this.getArgs('clean', opts);
|
||||
return execa(wrapper, args, { stdio: 'inherit', cwd: path.resolve(this.root) })
|
||||
.then(() => {
|
||||
@@ -18,104 +18,76 @@
|
||||
*/
|
||||
|
||||
const execa = require('execa');
|
||||
const path = require('path');
|
||||
const fs = require('fs-extra');
|
||||
var path = require('path');
|
||||
var fs = require('fs-extra');
|
||||
const { forgivingWhichSync, isWindows, isDarwin } = require('./utils');
|
||||
const java = require('./env/java');
|
||||
var REPO_ROOT = path.join(__dirname, '..', '..', '..', '..');
|
||||
var PROJECT_ROOT = path.join(__dirname, '..', '..');
|
||||
const { CordovaError, ConfigParser, events } = require('cordova-common');
|
||||
const android_sdk = require('./android_sdk');
|
||||
const { SDK_VERSION } = require('./gradle-config-defaults');
|
||||
var android_sdk = require('./android_sdk');
|
||||
const { createEditor } = require('properties-parser');
|
||||
const semver = require('semver');
|
||||
|
||||
const EXPECTED_JAVA_VERSION = '1.8.x';
|
||||
|
||||
// Re-exporting these for backwards compatibility and for unit testing.
|
||||
// TODO: Remove uses and use the ./utils module directly.
|
||||
Object.assign(module.exports, { isWindows, isDarwin });
|
||||
|
||||
/**
|
||||
* @param {string} projectRoot
|
||||
* @description Get valid target from framework/project.properties if run from this repo
|
||||
* Otherwise get target from project.properties file within a generated cordova-android project
|
||||
* @returns {string} The android target in format "android-${target}"
|
||||
*/
|
||||
module.exports.get_target = function (projectRoot) {
|
||||
const userTargetSdkVersion = getUserTargetSdkVersion(projectRoot);
|
||||
module.exports.get_target = function () {
|
||||
const projectPropertiesPaths = [
|
||||
path.join(REPO_ROOT, 'framework', 'project.properties'),
|
||||
path.join(PROJECT_ROOT, 'project.properties')
|
||||
];
|
||||
|
||||
if (userTargetSdkVersion && userTargetSdkVersion < SDK_VERSION) {
|
||||
events.emit('warn', `android-targetSdkVersion should be greater than or equal to ${SDK_VERSION}.`);
|
||||
// Get the minimum required target API from the framework.
|
||||
let target = projectPropertiesPaths.filter(filePath => fs.existsSync(filePath))
|
||||
.map(filePath => createEditor(filePath).get('target'))
|
||||
.pop();
|
||||
|
||||
if (!target) {
|
||||
throw new Error(`We could not locate the target from the "project.properties" at either "${projectPropertiesPaths.join('", "')}".`);
|
||||
}
|
||||
|
||||
return `android-${Math.max(userTargetSdkVersion, SDK_VERSION)}`;
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {string} projectRoot
|
||||
* @returns {string} The android target in format "android-${target}"
|
||||
*/
|
||||
module.exports.get_compile = function (projectRoot) {
|
||||
const userTargetSdkVersion = getUserTargetSdkVersion(projectRoot) || SDK_VERSION;
|
||||
const userCompileSdkVersion = getUserCompileSdkVersion(projectRoot) || userTargetSdkVersion;
|
||||
|
||||
module.exports.isCompileSdkValid(userCompileSdkVersion, userTargetSdkVersion);
|
||||
|
||||
return userCompileSdkVersion;
|
||||
};
|
||||
|
||||
module.exports.isCompileSdkValid = (compileSdk, targetSdk) => {
|
||||
targetSdk = (targetSdk || SDK_VERSION);
|
||||
compileSdk = (compileSdk || targetSdk);
|
||||
const isValid = compileSdk >= targetSdk;
|
||||
|
||||
if (!isValid) {
|
||||
events.emit('warn', `The "android-compileSdkVersion" (${compileSdk}) should be greater than or equal to the "android-targetSdkVersion" (${targetSdk}).`);
|
||||
}
|
||||
|
||||
return isValid;
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {string} projectRoot
|
||||
* @returns {number} target sdk or 0 if undefined
|
||||
*/
|
||||
function getUserTargetSdkVersion (projectRoot) {
|
||||
// If the repo config.xml file exists, find the desired targetSdkVersion.
|
||||
// We need to use the cordova project's config.xml here, since the platform
|
||||
// project's config.xml does not yet have the user's preferences when this
|
||||
// function is called during `Api.createPlatform`.
|
||||
const configFile = path.join(projectRoot, '../../config.xml');
|
||||
if (!fs.existsSync(configFile)) return 0;
|
||||
const configFile = path.join(REPO_ROOT, 'config.xml');
|
||||
if (!fs.existsSync(configFile)) return target;
|
||||
|
||||
const configParser = new ConfigParser(configFile);
|
||||
const targetSdkVersion = parseInt(configParser.getPreference('android-targetSdkVersion', 'android'), 10);
|
||||
return isNaN(targetSdkVersion) ? 0 : targetSdkVersion;
|
||||
}
|
||||
const desiredAPI = parseInt(configParser.getPreference('android-targetSdkVersion', 'android'), 10);
|
||||
|
||||
/**
|
||||
* @param {string} projectRoot
|
||||
* @returns {number} target sdk or 0 if undefined
|
||||
*/
|
||||
function getUserCompileSdkVersion (projectRoot) {
|
||||
// If the repo config.xml file exists, find the desired compileSdkVersion.
|
||||
// We need to use the cordova project's config.xml here, since the platform
|
||||
// project's config.xml does not yet have the user's preferences when this
|
||||
// function is called during `Api.createPlatform`.
|
||||
const configFile = path.join(projectRoot, '../../config.xml');
|
||||
if (!fs.existsSync(configFile)) return 0;
|
||||
if (!isNaN(desiredAPI)) {
|
||||
const minimumAPI = parseInt(target.split('-').pop(), 10);
|
||||
|
||||
const configParser = new ConfigParser(configFile);
|
||||
const compileSdkVersion = parseInt(configParser.getPreference('android-compileSdkVersion', 'android'), 10);
|
||||
return isNaN(compileSdkVersion) ? 0 : compileSdkVersion;
|
||||
}
|
||||
if (desiredAPI >= minimumAPI) {
|
||||
target = `android-${desiredAPI}`;
|
||||
} else {
|
||||
events.emit('warn', `android-targetSdkVersion should be greater than or equal to ${minimumAPI}.`);
|
||||
}
|
||||
}
|
||||
|
||||
return target;
|
||||
};
|
||||
|
||||
module.exports.get_gradle_wrapper = function () {
|
||||
let androidStudioPath;
|
||||
let i = 0;
|
||||
let foundStudio = false;
|
||||
let program_dir;
|
||||
var androidStudioPath;
|
||||
var i = 0;
|
||||
var foundStudio = false;
|
||||
var program_dir;
|
||||
// OK, This hack only works on Windows, not on Mac OS or Linux. We will be deleting this eventually!
|
||||
if (module.exports.isWindows()) {
|
||||
const result = execa.sync(path.join(__dirname, 'getASPath.bat'));
|
||||
var result = execa.sync(path.join(__dirname, 'getASPath.bat'));
|
||||
// console.log('result.stdout =' + result.stdout.toString());
|
||||
// console.log('result.stderr =' + result.stderr.toString());
|
||||
|
||||
if (result.stderr.toString().length > 0) {
|
||||
const androidPath = path.join(process.env.ProgramFiles, 'Android') + '/';
|
||||
var androidPath = path.join(process.env.ProgramFiles, 'Android') + '/';
|
||||
if (fs.existsSync(androidPath)) {
|
||||
program_dir = fs.readdirSync(androidPath);
|
||||
while (i < program_dir.length && !foundStudio) {
|
||||
@@ -134,7 +106,7 @@ module.exports.get_gradle_wrapper = function () {
|
||||
}
|
||||
|
||||
if (androidStudioPath !== null && fs.existsSync(androidStudioPath)) {
|
||||
const dirs = fs.readdirSync(androidStudioPath);
|
||||
var dirs = fs.readdirSync(androidStudioPath);
|
||||
if (dirs[0].split('-')[0] === 'gradle') {
|
||||
return path.join(androidStudioPath, dirs[0], 'bin', 'gradle');
|
||||
}
|
||||
@@ -146,13 +118,13 @@ module.exports.get_gradle_wrapper = function () {
|
||||
|
||||
// Returns a promise. Called only by build and clean commands.
|
||||
module.exports.check_gradle = function () {
|
||||
const sdkDir = process.env.ANDROID_HOME || process.env.ANDROID_SDK_ROOT;
|
||||
var sdkDir = process.env.ANDROID_SDK_ROOT || process.env.ANDROID_HOME;
|
||||
if (!sdkDir) {
|
||||
return Promise.reject(new CordovaError('Could not find gradle wrapper within Android SDK. Could not find Android SDK directory.\n' +
|
||||
'Might need to install Android SDK or set up \'ANDROID_HOME\' env variable.'));
|
||||
'Might need to install Android SDK or set up \'ANDROID_SDK_ROOT\' env variable.'));
|
||||
}
|
||||
|
||||
const gradlePath = module.exports.get_gradle_wrapper();
|
||||
var gradlePath = module.exports.get_gradle_wrapper();
|
||||
|
||||
if (gradlePath.length !== 0) return Promise.resolve(gradlePath);
|
||||
|
||||
@@ -168,31 +140,39 @@ module.exports.check_gradle = function () {
|
||||
*/
|
||||
module.exports.check_java = async function () {
|
||||
const javaVersion = await java.getVersion();
|
||||
|
||||
if (!semver.satisfies(javaVersion.version, EXPECTED_JAVA_VERSION)) {
|
||||
throw new CordovaError(
|
||||
`Requirements check failed for JDK ${EXPECTED_JAVA_VERSION}! Detected version: ${javaVersion.version}\n` +
|
||||
'Check your ANDROID_SDK_ROOT / JAVA_HOME / PATH environment variables.'
|
||||
);
|
||||
}
|
||||
|
||||
return javaVersion;
|
||||
};
|
||||
|
||||
// Returns a promise.
|
||||
module.exports.check_android = function () {
|
||||
return Promise.resolve().then(function () {
|
||||
let hasAndroidHome = false;
|
||||
|
||||
function maybeSetAndroidHome (value) {
|
||||
if (!hasAndroidHome && fs.existsSync(value)) {
|
||||
hasAndroidHome = true;
|
||||
process.env.ANDROID_HOME = value;
|
||||
process.env.ANDROID_SDK_ROOT = value;
|
||||
}
|
||||
}
|
||||
|
||||
const adbInPath = forgivingWhichSync('adb');
|
||||
const avdmanagerInPath = forgivingWhichSync('avdmanager');
|
||||
var androidCmdPath = forgivingWhichSync('android');
|
||||
var adbInPath = forgivingWhichSync('adb');
|
||||
var avdmanagerInPath = forgivingWhichSync('avdmanager');
|
||||
var hasAndroidHome = false;
|
||||
|
||||
if (process.env.ANDROID_HOME) {
|
||||
maybeSetAndroidHome(path.resolve(process.env.ANDROID_HOME));
|
||||
if (process.env.ANDROID_SDK_ROOT) {
|
||||
maybeSetAndroidHome(path.resolve(process.env.ANDROID_SDK_ROOT));
|
||||
}
|
||||
|
||||
// First ensure ANDROID_HOME is set
|
||||
// If we have no hints (nothing in PATH), try a few default locations
|
||||
if (!hasAndroidHome && !adbInPath && !avdmanagerInPath) {
|
||||
if (!hasAndroidHome && !androidCmdPath && !adbInPath && !avdmanagerInPath) {
|
||||
if (process.env.ANDROID_HOME) {
|
||||
// Fallback to deprecated `ANDROID_HOME` variable
|
||||
maybeSetAndroidHome(path.join(process.env.ANDROID_HOME));
|
||||
@@ -240,15 +220,26 @@ module.exports.check_android = function () {
|
||||
}
|
||||
|
||||
if (!hasAndroidHome) {
|
||||
// If we dont have ANDROID_HOME, but we do have some tools on the PATH, try to infer from the tooling PATH.
|
||||
let parentDir, grandParentDir;
|
||||
// If we dont have ANDROID_SDK_ROOT, but we do have some tools on the PATH, try to infer from the tooling PATH.
|
||||
var parentDir, grandParentDir;
|
||||
if (androidCmdPath) {
|
||||
parentDir = path.dirname(androidCmdPath);
|
||||
grandParentDir = path.dirname(parentDir);
|
||||
if (path.basename(parentDir) === 'tools' || fs.existsSync(path.join(grandParentDir, 'tools', 'android'))) {
|
||||
maybeSetAndroidHome(grandParentDir);
|
||||
} else {
|
||||
throw new CordovaError('Failed to find \'ANDROID_SDK_ROOT\' environment variable. Try setting it manually.\n' +
|
||||
'Detected \'android\' command at ' + parentDir + ' but no \'tools\' directory found near.\n' +
|
||||
'Try reinstall Android SDK or update your PATH to include valid path to SDK' + path.sep + 'tools directory.');
|
||||
}
|
||||
}
|
||||
if (adbInPath) {
|
||||
parentDir = path.dirname(adbInPath);
|
||||
grandParentDir = path.dirname(parentDir);
|
||||
if (path.basename(parentDir) === 'platform-tools') {
|
||||
maybeSetAndroidHome(grandParentDir);
|
||||
} else {
|
||||
throw new CordovaError('Failed to find \'ANDROID_HOME\' environment variable. Try setting it manually.\n' +
|
||||
throw new CordovaError('Failed to find \'ANDROID_SDK_ROOT\' environment variable. Try setting it manually.\n' +
|
||||
'Detected \'adb\' command at ' + parentDir + ' but no \'platform-tools\' directory found near.\n' +
|
||||
'Try reinstall Android SDK or update your PATH to include valid path to SDK' + path.sep + 'platform-tools directory.');
|
||||
}
|
||||
@@ -259,54 +250,79 @@ module.exports.check_android = function () {
|
||||
if (path.basename(parentDir) === 'bin' && path.basename(grandParentDir) === 'tools') {
|
||||
maybeSetAndroidHome(path.dirname(grandParentDir));
|
||||
} else {
|
||||
throw new CordovaError('Failed to find \'ANDROID_HOME\' environment variable. Try setting it manually.\n' +
|
||||
throw new CordovaError('Failed to find \'ANDROID_SDK_ROOT\' environment variable. Try setting it manually.\n' +
|
||||
'Detected \'avdmanager\' command at ' + parentDir + ' but no \'tools' + path.sep + 'bin\' directory found near.\n' +
|
||||
'Try reinstall Android SDK or update your PATH to include valid path to SDK' + path.sep + 'tools' + path.sep + 'bin directory.');
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!process.env.ANDROID_HOME) {
|
||||
throw new CordovaError('Failed to find \'ANDROID_HOME\' environment variable. Try setting it manually.\n' +
|
||||
if (!process.env.ANDROID_SDK_ROOT) {
|
||||
throw new CordovaError('Failed to find \'ANDROID_SDK_ROOT\' environment variable. Try setting it manually.\n' +
|
||||
'Failed to find \'android\' command in your \'PATH\'. Try update your \'PATH\' to include path to valid SDK directory.');
|
||||
}
|
||||
if (!fs.existsSync(process.env.ANDROID_HOME)) {
|
||||
throw new CordovaError('\'ANDROID_HOME\' environment variable is set to non-existent path: ' + process.env.ANDROID_HOME +
|
||||
if (!fs.existsSync(process.env.ANDROID_SDK_ROOT)) {
|
||||
throw new CordovaError('\'ANDROID_SDK_ROOT\' environment variable is set to non-existent path: ' + process.env.ANDROID_SDK_ROOT +
|
||||
'\nTry update it manually to point to valid SDK directory.');
|
||||
}
|
||||
// Next let's make sure relevant parts of the SDK tooling is in our PATH
|
||||
if (hasAndroidHome && !androidCmdPath) {
|
||||
process.env.PATH += path.delimiter + path.join(process.env.ANDROID_SDK_ROOT, 'tools');
|
||||
}
|
||||
if (hasAndroidHome && !adbInPath) {
|
||||
process.env.PATH += path.delimiter + path.join(process.env.ANDROID_HOME, 'platform-tools');
|
||||
process.env.PATH += path.delimiter + path.join(process.env.ANDROID_SDK_ROOT, 'platform-tools');
|
||||
}
|
||||
if (hasAndroidHome && !avdmanagerInPath) {
|
||||
process.env.PATH += path.delimiter + path.join(process.env.ANDROID_HOME, 'tools', 'bin');
|
||||
process.env.PATH += path.delimiter + path.join(process.env.ANDROID_SDK_ROOT, 'tools', 'bin');
|
||||
}
|
||||
return hasAndroidHome;
|
||||
});
|
||||
};
|
||||
|
||||
module.exports.check_android_target = function (projectRoot) {
|
||||
// TODO: is this actually needed?
|
||||
module.exports.getAbsoluteAndroidCmd = function () {
|
||||
var cmd = forgivingWhichSync('android');
|
||||
if (cmd.length === 0) {
|
||||
cmd = forgivingWhichSync('sdkmanager');
|
||||
}
|
||||
if (module.exports.isWindows()) {
|
||||
return '"' + cmd + '"';
|
||||
}
|
||||
return cmd.replace(/(\s)/g, '\\$1');
|
||||
};
|
||||
|
||||
module.exports.check_android_target = function (originalError) {
|
||||
// valid_target can look like:
|
||||
// android-19
|
||||
// android-L
|
||||
// Google Inc.:Google APIs:20
|
||||
// Google Inc.:Glass Development Kit Preview:20
|
||||
const desired_api_level = module.exports.get_target(projectRoot);
|
||||
var desired_api_level = module.exports.get_target();
|
||||
return android_sdk.list_targets().then(function (targets) {
|
||||
if (targets.indexOf(desired_api_level) >= 0) {
|
||||
return targets;
|
||||
}
|
||||
throw new CordovaError(`Please install the Android SDK Platform "platforms;${desired_api_level}"`);
|
||||
var androidCmd = module.exports.getAbsoluteAndroidCmd();
|
||||
var msg = 'Please install Android target / API level: "' + desired_api_level + '".\n\n' +
|
||||
'Hint: Open the SDK manager by running: ' + androidCmd + '\n' +
|
||||
'You will require:\n' +
|
||||
'1. "SDK Platform" for API level ' + desired_api_level + '\n' +
|
||||
'2. "Android SDK Platform-tools (latest)\n' +
|
||||
'3. "Android SDK Build-tools" (latest)';
|
||||
if (originalError) {
|
||||
msg = originalError + '\n' + msg;
|
||||
}
|
||||
throw new CordovaError(msg);
|
||||
});
|
||||
};
|
||||
|
||||
// Returns a promise.
|
||||
module.exports.run = function () {
|
||||
console.log('Checking Java JDK and Android SDK versions');
|
||||
console.log('ANDROID_HOME=' + process.env.ANDROID_HOME + ' (recommended setting)');
|
||||
console.log('ANDROID_SDK_ROOT=' + process.env.ANDROID_SDK_ROOT + ' (DEPRECATED)');
|
||||
console.log('ANDROID_SDK_ROOT=' + process.env.ANDROID_SDK_ROOT + ' (recommended setting)');
|
||||
console.log('ANDROID_HOME=' + process.env.ANDROID_HOME + ' (DEPRECATED)');
|
||||
|
||||
return Promise.all([this.check_java(), this.check_android()]).then(function (values) {
|
||||
console.log('Using Android SDK: ' + (process.env.ANDROID_HOME || process.env.ANDROID_SDK_ROOT));
|
||||
console.log('Using Android SDK: ' + process.env.ANDROID_SDK_ROOT);
|
||||
|
||||
if (!values[1]) {
|
||||
throw new CordovaError('Requirements check failed for Android SDK! Android SDK was not detected.');
|
||||
@@ -322,12 +338,12 @@ module.exports.run = function () {
|
||||
* (for example, check_android_target returns an array of android targets installed)
|
||||
* @param {Boolean} installed Indicates whether the requirement is installed or not
|
||||
*/
|
||||
const Requirement = function (id, name, version, installed) {
|
||||
var Requirement = function (id, name, version, installed) {
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
this.installed = installed || false;
|
||||
this.metadata = {
|
||||
version
|
||||
version: version
|
||||
};
|
||||
};
|
||||
|
||||
@@ -335,28 +351,27 @@ const Requirement = function (id, name, version, installed) {
|
||||
* Methods that runs all checks one by one and returns a result of checks
|
||||
* as an array of Requirement objects. This method intended to be used by cordova-lib check_reqs method
|
||||
*
|
||||
* @param {string} projectRoot
|
||||
* @return Promise<Requirement[]> Array of requirements. Due to implementation, promise is always fulfilled.
|
||||
*/
|
||||
module.exports.check_all = function (projectRoot) {
|
||||
const requirements = [
|
||||
module.exports.check_all = function () {
|
||||
var requirements = [
|
||||
new Requirement('java', 'Java JDK'),
|
||||
new Requirement('androidSdk', 'Android SDK'),
|
||||
new Requirement('androidTarget', 'Android target'),
|
||||
new Requirement('gradle', 'Gradle')
|
||||
];
|
||||
|
||||
const checkFns = [
|
||||
var checkFns = [
|
||||
this.check_java,
|
||||
this.check_android,
|
||||
this.check_android_target.bind(this, projectRoot),
|
||||
this.check_android_target,
|
||||
this.check_gradle
|
||||
];
|
||||
|
||||
// Then execute requirement checks one-by-one
|
||||
return checkFns.reduce(function (promise, checkFn, idx) {
|
||||
// Update each requirement with results
|
||||
const requirement = requirements[idx];
|
||||
var requirement = requirements[idx];
|
||||
return promise.then(checkFn).then(function (version) {
|
||||
requirement.installed = true;
|
||||
requirement.metadata.version = version;
|
||||
@@ -30,12 +30,15 @@ class GradlePropertiesParser {
|
||||
*/
|
||||
constructor (platformDir) {
|
||||
this._defaults = {
|
||||
// 10 seconds -> 6 seconds
|
||||
'org.gradle.daemon': 'true',
|
||||
|
||||
// to allow dex in process
|
||||
'org.gradle.jvmargs': '-Xmx2048m',
|
||||
|
||||
// Android X
|
||||
'android.useAndroidX': 'true',
|
||||
'android.enableJetifier': 'true'
|
||||
'android.useAndroidX': 'false',
|
||||
'android.enableJetifier': 'false'
|
||||
|
||||
// Shaves another 100ms, but produces a "try at own risk" warning. Not worth it (yet):
|
||||
// 'org.gradle.parallel': 'true'
|
||||
@@ -19,13 +19,14 @@
|
||||
|
||||
const execa = require('execa');
|
||||
const fs = require('fs-extra');
|
||||
const android_versions = require('android-versions');
|
||||
const path = require('path');
|
||||
const Adb = require('./Adb');
|
||||
const events = require('cordova-common').events;
|
||||
const CordovaError = require('cordova-common').CordovaError;
|
||||
const android_sdk = require('./android_sdk');
|
||||
const which = require('which');
|
||||
var android_versions = require('android-versions');
|
||||
var path = require('path');
|
||||
var Adb = require('./Adb');
|
||||
var events = require('cordova-common').events;
|
||||
var CordovaError = require('cordova-common').CordovaError;
|
||||
var android_sdk = require('./android_sdk');
|
||||
var check_reqs = require('./check_reqs');
|
||||
var which = require('which');
|
||||
|
||||
// constants
|
||||
const ONE_SECOND = 1000; // in milliseconds
|
||||
@@ -41,11 +42,11 @@ function forgivingWhichSync (cmd) {
|
||||
|
||||
module.exports.list_images_using_avdmanager = function () {
|
||||
return execa('avdmanager', ['list', 'avd']).then(({ stdout: output }) => {
|
||||
const response = output.split('\n');
|
||||
const emulator_list = [];
|
||||
for (let i = 1; i < response.length; i++) {
|
||||
var response = output.split('\n');
|
||||
var emulator_list = [];
|
||||
for (var i = 1; i < response.length; i++) {
|
||||
// To return more detailed information use img_obj
|
||||
const img_obj = {};
|
||||
var img_obj = {};
|
||||
if (response[i].match(/Name:\s/)) {
|
||||
img_obj.name = response[i].split('Name: ')[1].replace('\r', '');
|
||||
if (response[i + 1].match(/Device:\s/)) {
|
||||
@@ -74,9 +75,9 @@ module.exports.list_images_using_avdmanager = function () {
|
||||
img_obj.target = img_obj.target.substr(0, img_obj.target.indexOf('(') - 1).trim();
|
||||
}
|
||||
}
|
||||
const version_string = img_obj.target.replace(/Android\s+/, '');
|
||||
var version_string = img_obj.target.replace(/Android\s+/, '');
|
||||
|
||||
const api_level = android_sdk.version_string_to_api_level[version_string];
|
||||
var api_level = android_sdk.version_string_to_api_level[version_string];
|
||||
if (api_level) {
|
||||
img_obj.target += ' (API level ' + api_level + ')';
|
||||
}
|
||||
@@ -98,6 +99,48 @@ module.exports.list_images_using_avdmanager = function () {
|
||||
});
|
||||
};
|
||||
|
||||
module.exports.list_images_using_android = function () {
|
||||
return execa('android', ['list', 'avd']).then(({ stdout: output }) => {
|
||||
var response = output.split('\n');
|
||||
var emulator_list = [];
|
||||
for (var i = 1; i < response.length; i++) {
|
||||
// To return more detailed information use img_obj
|
||||
var img_obj = {};
|
||||
if (response[i].match(/Name:\s/)) {
|
||||
img_obj.name = response[i].split('Name: ')[1].replace('\r', '');
|
||||
if (response[i + 1].match(/Device:\s/)) {
|
||||
i++;
|
||||
img_obj.device = response[i].split('Device: ')[1].replace('\r', '');
|
||||
}
|
||||
if (response[i + 1].match(/Path:\s/)) {
|
||||
i++;
|
||||
img_obj.path = response[i].split('Path: ')[1].replace('\r', '');
|
||||
}
|
||||
if (response[i + 1].match(/\(API\slevel\s/) || (response[i + 2] && response[i + 2].match(/\(API\slevel\s/))) {
|
||||
i++;
|
||||
var secondLine = response[i + 1].match(/\(API\slevel\s/) ? response[i + 1] : '';
|
||||
img_obj.target = (response[i] + secondLine).split('Target: ')[1].replace('\r', '');
|
||||
}
|
||||
if (response[i + 1].match(/ABI:\s/)) {
|
||||
i++;
|
||||
img_obj.abi = response[i].split('ABI: ')[1].replace('\r', '');
|
||||
}
|
||||
if (response[i + 1].match(/Skin:\s/)) {
|
||||
i++;
|
||||
img_obj.skin = response[i].split('Skin: ')[1].replace('\r', '');
|
||||
}
|
||||
|
||||
emulator_list.push(img_obj);
|
||||
}
|
||||
/* To just return a list of names use this
|
||||
if (response[i].match(/Name:\s/)) {
|
||||
emulator_list.push(response[i].split('Name: ')[1].replace('\r', '');
|
||||
} */
|
||||
}
|
||||
return emulator_list;
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns a Promise for a list of emulator images in the form of objects
|
||||
* {
|
||||
@@ -113,16 +156,18 @@ module.exports.list_images = function () {
|
||||
return Promise.resolve().then(function () {
|
||||
if (forgivingWhichSync('avdmanager')) {
|
||||
return module.exports.list_images_using_avdmanager();
|
||||
} else if (forgivingWhichSync('android')) {
|
||||
return module.exports.list_images_using_android();
|
||||
} else {
|
||||
return Promise.reject(new CordovaError('Could not find `avdmanager` on your $PATH! Are you sure the Android SDK is installed and available?'));
|
||||
return Promise.reject(new CordovaError('Could not find either `android` or `avdmanager` on your $PATH! Are you sure the Android SDK is installed and available?'));
|
||||
}
|
||||
}).then(function (avds) {
|
||||
// In case we're missing the Android OS version string from the target description, add it.
|
||||
return avds.map(function (avd) {
|
||||
if (avd.target && avd.target.indexOf('Android API') > -1 && avd.target.indexOf('API level') < 0) {
|
||||
const api_level = avd.target.match(/\d+/);
|
||||
var api_level = avd.target.match(/\d+/);
|
||||
if (api_level) {
|
||||
const level = android_versions.get(api_level);
|
||||
var level = android_versions.get(api_level);
|
||||
if (level) {
|
||||
avd.target = 'Android ' + level.semver + ' (API level ' + api_level + ')';
|
||||
}
|
||||
@@ -134,23 +179,22 @@ module.exports.list_images = function () {
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the best image (if any) for given target.
|
||||
*
|
||||
* @param {Number} project_target Android targetSDK API level
|
||||
* @return {{name: string} | undefined} the closest avd to the given target
|
||||
* Will return the closest avd to the projects target
|
||||
* or undefined if no avds exist.
|
||||
* Returns a promise.
|
||||
*/
|
||||
module.exports.best_image = function (project_target) {
|
||||
module.exports.best_image = function () {
|
||||
return this.list_images().then(function (images) {
|
||||
// Just return undefined if there is no images
|
||||
if (images.length === 0) return;
|
||||
|
||||
let closest = 9999;
|
||||
let best = images[0];
|
||||
for (const i in images) {
|
||||
const target = images[i].target;
|
||||
var closest = 9999;
|
||||
var best = images[0];
|
||||
var project_target = parseInt(check_reqs.get_target().replace('android-', ''));
|
||||
for (var i in images) {
|
||||
var target = images[i].target;
|
||||
if (target && target.indexOf('API level') > -1) {
|
||||
const num = parseInt(target.split('(API level ')[1].replace(')', ''));
|
||||
var num = parseInt(target.split('(API level ')[1].replace(')', ''));
|
||||
if (num === project_target) {
|
||||
return images[i];
|
||||
} else if (project_target - num < closest && project_target > num) {
|
||||
@@ -173,10 +217,10 @@ exports.list_started = async () => {
|
||||
* Returns a promise.
|
||||
*/
|
||||
module.exports.get_available_port = function () {
|
||||
const self = this;
|
||||
var self = this;
|
||||
|
||||
return self.list_started().then(function (emulators) {
|
||||
for (let p = 5584; p >= 5554; p -= 2) {
|
||||
for (var p = 5584; p >= 5554; p -= 2) {
|
||||
if (emulators.indexOf('emulator-' + p) === -1) {
|
||||
events.emit('verbose', 'Found available port: ' + p);
|
||||
return p;
|
||||
@@ -189,24 +233,37 @@ module.exports.get_available_port = function () {
|
||||
/*
|
||||
* Starts an emulator with the given ID,
|
||||
* and returns the started ID of that emulator.
|
||||
* If no ID is given it will use the first image available,
|
||||
* if no image is available it will error out (maybe create one?).
|
||||
* If no boot timeout is given or the value is negative it will wait forever for
|
||||
* the emulator to boot
|
||||
*
|
||||
* Returns a promise.
|
||||
*/
|
||||
module.exports.start = function (emulatorId, boot_timeout) {
|
||||
const self = this;
|
||||
module.exports.start = function (emulator_ID, boot_timeout) {
|
||||
var self = this;
|
||||
|
||||
return Promise.resolve().then(function () {
|
||||
if (!emulatorId) {
|
||||
throw new CordovaError('No emulator ID given');
|
||||
}
|
||||
if (emulator_ID) return Promise.resolve(emulator_ID);
|
||||
|
||||
return self.best_image().then(function (best) {
|
||||
if (best && best.name) {
|
||||
events.emit('warn', 'No emulator specified, defaulting to ' + best.name);
|
||||
return best.name;
|
||||
}
|
||||
|
||||
var androidCmd = check_reqs.getAbsoluteAndroidCmd();
|
||||
return Promise.reject(new CordovaError('No emulator images (avds) found.\n' +
|
||||
'1. Download desired System Image by running: ' + androidCmd + ' sdk\n' +
|
||||
'2. Create an AVD by running: ' + androidCmd + ' avd\n' +
|
||||
'HINT: For a faster emulator, use an Intel System Image and install the HAXM device driver\n'));
|
||||
});
|
||||
}).then(function (emulatorId) {
|
||||
return self.get_available_port().then(function (port) {
|
||||
// Figure out the directory the emulator binary runs in, and set the cwd to that directory.
|
||||
// Workaround for https://code.google.com/p/android/issues/detail?id=235461
|
||||
const emulator_dir = path.dirname(which.sync('emulator'));
|
||||
const args = ['-avd', emulatorId, '-port', port];
|
||||
var emulator_dir = path.dirname(which.sync('emulator'));
|
||||
var args = ['-avd', emulatorId, '-port', port];
|
||||
// Don't wait for it to finish, since the emulator will probably keep running for a long time.
|
||||
execa('emulator', args, { stdio: 'inherit', detached: true, cwd: emulator_dir })
|
||||
.unref();
|
||||
@@ -241,9 +298,9 @@ module.exports.start = function (emulatorId, boot_timeout) {
|
||||
* Returns this emulator's ID in a promise.
|
||||
*/
|
||||
module.exports.wait_for_emulator = function (port) {
|
||||
const self = this;
|
||||
var self = this;
|
||||
return Promise.resolve().then(function () {
|
||||
const emulator_id = 'emulator-' + port;
|
||||
var emulator_id = 'emulator-' + port;
|
||||
return Adb.shell(emulator_id, 'getprop dev.bootcomplete').then(function (output) {
|
||||
if (output.indexOf('1') >= 0) {
|
||||
return emulator_id;
|
||||
@@ -271,7 +328,7 @@ module.exports.wait_for_emulator = function (port) {
|
||||
* time_remaining or passing a negative value will cause it to wait forever
|
||||
*/
|
||||
module.exports.wait_for_boot = function (emulator_id, time_remaining) {
|
||||
const self = this;
|
||||
var self = this;
|
||||
return Adb.shell(emulator_id, 'getprop sys.boot_completed').then(function (output) {
|
||||
if (output.match(/1/)) {
|
||||
return true;
|
||||
@@ -41,9 +41,9 @@ const java = {
|
||||
await java._ensure(process.env);
|
||||
|
||||
// Java <= 8 writes version info to stderr, Java >= 9 to stdout
|
||||
let javacOutput;
|
||||
let version = null;
|
||||
try {
|
||||
javacOutput = (await execa('javac', ['-version'], { all: true })).all;
|
||||
version = (await execa('javac', ['-version'], { all: true })).all;
|
||||
} catch (ex) {
|
||||
events.emit('verbose', ex.shortMessage);
|
||||
|
||||
@@ -58,11 +58,7 @@ const java = {
|
||||
throw new CordovaError(msg);
|
||||
}
|
||||
|
||||
// We have to filter the output, because javac prints _JAVA_OPTIONS
|
||||
// before printing the version which causes semver.coerce to fail to get
|
||||
// the correct version if those options contain any numbers.
|
||||
const match = /javac\s+([\d.]+)/i.exec(javacOutput);
|
||||
return semver.coerce(match && match[1]);
|
||||
return semver.coerce(version);
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -76,15 +72,14 @@ const java = {
|
||||
return;
|
||||
}
|
||||
|
||||
const javaHome = environment.CORDOVA_JAVA_HOME || environment.JAVA_HOME;
|
||||
if (javaHome) {
|
||||
// Ensure that CORDOVA_JAVA_HOME overrides
|
||||
environment.JAVA_HOME = javaHome;
|
||||
// Ensure that the JAVA_HOME bin path is before anything else
|
||||
// to cover cases where different Java versions is in the PATH
|
||||
environment.PATH = path.join(environment.JAVA_HOME, 'bin') + path.delimiter + environment.PATH;
|
||||
const javacPath = utils.forgivingWhichSync('javac');
|
||||
const hasJavaHome = !!environment.JAVA_HOME;
|
||||
if (hasJavaHome) {
|
||||
// Windows java installer doesn't add javac to PATH, nor set JAVA_HOME (ugh).
|
||||
if (!javacPath) {
|
||||
environment.PATH += path.delimiter + path.join(environment.JAVA_HOME, 'bin');
|
||||
}
|
||||
} else {
|
||||
const javacPath = utils.forgivingWhichSync('javac');
|
||||
if (javacPath) {
|
||||
// OS X has a command for finding JAVA_HOME.
|
||||
const find_java = '/usr/libexec/java_home';
|
||||
@@ -98,9 +93,8 @@ const java = {
|
||||
}
|
||||
} else {
|
||||
// See if we can derive it from javac's location.
|
||||
const maybeJavaHome = path.dirname(path.dirname(javacPath));
|
||||
if (fs.existsSync(path.join(maybeJavaHome, 'bin', 'java')) ||
|
||||
fs.existsSync(path.join(maybeJavaHome, 'bin', 'java.exe'))) {
|
||||
var maybeJavaHome = path.dirname(path.dirname(javacPath));
|
||||
if (fs.existsSync(path.join(maybeJavaHome, 'lib', 'tools.jar'))) {
|
||||
environment.JAVA_HOME = maybeJavaHome;
|
||||
} else {
|
||||
throw new CordovaError(default_java_error_msg);
|
||||
3
bin/templates/cordova/lib/getASPath.bat
Normal file
@@ -0,0 +1,3 @@
|
||||
@ECHO OFF
|
||||
for /f "tokens=2*" %%a in ('REG QUERY "HKEY_LOCAL_MACHINE\SOFTWARE\Android Studio" /v Path') do set "ASPath=%%~b"
|
||||
ECHO %ASPath%
|
||||
39
bin/templates/cordova/lib/install-device
Executable file
@@ -0,0 +1,39 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
/*
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
*/
|
||||
|
||||
const { resolve, install } = require('./target');
|
||||
|
||||
var args = process.argv;
|
||||
const targetSpec = { type: 'device' };
|
||||
|
||||
if (args.length > 2) {
|
||||
if (args[2].substring(0, 9) === '--target=') {
|
||||
targetSpec.id = args[2].substring(9, args[2].length);
|
||||
} else {
|
||||
console.error('ERROR : argument \'' + args[2] + '\' not recognized.');
|
||||
process.exit(2);
|
||||
}
|
||||
}
|
||||
|
||||
resolve(targetSpec).then(install).catch(err => {
|
||||
console.error('ERROR: ' + err);
|
||||
process.exit(2);
|
||||
});
|
||||
26
bin/templates/cordova/lib/install-device.bat
Normal file
@@ -0,0 +1,26 @@
|
||||
:: Licensed to the Apache Software Foundation (ASF) under one
|
||||
:: or more contributor license agreements. See the NOTICE file
|
||||
:: distributed with this work for additional information
|
||||
:: regarding copyright ownership. The ASF licenses this file
|
||||
:: to you under the Apache License, Version 2.0 (the
|
||||
:: "License"); you may not use this file except in compliance
|
||||
:: with the License. You may obtain a copy of the License at
|
||||
::
|
||||
:: http://www.apache.org/licenses/LICENSE-2.0
|
||||
::
|
||||
:: Unless required by applicable law or agreed to in writing,
|
||||
:: software distributed under the License is distributed on an
|
||||
:: "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
:: KIND, either express or implied. See the License for the
|
||||
:: specific language governing permissions and limitations
|
||||
:: under the License.
|
||||
|
||||
@ECHO OFF
|
||||
SET script_path="%~dp0install-device"
|
||||
IF EXIST %script_path% (
|
||||
node %script_path% %*
|
||||
) ELSE (
|
||||
ECHO.
|
||||
ECHO ERROR: Could not find 'install-device' script in 'cordova\lib' folder, aborting...>&2
|
||||
EXIT /B 1
|
||||
)
|
||||
39
bin/templates/cordova/lib/install-emulator
Executable file
@@ -0,0 +1,39 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
/*
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
*/
|
||||
|
||||
const { resolve, install } = require('./target');
|
||||
|
||||
var args = process.argv;
|
||||
const targetSpec = { type: 'emulator' };
|
||||
|
||||
if (args.length > 2) {
|
||||
if (args[2].substring(0, 9) === '--target=') {
|
||||
targetSpec.id = args[2].substring(9, args[2].length);
|
||||
} else {
|
||||
console.error('ERROR : argument \'' + args[2] + '\' not recognized.');
|
||||
process.exit(2);
|
||||
}
|
||||
}
|
||||
|
||||
resolve(targetSpec).then(install).catch(err => {
|
||||
console.error('ERROR: ' + err);
|
||||
process.exit(2);
|
||||
});
|
||||
26
bin/templates/cordova/lib/install-emulator.bat
Normal file
@@ -0,0 +1,26 @@
|
||||
:: Licensed to the Apache Software Foundation (ASF) under one
|
||||
:: or more contributor license agreements. See the NOTICE file
|
||||
:: distributed with this work for additional information
|
||||
:: regarding copyright ownership. The ASF licenses this file
|
||||
:: to you under the Apache License, Version 2.0 (the
|
||||
:: "License"); you may not use this file except in compliance
|
||||
:: with the License. You may obtain a copy of the License at
|
||||
::
|
||||
:: http://www.apache.org/licenses/LICENSE-2.0
|
||||
::
|
||||
:: Unless required by applicable law or agreed to in writing,
|
||||
:: software distributed under the License is distributed on an
|
||||
:: "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
:: KIND, either express or implied. See the License for the
|
||||
:: specific language governing permissions and limitations
|
||||
:: under the License.
|
||||
|
||||
@ECHO OFF
|
||||
SET script_path="%~dp0install-emulator"
|
||||
IF EXIST %script_path% (
|
||||
node %script_path% %*
|
||||
) ELSE (
|
||||
ECHO.
|
||||
ECHO ERROR: Could not find 'install-emulator' script in 'cordova\lib' folder, aborting...>&2
|
||||
EXIT /B 1
|
||||
)
|
||||
@@ -19,10 +19,10 @@
|
||||
under the License.
|
||||
*/
|
||||
|
||||
const { list } = require('cordova-android/lib/target');
|
||||
const { list } = require('./target');
|
||||
|
||||
// Usage support for when args are given
|
||||
require('cordova-android/lib/check_reqs').check_android().then(function () {
|
||||
require('./check_reqs').check_android().then(function () {
|
||||
list().then(targets => {
|
||||
const deviceIds = targets
|
||||
.filter(({ type }) => type === 'device')
|
||||
26
bin/templates/cordova/lib/list-devices.bat
Normal file
@@ -0,0 +1,26 @@
|
||||
:: Licensed to the Apache Software Foundation (ASF) under one
|
||||
:: or more contributor license agreements. See the NOTICE file
|
||||
:: distributed with this work for additional information
|
||||
:: regarding copyright ownership. The ASF licenses this file
|
||||
:: to you under the Apache License, Version 2.0 (the
|
||||
:: "License"); you may not use this file except in compliance
|
||||
:: with the License. You may obtain a copy of the License at
|
||||
::
|
||||
:: http://www.apache.org/licenses/LICENSE-2.0
|
||||
::
|
||||
:: Unless required by applicable law or agreed to in writing,
|
||||
:: software distributed under the License is distributed on an
|
||||
:: "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
:: KIND, either express or implied. See the License for the
|
||||
:: specific language governing permissions and limitations
|
||||
:: under the License.
|
||||
|
||||
@ECHO OFF
|
||||
SET script_path="%~dp0list-devices"
|
||||
IF EXIST %script_path% (
|
||||
node %script_path% %*
|
||||
) ELSE (
|
||||
ECHO.
|
||||
ECHO ERROR: Could not find 'list-devices' script in 'cordova\lib' folder, aborting...>&2
|
||||
EXIT /B 1
|
||||
)
|
||||
@@ -19,10 +19,10 @@
|
||||
under the License.
|
||||
*/
|
||||
|
||||
const emulators = require('cordova-android/lib/emulator');
|
||||
var emulators = require('./emulator');
|
||||
|
||||
// Usage support for when args are given
|
||||
require('cordova-android/lib/check_reqs').check_android().then(function () {
|
||||
require('./check_reqs').check_android().then(function () {
|
||||
emulators.list_images().then(function (emulator_list) {
|
||||
emulator_list && emulator_list.forEach(function (emu) {
|
||||
console.log(emu.name);
|
||||
26
bin/templates/cordova/lib/list-emulator-images.bat
Normal file
@@ -0,0 +1,26 @@
|
||||
:: Licensed to the Apache Software Foundation (ASF) under one
|
||||
:: or more contributor license agreements. See the NOTICE file
|
||||
:: distributed with this work for additional information
|
||||
:: regarding copyright ownership. The ASF licenses this file
|
||||
:: to you under the Apache License, Version 2.0 (the
|
||||
:: "License"); you may not use this file except in compliance
|
||||
:: with the License. You may obtain a copy of the License at
|
||||
::
|
||||
:: http://www.apache.org/licenses/LICENSE-2.0
|
||||
::
|
||||
:: Unless required by applicable law or agreed to in writing,
|
||||
:: software distributed under the License is distributed on an
|
||||
:: "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
:: KIND, either express or implied. See the License for the
|
||||
:: specific language governing permissions and limitations
|
||||
:: under the License.
|
||||
|
||||
@ECHO OFF
|
||||
SET script_path="%~dp0list-emulator-images"
|
||||
IF EXIST %script_path% (
|
||||
node %script_path% %*
|
||||
) ELSE (
|
||||
ECHO.
|
||||
ECHO ERROR: Could not find 'list-emulator-images' script in 'cordova\lib' folder, aborting...>&2
|
||||
EXIT /B 1
|
||||
)
|
||||
34
bin/templates/cordova/lib/list-started-emulators
Executable file
@@ -0,0 +1,34 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
/*
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
*/
|
||||
|
||||
var emulators = require('./emulator');
|
||||
|
||||
// Usage support for when args are given
|
||||
require('./check_reqs').check_android().then(function () {
|
||||
emulators.list_started().then(function (emulator_list) {
|
||||
emulator_list && emulator_list.forEach(function (emu) {
|
||||
console.log(emu);
|
||||
});
|
||||
}, function (err) {
|
||||
console.error('ERROR: ' + err);
|
||||
process.exit(2);
|
||||
});
|
||||
});
|
||||
26
bin/templates/cordova/lib/list-started-emulators.bat
Normal file
@@ -0,0 +1,26 @@
|
||||
:: Licensed to the Apache Software Foundation (ASF) under one
|
||||
:: or more contributor license agreements. See the NOTICE file
|
||||
:: distributed with this work for additional information
|
||||
:: regarding copyright ownership. The ASF licenses this file
|
||||
:: to you under the Apache License, Version 2.0 (the
|
||||
:: "License"); you may not use this file except in compliance
|
||||
:: with the License. You may obtain a copy of the License at
|
||||
::
|
||||
:: http://www.apache.org/licenses/LICENSE-2.0
|
||||
::
|
||||
:: Unless required by applicable law or agreed to in writing,
|
||||
:: software distributed under the License is distributed on an
|
||||
:: "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
:: KIND, either express or implied. See the License for the
|
||||
:: specific language governing permissions and limitations
|
||||
:: under the License.
|
||||
|
||||
@ECHO OFF
|
||||
SET script_path="%~dp0list-started-emulators"
|
||||
IF EXIST %script_path% (
|
||||
node %script_path% %*
|
||||
) ELSE (
|
||||
ECHO.
|
||||
ECHO ERROR: Could not find 'list-started-emulators' script in 'cordova\lib' folder, aborting...>&2
|
||||
EXIT /B 1
|
||||
)
|
||||
45
bin/templates/cordova/lib/log.js
vendored
Normal file
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
*/
|
||||
|
||||
var path = require('path');
|
||||
var os = require('os');
|
||||
var execa = require('execa');
|
||||
var ROOT = path.join(__dirname, '..', '..');
|
||||
|
||||
/*
|
||||
* Starts running logcat in the shell.
|
||||
* Returns a promise.
|
||||
*/
|
||||
module.exports.run = function () {
|
||||
var adb = execa('adb', ['logcat'], { cwd: os.tmpdir(), stderr: 'inherit' });
|
||||
|
||||
adb.stdout.on('data', function (data) {
|
||||
var lines = data ? data.toString().split('\n') : [];
|
||||
var out = lines.filter(function (x) { return x.indexOf('nativeGetEnabledTags') < 0; });
|
||||
console.log(out.join('\n'));
|
||||
});
|
||||
|
||||
return adb;
|
||||
};
|
||||
|
||||
module.exports.help = function () {
|
||||
console.log('Usage: ' + path.relative(process.cwd(), path.join(ROOT, 'cordova', 'log')));
|
||||
console.log('Gives the logcat output on the command line.');
|
||||
process.exit(0);
|
||||
};
|
||||
@@ -21,7 +21,7 @@
|
||||
buildscript {
|
||||
repositories {
|
||||
google()
|
||||
mavenCentral()
|
||||
jcenter()
|
||||
}
|
||||
|
||||
// Switch the Android Gradle plugin version requirement depending on the
|
||||
@@ -42,8 +42,8 @@ dependencies {
|
||||
}
|
||||
|
||||
android {
|
||||
compileSdkVersion cordovaConfig.COMPILE_SDK_VERSION
|
||||
buildToolsVersion cordovaConfig.BUILD_TOOLS_VERSION
|
||||
compileSdkVersion cdvCompileSdkVersion
|
||||
buildToolsVersion cdvBuildToolsVersion
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_1_6
|
||||
@@ -14,19 +14,19 @@
|
||||
*
|
||||
*/
|
||||
|
||||
const fs = require('fs-extra');
|
||||
const path = require('path');
|
||||
const isPathInside = require('is-path-inside');
|
||||
const events = require('cordova-common').events;
|
||||
const CordovaError = require('cordova-common').CordovaError;
|
||||
var fs = require('fs-extra');
|
||||
var path = require('path');
|
||||
var isPathInside = require('is-path-inside');
|
||||
var events = require('cordova-common').events;
|
||||
var CordovaError = require('cordova-common').CordovaError;
|
||||
|
||||
const handlers = {
|
||||
var handlers = {
|
||||
'source-file': {
|
||||
install: function (obj, plugin, project, options) {
|
||||
if (!obj.src) throw new CordovaError(generateAttributeError('src', 'source-file', plugin.id));
|
||||
if (!obj.targetDir) throw new CordovaError(generateAttributeError('target-dir', 'source-file', plugin.id));
|
||||
|
||||
const dest = getInstallDestination(obj);
|
||||
var dest = getInstallDestination(obj);
|
||||
|
||||
if (options && options.force) {
|
||||
copyFile(plugin.dir, obj.src, project.projectDir, dest, !!(options && options.link));
|
||||
@@ -35,7 +35,7 @@ const handlers = {
|
||||
}
|
||||
},
|
||||
uninstall: function (obj, plugin, project, options) {
|
||||
const dest = getInstallDestination(obj);
|
||||
var dest = getInstallDestination(obj);
|
||||
|
||||
// TODO: Add Koltin extension to uninstall, since they are handled like Java files
|
||||
if (obj.src.endsWith('java')) {
|
||||
@@ -48,35 +48,35 @@ const handlers = {
|
||||
},
|
||||
'lib-file': {
|
||||
install: function (obj, plugin, project, options) {
|
||||
const dest = path.join('app/libs', path.basename(obj.src));
|
||||
var dest = path.join('app/libs', path.basename(obj.src));
|
||||
copyFile(plugin.dir, obj.src, project.projectDir, dest, !!(options && options.link));
|
||||
},
|
||||
uninstall: function (obj, plugin, project, options) {
|
||||
const dest = path.join('app/libs', path.basename(obj.src));
|
||||
var dest = path.join('app/libs', path.basename(obj.src));
|
||||
removeFile(path.resolve(project.projectDir, dest));
|
||||
}
|
||||
},
|
||||
'resource-file': {
|
||||
install: function (obj, plugin, project, options) {
|
||||
const dest = path.join('app', 'src', 'main', obj.target);
|
||||
var dest = path.join('app', 'src', 'main', obj.target);
|
||||
copyFile(plugin.dir, obj.src, project.projectDir, dest, !!(options && options.link));
|
||||
},
|
||||
uninstall: function (obj, plugin, project, options) {
|
||||
const dest = path.join('app', 'src', 'main', obj.target);
|
||||
var dest = path.join('app', 'src', 'main', obj.target);
|
||||
removeFile(path.resolve(project.projectDir, dest));
|
||||
}
|
||||
},
|
||||
framework: {
|
||||
install: function (obj, plugin, project, options) {
|
||||
const src = obj.src;
|
||||
var src = obj.src;
|
||||
if (!src) throw new CordovaError(generateAttributeError('src', 'framework', plugin.id));
|
||||
|
||||
events.emit('verbose', 'Installing Android library: ' + src);
|
||||
const parentDir = obj.parent ? path.resolve(project.projectDir, obj.parent) : project.projectDir;
|
||||
let subDir;
|
||||
var parentDir = obj.parent ? path.resolve(project.projectDir, obj.parent) : project.projectDir;
|
||||
var subDir;
|
||||
|
||||
if (obj.custom) {
|
||||
const subRelativeDir = project.getCustomSubprojectRelativeDir(plugin.id, src);
|
||||
var subRelativeDir = project.getCustomSubprojectRelativeDir(plugin.id, src);
|
||||
copyNewFile(plugin.dir, src, project.projectDir, subRelativeDir, !!(options && options.link));
|
||||
subDir = path.resolve(project.projectDir, subRelativeDir);
|
||||
} else {
|
||||
@@ -93,19 +93,19 @@ const handlers = {
|
||||
}
|
||||
},
|
||||
uninstall: function (obj, plugin, project, options) {
|
||||
const src = obj.src;
|
||||
var src = obj.src;
|
||||
if (!src) throw new CordovaError(generateAttributeError('src', 'framework', plugin.id));
|
||||
|
||||
events.emit('verbose', 'Uninstalling Android library: ' + src);
|
||||
const parentDir = obj.parent ? path.resolve(project.projectDir, obj.parent) : project.projectDir;
|
||||
let subDir;
|
||||
var parentDir = obj.parent ? path.resolve(project.projectDir, obj.parent) : project.projectDir;
|
||||
var subDir;
|
||||
|
||||
if (obj.custom) {
|
||||
const subRelativeDir = project.getCustomSubprojectRelativeDir(plugin.id, src);
|
||||
var subRelativeDir = project.getCustomSubprojectRelativeDir(plugin.id, src);
|
||||
removeFile(path.resolve(project.projectDir, subRelativeDir));
|
||||
subDir = path.resolve(project.projectDir, subRelativeDir);
|
||||
// If it's the last framework in the plugin, remove the parent directory.
|
||||
const parDir = path.dirname(subDir);
|
||||
var parDir = path.dirname(subDir);
|
||||
if (fs.existsSync(parDir) && fs.readdirSync(parDir).length === 0) {
|
||||
fs.rmdirSync(parDir);
|
||||
}
|
||||
@@ -139,7 +139,7 @@ const handlers = {
|
||||
}
|
||||
},
|
||||
uninstall: function (obj, plugin, project, options) {
|
||||
const target = obj.target || obj.src;
|
||||
var target = obj.target || obj.src;
|
||||
|
||||
if (!target) throw new CordovaError(generateAttributeError('target', 'asset', plugin.id));
|
||||
|
||||
@@ -155,29 +155,29 @@ const handlers = {
|
||||
'js-module': {
|
||||
install: function (obj, plugin, project, options) {
|
||||
// Copy the plugin's files into the www directory.
|
||||
const moduleSource = path.resolve(plugin.dir, obj.src);
|
||||
const moduleName = plugin.id + '.' + (obj.name || path.basename(obj.src, path.extname(obj.src)));
|
||||
var moduleSource = path.resolve(plugin.dir, obj.src);
|
||||
var moduleName = plugin.id + '.' + (obj.name || path.basename(obj.src, path.extname(obj.src)));
|
||||
|
||||
// Read in the file, prepend the cordova.define, and write it back out.
|
||||
let scriptContent = fs.readFileSync(moduleSource, 'utf-8').replace(/^\ufeff/, ''); // Window BOM
|
||||
var scriptContent = fs.readFileSync(moduleSource, 'utf-8').replace(/^\ufeff/, ''); // Window BOM
|
||||
if (moduleSource.match(/.*\.json$/)) {
|
||||
scriptContent = 'module.exports = ' + scriptContent;
|
||||
}
|
||||
scriptContent = 'cordova.define("' + moduleName + '", function(require, exports, module) {\n' + scriptContent + '\n});\n';
|
||||
|
||||
const wwwDest = path.resolve(project.www, 'plugins', plugin.id, obj.src);
|
||||
var wwwDest = path.resolve(project.www, 'plugins', plugin.id, obj.src);
|
||||
fs.ensureDirSync(path.dirname(wwwDest));
|
||||
fs.writeFileSync(wwwDest, scriptContent, 'utf-8');
|
||||
|
||||
if (options && options.usePlatformWww) {
|
||||
// CB-11022 copy file to both directories if usePlatformWww is specified
|
||||
const platformWwwDest = path.resolve(project.platformWww, 'plugins', plugin.id, obj.src);
|
||||
var platformWwwDest = path.resolve(project.platformWww, 'plugins', plugin.id, obj.src);
|
||||
fs.ensureDirSync(path.dirname(platformWwwDest));
|
||||
fs.writeFileSync(platformWwwDest, scriptContent, 'utf-8');
|
||||
}
|
||||
},
|
||||
uninstall: function (obj, plugin, project, options) {
|
||||
const pluginRelativePath = path.join('plugins', plugin.id, obj.src);
|
||||
var pluginRelativePath = path.join('plugins', plugin.id, obj.src);
|
||||
removeFileAndParents(project.www, pluginRelativePath);
|
||||
if (options && options.usePlatformWww) {
|
||||
// CB-11022 remove file from both directories if usePlatformWww is specified
|
||||
@@ -208,8 +208,8 @@ function copyFile (plugin_dir, src, project_dir, dest, link) {
|
||||
if (!fs.existsSync(src)) throw new CordovaError('"' + src + '" not found!');
|
||||
|
||||
// check that src path is inside plugin directory
|
||||
const real_path = fs.realpathSync(src);
|
||||
const real_plugin_path = fs.realpathSync(plugin_dir);
|
||||
var real_path = fs.realpathSync(src);
|
||||
var real_plugin_path = fs.realpathSync(plugin_dir);
|
||||
if (!isPathInside(real_path, real_plugin_path)) { throw new CordovaError('File "' + src + '" is located outside the plugin directory "' + plugin_dir + '"'); }
|
||||
|
||||
dest = path.resolve(project_dir, dest);
|
||||
@@ -227,7 +227,7 @@ function copyFile (plugin_dir, src, project_dir, dest, link) {
|
||||
|
||||
// Same as copy file but throws error if target exists
|
||||
function copyNewFile (plugin_dir, src, project_dir, dest, link) {
|
||||
const target_path = path.resolve(project_dir, dest);
|
||||
var target_path = path.resolve(project_dir, dest);
|
||||
if (fs.existsSync(target_path)) { throw new CordovaError('"' + target_path + '" already exists!'); }
|
||||
|
||||
copyFile(plugin_dir, src, project_dir, dest, !!link);
|
||||
@@ -259,13 +259,13 @@ function deleteJava (project_dir, destFile) {
|
||||
|
||||
function removeFileAndParents (baseDir, destFile, stopper) {
|
||||
stopper = stopper || '.';
|
||||
const file = path.resolve(baseDir, destFile);
|
||||
var file = path.resolve(baseDir, destFile);
|
||||
if (!fs.existsSync(file)) return;
|
||||
|
||||
removeFile(file);
|
||||
|
||||
// check if directory is empty
|
||||
let curDir = path.dirname(file);
|
||||
var curDir = path.dirname(file);
|
||||
|
||||
while (curDir !== path.resolve(baseDir, stopper)) {
|
||||
if (fs.existsSync(curDir) && fs.readdirSync(curDir).length === 0) {
|
||||
@@ -283,16 +283,16 @@ function generateAttributeError (attribute, element, id) {
|
||||
}
|
||||
|
||||
function getInstallDestination (obj) {
|
||||
const APP_MAIN_PREFIX = 'app/src/main';
|
||||
const PATH_SEPARATOR = '/';
|
||||
var APP_MAIN_PREFIX = 'app/src/main';
|
||||
var PATH_SEPARATOR = '/';
|
||||
|
||||
const PATH_SEP_MATCH = '\\' + PATH_SEPARATOR;
|
||||
const PATH_SEP_OR_EOL_MATCH = '(\\' + PATH_SEPARATOR + '|$)';
|
||||
var PATH_SEP_MATCH = '\\' + PATH_SEPARATOR;
|
||||
var PATH_SEP_OR_EOL_MATCH = '(\\' + PATH_SEPARATOR + '|$)';
|
||||
|
||||
const appReg = new RegExp('^app' + PATH_SEP_OR_EOL_MATCH);
|
||||
const libsReg = new RegExp('^libs' + PATH_SEP_OR_EOL_MATCH);
|
||||
const srcReg = new RegExp('^src' + PATH_SEP_OR_EOL_MATCH);
|
||||
const srcMainReg = new RegExp('^src' + PATH_SEP_MATCH + 'main' + PATH_SEP_OR_EOL_MATCH);
|
||||
var appReg = new RegExp('^app' + PATH_SEP_OR_EOL_MATCH);
|
||||
var libsReg = new RegExp('^libs' + PATH_SEP_OR_EOL_MATCH);
|
||||
var srcReg = new RegExp('^src' + PATH_SEP_OR_EOL_MATCH);
|
||||
var srcMainReg = new RegExp('^src' + PATH_SEP_MATCH + 'main' + PATH_SEP_OR_EOL_MATCH);
|
||||
|
||||
if (appReg.test(obj.targetDir)) {
|
||||
// If any source file is using the new app directory structure,
|
||||
761
bin/templates/cordova/lib/prepare.js
vendored
Normal file
@@ -0,0 +1,761 @@
|
||||
/**
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
*/
|
||||
|
||||
var fs = require('fs-extra');
|
||||
var path = require('path');
|
||||
const nopt = require('nopt');
|
||||
const glob = require('fast-glob');
|
||||
var events = require('cordova-common').events;
|
||||
var AndroidManifest = require('./AndroidManifest');
|
||||
var checkReqs = require('./check_reqs');
|
||||
var xmlHelpers = require('cordova-common').xmlHelpers;
|
||||
var CordovaError = require('cordova-common').CordovaError;
|
||||
var ConfigParser = require('cordova-common').ConfigParser;
|
||||
var FileUpdater = require('cordova-common').FileUpdater;
|
||||
var PlatformJson = require('cordova-common').PlatformJson;
|
||||
var PlatformMunger = require('cordova-common').ConfigChanges.PlatformMunger;
|
||||
var PluginInfoProvider = require('cordova-common').PluginInfoProvider;
|
||||
const utils = require('./utils');
|
||||
|
||||
const GradlePropertiesParser = require('./config/GradlePropertiesParser');
|
||||
|
||||
function parseArguments (argv) {
|
||||
return nopt({
|
||||
// `jvmargs` is a valid option however, we don't actually want to parse it because we want the entire string as is.
|
||||
// jvmargs: String
|
||||
}, {}, argv || [], 0);
|
||||
}
|
||||
|
||||
module.exports.prepare = function (cordovaProject, options) {
|
||||
var self = this;
|
||||
|
||||
let args = {};
|
||||
if (options && options.options) {
|
||||
args = parseArguments(options.options.argv);
|
||||
}
|
||||
|
||||
var platformJson = PlatformJson.load(this.locations.root, this.platform);
|
||||
var munger = new PlatformMunger(this.platform, this.locations.root, platformJson, new PluginInfoProvider());
|
||||
|
||||
this._config = updateConfigFilesFrom(cordovaProject.projectConfig, munger, this.locations);
|
||||
|
||||
// Get the min SDK version from config.xml
|
||||
const minSdkVersion = this._config.getPreference('android-minSdkVersion', 'android');
|
||||
const maxSdkVersion = this._config.getPreference('android-maxSdkVersion', 'android');
|
||||
const targetSdkVersion = this._config.getPreference('android-targetSdkVersion', 'android');
|
||||
const androidXEnabled = this._config.getPreference('AndroidXEnabled', 'android');
|
||||
const isGradlePluginKotlinEnabled = this._config.getPreference('GradlePluginKotlinEnabled', 'android');
|
||||
const gradlePluginKotlinCodeStyle = this._config.getPreference('GradlePluginKotlinCodeStyle', 'android');
|
||||
|
||||
const gradlePropertiesUserConfig = {};
|
||||
if (minSdkVersion) gradlePropertiesUserConfig.cdvMinSdkVersion = minSdkVersion;
|
||||
if (maxSdkVersion) gradlePropertiesUserConfig.cdvMaxSdkVersion = maxSdkVersion;
|
||||
if (targetSdkVersion) gradlePropertiesUserConfig.cdvTargetSdkVersion = targetSdkVersion;
|
||||
if (args.jvmargs) gradlePropertiesUserConfig['org.gradle.jvmargs'] = args.jvmargs;
|
||||
if (isGradlePluginKotlinEnabled) {
|
||||
gradlePropertiesUserConfig['kotlin.code.style'] = gradlePluginKotlinCodeStyle || 'official';
|
||||
}
|
||||
|
||||
// Both 'useAndroidX' and 'enableJetifier' are linked together.
|
||||
if (androidXEnabled) {
|
||||
gradlePropertiesUserConfig['android.useAndroidX'] = androidXEnabled;
|
||||
gradlePropertiesUserConfig['android.enableJetifier'] = androidXEnabled;
|
||||
}
|
||||
|
||||
const gradlePropertiesParser = new GradlePropertiesParser(this.locations.root);
|
||||
gradlePropertiesParser.configure(gradlePropertiesUserConfig);
|
||||
|
||||
// Update own www dir with project's www assets and plugins' assets and js-files
|
||||
return Promise.resolve(updateWww(cordovaProject, this.locations)).then(function () {
|
||||
// update project according to config.xml changes.
|
||||
return updateProjectAccordingTo(self._config, self.locations);
|
||||
}).then(function () {
|
||||
updateIcons(cordovaProject, path.relative(cordovaProject.root, self.locations.res));
|
||||
updateSplashes(cordovaProject, path.relative(cordovaProject.root, self.locations.res));
|
||||
updateFileResources(cordovaProject, path.relative(cordovaProject.root, self.locations.root));
|
||||
}).then(function () {
|
||||
events.emit('verbose', 'Prepared android project successfully');
|
||||
});
|
||||
};
|
||||
|
||||
module.exports.clean = function (options) {
|
||||
// A cordovaProject isn't passed into the clean() function, because it might have
|
||||
// been called from the platform shell script rather than the CLI. Check for the
|
||||
// noPrepare option passed in by the non-CLI clean script. If that's present, or if
|
||||
// there's no config.xml found at the project root, then don't clean prepared files.
|
||||
var projectRoot = path.resolve(this.root, '../..');
|
||||
if ((options && options.noPrepare) || !fs.existsSync(this.locations.configXml) ||
|
||||
!fs.existsSync(this.locations.configXml)) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
var projectConfig = new ConfigParser(this.locations.configXml);
|
||||
|
||||
var self = this;
|
||||
return Promise.resolve().then(function () {
|
||||
cleanWww(projectRoot, self.locations);
|
||||
cleanIcons(projectRoot, projectConfig, path.relative(projectRoot, self.locations.res));
|
||||
cleanSplashes(projectRoot, projectConfig, path.relative(projectRoot, self.locations.res));
|
||||
cleanFileResources(projectRoot, projectConfig, path.relative(projectRoot, self.locations.root));
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Updates config files in project based on app's config.xml and config munge,
|
||||
* generated by plugins.
|
||||
*
|
||||
* @param {ConfigParser} sourceConfig A project's configuration that will
|
||||
* be merged into platform's config.xml
|
||||
* @param {ConfigChanges} configMunger An initialized ConfigChanges instance
|
||||
* for this platform.
|
||||
* @param {Object} locations A map of locations for this platform
|
||||
*
|
||||
* @return {ConfigParser} An instance of ConfigParser, that
|
||||
* represents current project's configuration. When returned, the
|
||||
* configuration is already dumped to appropriate config.xml file.
|
||||
*/
|
||||
function updateConfigFilesFrom (sourceConfig, configMunger, locations) {
|
||||
events.emit('verbose', 'Generating platform-specific config.xml from defaults for android at ' + locations.configXml);
|
||||
|
||||
// First cleanup current config and merge project's one into own
|
||||
// Overwrite platform config.xml with defaults.xml.
|
||||
fs.copySync(locations.defaultConfigXml, locations.configXml);
|
||||
|
||||
// Then apply config changes from global munge to all config files
|
||||
// in project (including project's config)
|
||||
configMunger.reapply_global_munge().save_all();
|
||||
|
||||
events.emit('verbose', 'Merging project\'s config.xml into platform-specific android config.xml');
|
||||
// Merge changes from app's config.xml into platform's one
|
||||
var config = new ConfigParser(locations.configXml);
|
||||
xmlHelpers.mergeXml(sourceConfig.doc.getroot(),
|
||||
config.doc.getroot(), 'android', /* clobber= */true);
|
||||
|
||||
config.write();
|
||||
return config;
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs all file operations via the verbose event stream, indented.
|
||||
*/
|
||||
function logFileOp (message) {
|
||||
events.emit('verbose', ' ' + message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates platform 'www' directory by replacing it with contents of
|
||||
* 'platform_www' and app www. Also copies project's overrides' folder into
|
||||
* the platform 'www' folder
|
||||
*
|
||||
* @param {Object} cordovaProject An object which describes cordova project.
|
||||
* @param {Object} destinations An object that contains destination
|
||||
* paths for www files.
|
||||
*/
|
||||
function updateWww (cordovaProject, destinations) {
|
||||
var sourceDirs = [
|
||||
path.relative(cordovaProject.root, cordovaProject.locations.www),
|
||||
path.relative(cordovaProject.root, destinations.platformWww)
|
||||
];
|
||||
|
||||
// If project contains 'merges' for our platform, use them as another overrides
|
||||
var merges_path = path.join(cordovaProject.root, 'merges', 'android');
|
||||
if (fs.existsSync(merges_path)) {
|
||||
events.emit('verbose', 'Found "merges/android" folder. Copying its contents into the android project.');
|
||||
sourceDirs.push(path.join('merges', 'android'));
|
||||
}
|
||||
|
||||
var targetDir = path.relative(cordovaProject.root, destinations.www);
|
||||
events.emit(
|
||||
'verbose', 'Merging and updating files from [' + sourceDirs.join(', ') + '] to ' + targetDir);
|
||||
FileUpdater.mergeAndUpdateDir(
|
||||
sourceDirs, targetDir, { rootDir: cordovaProject.root }, logFileOp);
|
||||
}
|
||||
|
||||
/**
|
||||
* Cleans all files from the platform 'www' directory.
|
||||
*/
|
||||
function cleanWww (projectRoot, locations) {
|
||||
var targetDir = path.relative(projectRoot, locations.www);
|
||||
events.emit('verbose', 'Cleaning ' + targetDir);
|
||||
|
||||
// No source paths are specified, so mergeAndUpdateDir() will clear the target directory.
|
||||
FileUpdater.mergeAndUpdateDir(
|
||||
[], targetDir, { rootDir: projectRoot, all: true }, logFileOp);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates project structure and AndroidManifest according to project's configuration.
|
||||
*
|
||||
* @param {ConfigParser} platformConfig A project's configuration that will
|
||||
* be used to update project
|
||||
* @param {Object} locations A map of locations for this platform
|
||||
*/
|
||||
function updateProjectAccordingTo (platformConfig, locations) {
|
||||
// Update app name by editing res/values/strings.xml
|
||||
var strings = xmlHelpers.parseElementtreeSync(locations.strings);
|
||||
|
||||
var name = platformConfig.name();
|
||||
strings.find('string[@name="app_name"]').text = name.replace(/'/g, '\\\'');
|
||||
|
||||
var shortName = platformConfig.shortName && platformConfig.shortName();
|
||||
if (shortName && shortName !== name) {
|
||||
strings.find('string[@name="launcher_name"]').text = shortName.replace(/'/g, '\\\'');
|
||||
}
|
||||
|
||||
fs.writeFileSync(locations.strings, strings.write({ indent: 4 }), 'utf-8');
|
||||
events.emit('verbose', 'Wrote out android application name "' + name + '" to ' + locations.strings);
|
||||
|
||||
// Java packages cannot support dashes
|
||||
var androidPkgName = (platformConfig.android_packageName() || platformConfig.packageName()).replace(/-/g, '_');
|
||||
|
||||
var manifest = new AndroidManifest(locations.manifest);
|
||||
var manifestId = manifest.getPackageId();
|
||||
|
||||
manifest.getActivity()
|
||||
.setOrientation(platformConfig.getPreference('orientation'))
|
||||
.setLaunchMode(findAndroidLaunchModePreference(platformConfig));
|
||||
|
||||
manifest.setVersionName(platformConfig.version())
|
||||
.setVersionCode(platformConfig.android_versionCode() || default_versionCode(platformConfig.version()))
|
||||
.setPackageId(androidPkgName)
|
||||
.write();
|
||||
|
||||
// Java file paths shouldn't be hard coded
|
||||
const javaDirectory = path.join(locations.javaSrc, manifestId.replace(/\./g, '/'));
|
||||
const java_files = glob.sync('**/*.java', { cwd: javaDirectory, absolute: true }).filter(f => {
|
||||
const contents = fs.readFileSync(f, 'utf-8');
|
||||
return /extends\s+CordovaActivity/.test(contents);
|
||||
});
|
||||
|
||||
if (java_files.length === 0) {
|
||||
throw new CordovaError('No Java files found that extend CordovaActivity.');
|
||||
} else if (java_files.length > 1) {
|
||||
events.emit('log', 'Multiple candidate Java files that extend CordovaActivity found. Guessing at the first one, ' + java_files[0]);
|
||||
}
|
||||
|
||||
const destFile = java_files[0];
|
||||
|
||||
// var destFile = path.join(locations.root, 'app', 'src', 'main', 'java', androidPkgName.replace(/\./g, '/'), path.basename(java_files[0]));
|
||||
// fs.ensureDirSync(path.dirname(destFile));
|
||||
// events.emit('verbose', java_files[0]);
|
||||
// events.emit('verbose', destFile);
|
||||
// console.log(locations);
|
||||
// fs.copySync(java_files[0], destFile);
|
||||
utils.replaceFileContents(destFile, /package [\w.]*;/, 'package ' + androidPkgName + ';');
|
||||
events.emit('verbose', 'Wrote out Android package name "' + androidPkgName + '" to ' + destFile);
|
||||
|
||||
var removeOrigPkg = checkReqs.isWindows() || checkReqs.isDarwin()
|
||||
? manifestId.toUpperCase() !== androidPkgName.toUpperCase()
|
||||
: manifestId !== androidPkgName;
|
||||
|
||||
if (removeOrigPkg) {
|
||||
// If package was name changed we need to remove old java with main activity
|
||||
fs.removeSync(java_files[0]);
|
||||
// remove any empty directories
|
||||
var currentDir = path.dirname(java_files[0]);
|
||||
var sourcesRoot = path.resolve(locations.root, 'src');
|
||||
while (currentDir !== sourcesRoot) {
|
||||
if (fs.existsSync(currentDir) && fs.readdirSync(currentDir).length === 0) {
|
||||
fs.rmdirSync(currentDir);
|
||||
currentDir = path.resolve(currentDir, '..');
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Consturct the default value for versionCode as
|
||||
// PATCH + MINOR * 100 + MAJOR * 10000
|
||||
// see http://developer.android.com/tools/publishing/versioning.html
|
||||
function default_versionCode (version) {
|
||||
var nums = version.split('-')[0].split('.');
|
||||
var versionCode = 0;
|
||||
if (+nums[0]) {
|
||||
versionCode += +nums[0] * 10000;
|
||||
}
|
||||
if (+nums[1]) {
|
||||
versionCode += +nums[1] * 100;
|
||||
}
|
||||
if (+nums[2]) {
|
||||
versionCode += +nums[2];
|
||||
}
|
||||
|
||||
events.emit('verbose', 'android-versionCode not found in config.xml. Generating a code based on version in config.xml (' + version + '): ' + versionCode);
|
||||
return versionCode;
|
||||
}
|
||||
|
||||
function getImageResourcePath (resourcesDir, type, density, name, sourceName) {
|
||||
// Use same extension as source with special case for 9-Patch files
|
||||
const ext = sourceName.endsWith('.9.png')
|
||||
? '.9.png' : path.extname(sourceName).toLowerCase();
|
||||
|
||||
const subDir = density ? `${type}-${density}` : type;
|
||||
return path.join(resourcesDir, subDir, name + ext);
|
||||
}
|
||||
|
||||
function getAdaptiveImageResourcePath (resourcesDir, type, density, name, sourceName) {
|
||||
if (/\.9\.png$/.test(sourceName)) {
|
||||
name = name.replace(/\.png$/, '.9.png');
|
||||
}
|
||||
var resourcePath = path.join(resourcesDir, (density ? type + '-' + density + '-v26' : type), name);
|
||||
return resourcePath;
|
||||
}
|
||||
|
||||
function makeSplashCleanupMap (projectRoot, resourcesDir) {
|
||||
// Build an initial resource map that deletes all existing splash screens
|
||||
const existingSplashPaths = glob.sync(
|
||||
`${resourcesDir.replace(/\\/g, '/')}/drawable-*/screen.{png,9.png,webp,jpg,jpeg}`,
|
||||
{ cwd: projectRoot }
|
||||
);
|
||||
return makeCleanResourceMap(existingSplashPaths);
|
||||
}
|
||||
|
||||
function updateSplashes (cordovaProject, platformResourcesDir) {
|
||||
var resources = cordovaProject.projectConfig.getSplashScreens('android');
|
||||
|
||||
// if there are "splash" elements in config.xml
|
||||
if (resources.length === 0) {
|
||||
events.emit('verbose', 'This app does not have splash screens defined');
|
||||
return;
|
||||
}
|
||||
|
||||
// Build an initial resource map that deletes all existing splash screens
|
||||
const resourceMap = makeSplashCleanupMap(cordovaProject.root, platformResourcesDir);
|
||||
|
||||
var hadMdpi = false;
|
||||
resources.forEach(function (resource) {
|
||||
if (!resource.density) {
|
||||
return;
|
||||
}
|
||||
if (resource.density === 'mdpi') {
|
||||
hadMdpi = true;
|
||||
}
|
||||
var targetPath = getImageResourcePath(
|
||||
platformResourcesDir, 'drawable', resource.density, 'screen', path.basename(resource.src));
|
||||
resourceMap[targetPath] = resource.src;
|
||||
});
|
||||
|
||||
// There's no "default" drawable, so assume default == mdpi.
|
||||
if (!hadMdpi && resources.defaultResource) {
|
||||
var targetPath = getImageResourcePath(
|
||||
platformResourcesDir, 'drawable', 'mdpi', 'screen', path.basename(resources.defaultResource.src));
|
||||
resourceMap[targetPath] = resources.defaultResource.src;
|
||||
}
|
||||
|
||||
events.emit('verbose', 'Updating splash screens at ' + platformResourcesDir);
|
||||
FileUpdater.updatePaths(
|
||||
resourceMap, { rootDir: cordovaProject.root }, logFileOp);
|
||||
}
|
||||
|
||||
function cleanSplashes (projectRoot, projectConfig, platformResourcesDir) {
|
||||
var resources = projectConfig.getSplashScreens('android');
|
||||
if (resources.length > 0) {
|
||||
const resourceMap = makeSplashCleanupMap(projectRoot, platformResourcesDir);
|
||||
|
||||
events.emit('verbose', 'Cleaning splash screens at ' + platformResourcesDir);
|
||||
|
||||
// No source paths are specified in the map, so updatePaths() will delete the target files.
|
||||
FileUpdater.updatePaths(
|
||||
resourceMap, { rootDir: projectRoot, all: true }, logFileOp);
|
||||
}
|
||||
}
|
||||
|
||||
function updateIcons (cordovaProject, platformResourcesDir) {
|
||||
const icons = cordovaProject.projectConfig.getIcons('android');
|
||||
|
||||
// Skip if there are no app defined icons in config.xml
|
||||
if (icons.length === 0) {
|
||||
events.emit('verbose', 'This app does not have launcher icons defined');
|
||||
return;
|
||||
}
|
||||
|
||||
// 1. loop icons determin if there is an error in the setup.
|
||||
// 2. during initial loop, also setup for legacy support.
|
||||
const errorMissingAttributes = [];
|
||||
const errorLegacyIconNeeded = [];
|
||||
let hasAdaptive = false;
|
||||
icons.forEach((icon, key) => {
|
||||
if (
|
||||
(icon.background && !icon.foreground) ||
|
||||
(!icon.background && icon.foreground) ||
|
||||
(!icon.background && !icon.foreground && !icon.src)
|
||||
) {
|
||||
errorMissingAttributes.push(icon.density ? icon.density : 'size=' + (icon.height || icon.width));
|
||||
}
|
||||
|
||||
if (icon.foreground) {
|
||||
hasAdaptive = true;
|
||||
|
||||
if (
|
||||
!icon.src &&
|
||||
(
|
||||
icon.foreground.startsWith('@color') ||
|
||||
path.extname(path.basename(icon.foreground)) === '.xml'
|
||||
)
|
||||
) {
|
||||
errorLegacyIconNeeded.push(icon.density ? icon.density : 'size=' + (icon.height || icon.width));
|
||||
} else if (!icon.src) {
|
||||
icons[key].src = icon.foreground;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const errorMessage = [];
|
||||
if (errorMissingAttributes.length > 0) {
|
||||
errorMessage.push('One of the following attributes are set but missing the other for the density type: ' + errorMissingAttributes.join(', ') + '. Please ensure that all require attributes are defined.');
|
||||
}
|
||||
|
||||
if (errorLegacyIconNeeded.length > 0) {
|
||||
errorMessage.push('For the following icons with the density of: ' + errorLegacyIconNeeded.join(', ') + ', adaptive foreground with a defined color or vector can not be used as a standard fallback icon for older Android devices. To support older Android environments, please provide a value for the src attribute.');
|
||||
}
|
||||
|
||||
if (errorMessage.length > 0) {
|
||||
throw new CordovaError(errorMessage.join(' '));
|
||||
}
|
||||
|
||||
let resourceMap = Object.assign(
|
||||
{},
|
||||
mapImageResources(cordovaProject.root, platformResourcesDir, 'mipmap', 'ic_launcher.png'),
|
||||
mapImageResources(cordovaProject.root, platformResourcesDir, 'mipmap', 'ic_launcher_foreground.png'),
|
||||
mapImageResources(cordovaProject.root, platformResourcesDir, 'mipmap', 'ic_launcher_background.png'),
|
||||
mapImageResources(cordovaProject.root, platformResourcesDir, 'mipmap', 'ic_launcher_foreground.xml'),
|
||||
mapImageResources(cordovaProject.root, platformResourcesDir, 'mipmap', 'ic_launcher_background.xml'),
|
||||
mapImageResources(cordovaProject.root, platformResourcesDir, 'mipmap', 'ic_launcher.xml')
|
||||
);
|
||||
|
||||
const preparedIcons = prepareIcons(icons);
|
||||
|
||||
if (hasAdaptive) {
|
||||
resourceMap = updateIconResourceForAdaptive(preparedIcons, resourceMap, platformResourcesDir);
|
||||
}
|
||||
|
||||
resourceMap = updateIconResourceForLegacy(preparedIcons, resourceMap, platformResourcesDir);
|
||||
|
||||
events.emit('verbose', 'Updating icons at ' + platformResourcesDir);
|
||||
FileUpdater.updatePaths(resourceMap, { rootDir: cordovaProject.root }, logFileOp);
|
||||
}
|
||||
|
||||
function updateIconResourceForAdaptive (preparedIcons, resourceMap, platformResourcesDir) {
|
||||
const android_icons = preparedIcons.android_icons;
|
||||
const default_icon = preparedIcons.default_icon;
|
||||
|
||||
// The source paths for icons and splashes are relative to
|
||||
// project's config.xml location, so we use it as base path.
|
||||
let background;
|
||||
let foreground;
|
||||
let targetPathBackground;
|
||||
let targetPathForeground;
|
||||
|
||||
for (const density in android_icons) {
|
||||
let backgroundVal = '@mipmap/ic_launcher_background';
|
||||
let foregroundVal = '@mipmap/ic_launcher_foreground';
|
||||
|
||||
background = android_icons[density].background;
|
||||
foreground = android_icons[density].foreground;
|
||||
|
||||
if (!background || !foreground) {
|
||||
// This icon isn't an adaptive icon, so skip it
|
||||
continue;
|
||||
}
|
||||
|
||||
if (background.startsWith('@color')) {
|
||||
// Colors Use Case
|
||||
backgroundVal = background; // Example: @color/background_foobar_1
|
||||
} else if (path.extname(path.basename(background)) === '.xml') {
|
||||
// Vector Use Case
|
||||
targetPathBackground = getAdaptiveImageResourcePath(platformResourcesDir, 'mipmap', density, 'ic_launcher_background.xml', path.basename(android_icons[density].background));
|
||||
resourceMap[targetPathBackground] = android_icons[density].background;
|
||||
} else if (path.extname(path.basename(background)) === '.png') {
|
||||
// Images Use Case
|
||||
targetPathBackground = getAdaptiveImageResourcePath(platformResourcesDir, 'mipmap', density, 'ic_launcher_background.png', path.basename(android_icons[density].background));
|
||||
resourceMap[targetPathBackground] = android_icons[density].background;
|
||||
}
|
||||
|
||||
if (foreground.startsWith('@color')) {
|
||||
// Colors Use Case
|
||||
foregroundVal = foreground;
|
||||
} else if (path.extname(path.basename(foreground)) === '.xml') {
|
||||
// Vector Use Case
|
||||
targetPathForeground = getAdaptiveImageResourcePath(platformResourcesDir, 'mipmap', density, 'ic_launcher_foreground.xml', path.basename(android_icons[density].foreground));
|
||||
resourceMap[targetPathForeground] = android_icons[density].foreground;
|
||||
} else if (path.extname(path.basename(foreground)) === '.png') {
|
||||
// Images Use Case
|
||||
targetPathForeground = getAdaptiveImageResourcePath(platformResourcesDir, 'mipmap', density, 'ic_launcher_foreground.png', path.basename(android_icons[density].foreground));
|
||||
resourceMap[targetPathForeground] = android_icons[density].foreground;
|
||||
}
|
||||
|
||||
// create an XML for DPI and set color
|
||||
const icLauncherTemplate = `<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="` + backgroundVal + `" />
|
||||
<foreground android:drawable="` + foregroundVal + `" />
|
||||
</adaptive-icon>`;
|
||||
|
||||
const launcherXmlPath = path.join(platformResourcesDir, 'mipmap-' + density + '-v26', 'ic_launcher.xml');
|
||||
|
||||
// Remove the XML from the resourceMap so the file does not get removed.
|
||||
delete resourceMap[launcherXmlPath];
|
||||
|
||||
fs.writeFileSync(path.resolve(launcherXmlPath), icLauncherTemplate);
|
||||
}
|
||||
|
||||
// There's no "default" drawable, so assume default == mdpi.
|
||||
if (default_icon && !android_icons.mdpi) {
|
||||
let defaultTargetPathBackground;
|
||||
let defaultTargetPathForeground;
|
||||
|
||||
if (background.startsWith('@color')) {
|
||||
// Colors Use Case
|
||||
targetPathBackground = default_icon.background;
|
||||
} else if (path.extname(path.basename(background)) === '.xml') {
|
||||
// Vector Use Case
|
||||
defaultTargetPathBackground = getAdaptiveImageResourcePath(platformResourcesDir, 'mipmap', 'mdpi', 'ic_launcher_background.xml', path.basename(default_icon.background));
|
||||
resourceMap[defaultTargetPathBackground] = default_icon.background;
|
||||
} else if (path.extname(path.basename(background)) === '.png') {
|
||||
// Images Use Case
|
||||
defaultTargetPathBackground = getAdaptiveImageResourcePath(platformResourcesDir, 'mipmap', 'mdpi', 'ic_launcher_background.png', path.basename(default_icon.background));
|
||||
resourceMap[defaultTargetPathBackground] = default_icon.background;
|
||||
}
|
||||
|
||||
if (foreground.startsWith('@color')) {
|
||||
// Colors Use Case
|
||||
targetPathForeground = default_icon.foreground;
|
||||
} else if (path.extname(path.basename(foreground)) === '.xml') {
|
||||
// Vector Use Case
|
||||
defaultTargetPathForeground = getAdaptiveImageResourcePath(platformResourcesDir, 'mipmap', 'mdpi', 'ic_launcher_foreground.xml', path.basename(default_icon.foreground));
|
||||
resourceMap[defaultTargetPathForeground] = default_icon.foreground;
|
||||
} else if (path.extname(path.basename(foreground)) === '.png') {
|
||||
// Images Use Case
|
||||
defaultTargetPathForeground = getAdaptiveImageResourcePath(platformResourcesDir, 'mipmap', 'mdpi', 'ic_launcher_foreground.png', path.basename(default_icon.foreground));
|
||||
resourceMap[defaultTargetPathForeground] = default_icon.foreground;
|
||||
}
|
||||
}
|
||||
|
||||
return resourceMap;
|
||||
}
|
||||
|
||||
function updateIconResourceForLegacy (preparedIcons, resourceMap, platformResourcesDir) {
|
||||
const android_icons = preparedIcons.android_icons;
|
||||
const default_icon = preparedIcons.default_icon;
|
||||
|
||||
// The source paths for icons and splashes are relative to
|
||||
// project's config.xml location, so we use it as base path.
|
||||
for (var density in android_icons) {
|
||||
var targetPath = getImageResourcePath(platformResourcesDir, 'mipmap', density, 'ic_launcher', path.basename(android_icons[density].src));
|
||||
resourceMap[targetPath] = android_icons[density].src;
|
||||
}
|
||||
|
||||
// There's no "default" drawable, so assume default == mdpi.
|
||||
if (default_icon && !android_icons.mdpi) {
|
||||
var defaultTargetPath = getImageResourcePath(platformResourcesDir, 'mipmap', 'mdpi', 'ic_launcher', path.basename(default_icon.src));
|
||||
resourceMap[defaultTargetPath] = default_icon.src;
|
||||
}
|
||||
|
||||
return resourceMap;
|
||||
}
|
||||
|
||||
function prepareIcons (icons) {
|
||||
// http://developer.android.com/design/style/iconography.html
|
||||
const SIZE_TO_DENSITY_MAP = {
|
||||
36: 'ldpi',
|
||||
48: 'mdpi',
|
||||
72: 'hdpi',
|
||||
96: 'xhdpi',
|
||||
144: 'xxhdpi',
|
||||
192: 'xxxhdpi'
|
||||
};
|
||||
|
||||
const android_icons = {};
|
||||
let default_icon;
|
||||
|
||||
// find the best matching icon for a given density or size
|
||||
// @output android_icons
|
||||
var parseIcon = function (icon, icon_size) {
|
||||
// do I have a platform icon for that density already
|
||||
var density = icon.density || SIZE_TO_DENSITY_MAP[icon_size];
|
||||
if (!density) {
|
||||
// invalid icon defition ( or unsupported size)
|
||||
return;
|
||||
}
|
||||
var previous = android_icons[density];
|
||||
if (previous && previous.platform) {
|
||||
return;
|
||||
}
|
||||
android_icons[density] = icon;
|
||||
};
|
||||
|
||||
// iterate over all icon elements to find the default icon and call parseIcon
|
||||
for (var i = 0; i < icons.length; i++) {
|
||||
var icon = icons[i];
|
||||
var size = icon.width;
|
||||
|
||||
if (!size) {
|
||||
size = icon.height;
|
||||
}
|
||||
|
||||
if (!size && !icon.density) {
|
||||
if (default_icon) {
|
||||
const found = {};
|
||||
const favor = {};
|
||||
|
||||
// populating found icon.
|
||||
if (icon.background && icon.foreground) {
|
||||
found.background = icon.background;
|
||||
found.foreground = icon.foreground;
|
||||
}
|
||||
if (icon.src) {
|
||||
found.src = icon.src;
|
||||
}
|
||||
|
||||
if (default_icon.background && default_icon.foreground) {
|
||||
favor.background = default_icon.background;
|
||||
favor.foreground = default_icon.foreground;
|
||||
}
|
||||
if (default_icon.src) {
|
||||
favor.src = default_icon.src;
|
||||
}
|
||||
|
||||
events.emit('verbose', 'Found extra default icon: ' + JSON.stringify(found) + ' and ignoring in favor of ' + JSON.stringify(favor) + '.');
|
||||
} else {
|
||||
default_icon = icon;
|
||||
}
|
||||
} else {
|
||||
parseIcon(icon, size);
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
android_icons: android_icons,
|
||||
default_icon: default_icon
|
||||
};
|
||||
}
|
||||
|
||||
function cleanIcons (projectRoot, projectConfig, platformResourcesDir) {
|
||||
var icons = projectConfig.getIcons('android');
|
||||
|
||||
// Skip if there are no app defined icons in config.xml
|
||||
if (icons.length === 0) {
|
||||
events.emit('verbose', 'This app does not have launcher icons defined');
|
||||
return;
|
||||
}
|
||||
|
||||
const resourceMap = Object.assign(
|
||||
{},
|
||||
mapImageResources(projectRoot, platformResourcesDir, 'mipmap', 'ic_launcher.png'),
|
||||
mapImageResources(projectRoot, platformResourcesDir, 'mipmap', 'ic_launcher_foreground.png'),
|
||||
mapImageResources(projectRoot, platformResourcesDir, 'mipmap', 'ic_launcher_background.png'),
|
||||
mapImageResources(projectRoot, platformResourcesDir, 'mipmap', 'ic_launcher_foreground.xml'),
|
||||
mapImageResources(projectRoot, platformResourcesDir, 'mipmap', 'ic_launcher_background.xml'),
|
||||
mapImageResources(projectRoot, platformResourcesDir, 'mipmap', 'ic_launcher.xml')
|
||||
);
|
||||
|
||||
events.emit('verbose', 'Cleaning icons at ' + platformResourcesDir);
|
||||
|
||||
// No source paths are specified in the map, so updatePaths() will delete the target files.
|
||||
FileUpdater.updatePaths(resourceMap, { rootDir: projectRoot, all: true }, logFileOp);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a map containing resources of a specified name from all drawable folders in a directory.
|
||||
*/
|
||||
function mapImageResources (rootDir, subDir, type, resourceName) {
|
||||
const pathMap = {};
|
||||
const globOptions = { cwd: path.join(rootDir, subDir), onlyDirectories: true };
|
||||
glob.sync(type + '-*', globOptions).forEach(drawableFolder => {
|
||||
const imagePath = path.join(subDir, drawableFolder, resourceName);
|
||||
pathMap[imagePath] = null;
|
||||
});
|
||||
return pathMap;
|
||||
}
|
||||
|
||||
/** Returns resource map that deletes all given paths */
|
||||
function makeCleanResourceMap (resourcePaths) {
|
||||
const pathMap = {};
|
||||
resourcePaths.map(path.normalize)
|
||||
.forEach(resourcePath => {
|
||||
pathMap[resourcePath] = null;
|
||||
});
|
||||
return pathMap;
|
||||
}
|
||||
|
||||
function updateFileResources (cordovaProject, platformDir) {
|
||||
var files = cordovaProject.projectConfig.getFileResources('android');
|
||||
|
||||
// if there are resource-file elements in config.xml
|
||||
if (files.length === 0) {
|
||||
events.emit('verbose', 'This app does not have additional resource files defined');
|
||||
return;
|
||||
}
|
||||
|
||||
var resourceMap = {};
|
||||
files.forEach(function (res) {
|
||||
var targetPath = path.join(platformDir, res.target);
|
||||
resourceMap[targetPath] = res.src;
|
||||
});
|
||||
|
||||
events.emit('verbose', 'Updating resource files at ' + platformDir);
|
||||
FileUpdater.updatePaths(
|
||||
resourceMap, { rootDir: cordovaProject.root }, logFileOp);
|
||||
}
|
||||
|
||||
function cleanFileResources (projectRoot, projectConfig, platformDir) {
|
||||
var files = projectConfig.getFileResources('android', true);
|
||||
if (files.length > 0) {
|
||||
events.emit('verbose', 'Cleaning resource files at ' + platformDir);
|
||||
|
||||
var resourceMap = {};
|
||||
files.forEach(function (res) {
|
||||
var filePath = path.join(platformDir, res.target);
|
||||
resourceMap[filePath] = null;
|
||||
});
|
||||
|
||||
FileUpdater.updatePaths(
|
||||
resourceMap, { rootDir: projectRoot, all: true }, logFileOp);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets and validates 'AndroidLaunchMode' prepference from config.xml. Returns
|
||||
* preference value and warns if it doesn't seems to be valid
|
||||
*
|
||||
* @param {ConfigParser} platformConfig A configParser instance for
|
||||
* platform.
|
||||
*
|
||||
* @return {String} Preference's value from config.xml or
|
||||
* default value, if there is no such preference. The default value is
|
||||
* 'singleTop'
|
||||
*/
|
||||
function findAndroidLaunchModePreference (platformConfig) {
|
||||
var launchMode = platformConfig.getPreference('AndroidLaunchMode');
|
||||
if (!launchMode) {
|
||||
// Return a default value
|
||||
return 'singleTop';
|
||||
}
|
||||
|
||||
var expectedValues = ['standard', 'singleTop', 'singleTask', 'singleInstance'];
|
||||
var valid = expectedValues.indexOf(launchMode) >= 0;
|
||||
if (!valid) {
|
||||
// Note: warn, but leave the launch mode as developer wanted, in case the list of options changes in the future
|
||||
events.emit('warn', 'Unrecognized value for AndroidLaunchMode preference: ' +
|
||||
launchMode + '. Expected values are: ' + expectedValues.join(', '));
|
||||
}
|
||||
|
||||
return launchMode;
|
||||
}
|
||||
@@ -19,7 +19,7 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
const events = require('cordova-common').events;
|
||||
var events = require('cordova-common').events;
|
||||
|
||||
/**
|
||||
* Retry a promise-returning function a number of times, propagating its
|
||||
99
bin/templates/cordova/lib/run.js
vendored
Normal file
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
*/
|
||||
|
||||
var path = require('path');
|
||||
var emulator = require('./emulator');
|
||||
const target = require('./target');
|
||||
var PackageType = require('./PackageType');
|
||||
const { events } = require('cordova-common');
|
||||
|
||||
/**
|
||||
* Builds a target spec from a runOptions object
|
||||
*
|
||||
* @param {{target?: string, device?: boolean, emulator?: boolean}} runOptions
|
||||
* @return {target.TargetSpec}
|
||||
*/
|
||||
function buildTargetSpec (runOptions) {
|
||||
const spec = {};
|
||||
if (runOptions.target) {
|
||||
spec.id = runOptions.target;
|
||||
} else if (runOptions.device) {
|
||||
spec.type = 'device';
|
||||
} else if (runOptions.emulator) {
|
||||
spec.type = 'emulator';
|
||||
}
|
||||
return spec;
|
||||
}
|
||||
|
||||
function formatResolvedTarget ({ id, type }) {
|
||||
return `${type} ${id}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs the application on a device if available. If no device is found, it will
|
||||
* use a started emulator. If no started emulators are found it will attempt
|
||||
* to start an avd. If no avds are found it will error out.
|
||||
*
|
||||
* @param {Object} runOptions various run/build options. See Api.js build/run
|
||||
* methods for reference.
|
||||
*
|
||||
* @return {Promise}
|
||||
*/
|
||||
module.exports.run = function (runOptions) {
|
||||
runOptions = runOptions || {};
|
||||
|
||||
var self = this;
|
||||
const spec = buildTargetSpec(runOptions);
|
||||
|
||||
return target.resolve(spec).then(function (resolvedTarget) {
|
||||
events.emit('log', `Deploying to ${formatResolvedTarget(resolvedTarget)}`);
|
||||
|
||||
return new Promise((resolve) => {
|
||||
const buildOptions = require('./build').parseBuildOptions(runOptions, null, self.root);
|
||||
|
||||
// Android app bundles cannot be deployed directly to the device
|
||||
if (buildOptions.packageType === PackageType.BUNDLE) {
|
||||
const packageTypeErrorMessage = 'Package type "bundle" is not supported during cordova run.';
|
||||
events.emit('error', packageTypeErrorMessage);
|
||||
throw packageTypeErrorMessage;
|
||||
}
|
||||
|
||||
resolve(self._builder.fetchBuildResults(buildOptions.buildType, buildOptions.arch));
|
||||
}).then(async function (buildResults) {
|
||||
if (resolvedTarget.type === 'emulator') {
|
||||
await emulator.wait_for_boot(resolvedTarget.id);
|
||||
}
|
||||
|
||||
return target.install(resolvedTarget, buildResults);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
module.exports.help = function () {
|
||||
console.log('Usage: ' + path.relative(process.cwd(), process.argv[1]) + ' [options]');
|
||||
console.log('Build options :');
|
||||
console.log(' --debug : Builds project in debug mode');
|
||||
console.log(' --release : Builds project in release mode');
|
||||
console.log(' --nobuild : Runs the currently built project without recompiling');
|
||||
console.log('Deploy options :');
|
||||
console.log(' --device : Will deploy the built project to a device');
|
||||
console.log(' --emulator : Will deploy the built project to an emulator if one exists');
|
||||
console.log(' --target=<target_id> : Installs to the target with the specified id.');
|
||||
process.exit(0);
|
||||
};
|
||||
38
bin/templates/cordova/lib/start-emulator
Executable file
@@ -0,0 +1,38 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
/*
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
*/
|
||||
|
||||
var emulator = require('./emulator');
|
||||
var args = process.argv;
|
||||
|
||||
var install_target;
|
||||
if (args.length > 2) {
|
||||
if (args[2].substring(0, 9) === '--target=') {
|
||||
install_target = args[2].substring(9, args[2].length);
|
||||
} else {
|
||||
console.error('ERROR : argument \'' + args[2] + '\' not recognized.');
|
||||
process.exit(2);
|
||||
}
|
||||
}
|
||||
|
||||
emulator.start(install_target).catch(function (err) {
|
||||
console.error('ERROR: ' + err);
|
||||
process.exit(2);
|
||||
});
|
||||
26
bin/templates/cordova/lib/start-emulator.bat
Normal file
@@ -0,0 +1,26 @@
|
||||
:: Licensed to the Apache Software Foundation (ASF) under one
|
||||
:: or more contributor license agreements. See the NOTICE file
|
||||
:: distributed with this work for additional information
|
||||
:: regarding copyright ownership. The ASF licenses this file
|
||||
:: to you under the Apache License, Version 2.0 (the
|
||||
:: "License"); you may not use this file except in compliance
|
||||
:: with the License. You may obtain a copy of the License at
|
||||
::
|
||||
:: http://www.apache.org/licenses/LICENSE-2.0
|
||||
::
|
||||
:: Unless required by applicable law or agreed to in writing,
|
||||
:: software distributed under the License is distributed on an
|
||||
:: "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
:: KIND, either express or implied. See the License for the
|
||||
:: specific language governing permissions and limitations
|
||||
:: under the License.
|
||||
|
||||
@ECHO OFF
|
||||
SET script_path="%~dp0start-emulator"
|
||||
IF EXIST %script_path% (
|
||||
node %script_path% %*
|
||||
) ELSE (
|
||||
ECHO.
|
||||
ECHO ERROR: Could not find 'start-emulator' script in 'cordova\lib' folder, aborting...>&2
|
||||
EXIT /B 1
|
||||
)
|
||||
@@ -17,11 +17,12 @@
|
||||
under the License.
|
||||
*/
|
||||
|
||||
const path = require('path');
|
||||
const { inspect } = require('util');
|
||||
const execa = require('execa');
|
||||
const Adb = require('./Adb');
|
||||
const build = require('./build');
|
||||
const emulator = require('./emulator');
|
||||
const AndroidManifest = require('./AndroidManifest');
|
||||
const { compareBy } = require('./utils');
|
||||
const { retryPromise } = require('./retry');
|
||||
const { events, CordovaError } = require('cordova-common');
|
||||
@@ -34,7 +35,6 @@ const EXEC_KILL_SIGNAL = 'SIGKILL';
|
||||
* @typedef { 'device' | 'emulator' } TargetType
|
||||
* @typedef { { id: string, type: TargetType } } Target
|
||||
* @typedef { { id?: string, type?: TargetType } } TargetSpec
|
||||
* @typedef { { apkPaths: string[] } } BuildResults
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -73,49 +73,30 @@ async function isEmulatorName (name) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {TargetSpec} spec
|
||||
* @param {BuildResults} buildResults
|
||||
* @param {TargetSpec?} spec
|
||||
* @return {Promise<Target>}
|
||||
*/
|
||||
async function resolveToOfflineEmulator ({ id: avdName, type }, { apkPaths }) {
|
||||
if (type === 'device') return null;
|
||||
async function resolveToOfflineEmulator (spec = {}) {
|
||||
if (spec.type === 'device') return null;
|
||||
if (spec.id && !(await isEmulatorName(spec.id))) return null;
|
||||
|
||||
if (avdName) {
|
||||
if (!await isEmulatorName(avdName)) return null;
|
||||
} else {
|
||||
events.emit('verbose', 'Looking for emulator image that best matches the target API');
|
||||
|
||||
const targetSdk = await getTargetSdkFromApk(apkPaths[0]);
|
||||
const bestImage = await emulator.best_image(targetSdk);
|
||||
if (!bestImage) return null;
|
||||
|
||||
avdName = bestImage.name;
|
||||
}
|
||||
|
||||
// try to start an emulator with name avdName
|
||||
const emulatorId = await emulator.start(avdName);
|
||||
// try to start an emulator with name spec.id
|
||||
// if spec.id is undefined, picks best match regarding target API
|
||||
const emulatorId = await emulator.start(spec.id);
|
||||
|
||||
return { id: emulatorId, type: 'emulator' };
|
||||
}
|
||||
|
||||
async function getTargetSdkFromApk (apkPath) {
|
||||
const { stdout: targetSdkStr } = await execa('apkanalyzer', [
|
||||
'manifest', 'target-sdk', apkPath
|
||||
]);
|
||||
return Number(targetSdkStr);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {TargetSpec?} spec
|
||||
* @param {BuildResults} buildResults
|
||||
* @return {Promise<Target & {arch: string}>}
|
||||
*/
|
||||
exports.resolve = async (spec, buildResults) => {
|
||||
exports.resolve = async (spec = {}) => {
|
||||
events.emit('verbose', `Trying to find target matching ${inspect(spec)}`);
|
||||
|
||||
const resolvedTarget =
|
||||
(await resolveToOnlineTarget(spec)) ||
|
||||
(await resolveToOfflineEmulator(spec, buildResults));
|
||||
(await resolveToOfflineEmulator(spec));
|
||||
|
||||
if (!resolvedTarget) {
|
||||
throw new CordovaError(`Could not find target matching ${inspect(spec)}`);
|
||||
@@ -127,9 +108,10 @@ exports.resolve = async (spec, buildResults) => {
|
||||
};
|
||||
};
|
||||
|
||||
exports.install = async function ({ id: target, arch, type }, { manifest, buildResults, cordovaGradleConfigParser }) {
|
||||
exports.install = async function ({ id: target, arch, type }, buildResults) {
|
||||
const apk_path = build.findBestApkForArchitecture(buildResults, arch);
|
||||
const pkgName = cordovaGradleConfigParser.getPackageName();
|
||||
const manifest = new AndroidManifest(path.join(__dirname, '../../app/src/main/AndroidManifest.xml'));
|
||||
const pkgName = manifest.getPackageId();
|
||||
const launchName = pkgName + '/.' + manifest.getActivity().getName();
|
||||
|
||||
events.emit('log', 'Using apk: ' + apk_path);
|
||||
@@ -66,21 +66,3 @@ exports.forgivingWhichSync = (cmd) => {
|
||||
|
||||
exports.isWindows = () => os.platform() === 'win32';
|
||||
exports.isDarwin = () => os.platform() === 'darwin';
|
||||
|
||||
const UNESCAPED_REGEX = /[&<>"']/g;
|
||||
|
||||
const escapes = {
|
||||
'&': '&',
|
||||
'<': '<',
|
||||
'>': '>',
|
||||
'"': '"',
|
||||
"'": '''
|
||||
};
|
||||
|
||||
/**
|
||||
* Converts the characters "&", "<", ">", '"' and "'" in the given string to
|
||||
* their corresponding escaped value
|
||||
* @param {string} str the string to be escaped
|
||||
* @returns the escaped string
|
||||
*/
|
||||
exports.escape = (str) => UNESCAPED_REGEX.test(str) ? str.replace(UNESCAPED_REGEX, (key) => escapes[key]) : str;
|
||||
36
bin/templates/cordova/log
Executable file
@@ -0,0 +1,36 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
/*
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
*/
|
||||
|
||||
var log = require('./lib/log');
|
||||
var reqs = require('./lib/check_reqs');
|
||||
var args = process.argv;
|
||||
|
||||
// Usage support for when args are given
|
||||
if (args.length > 2) {
|
||||
log.help();
|
||||
} else {
|
||||
reqs.run().then(function () {
|
||||
return log.run();
|
||||
}, function (err) {
|
||||
console.error('ERROR: ' + err);
|
||||
process.exit(2);
|
||||
});
|
||||
}
|
||||
26
bin/templates/cordova/log.bat
Normal file
@@ -0,0 +1,26 @@
|
||||
:: Licensed to the Apache Software Foundation (ASF) under one
|
||||
:: or more contributor license agreements. See the NOTICE file
|
||||
:: distributed with this work for additional information
|
||||
:: regarding copyright ownership. The ASF licenses this file
|
||||
:: to you under the Apache License, Version 2.0 (the
|
||||
:: "License"); you may not use this file except in compliance
|
||||
:: with the License. You may obtain a copy of the License at
|
||||
::
|
||||
:: http://www.apache.org/licenses/LICENSE-2.0
|
||||
::
|
||||
:: Unless required by applicable law or agreed to in writing,
|
||||
:: software distributed under the License is distributed on an
|
||||
:: "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
:: KIND, either express or implied. See the License for the
|
||||
:: specific language governing permissions and limitations
|
||||
:: under the License.
|
||||
|
||||
@ECHO OFF
|
||||
SET script_path="%~dp0log"
|
||||
IF EXIST %script_path% (
|
||||
node %script_path% %*
|
||||
) ELSE (
|
||||
ECHO.
|
||||
ECHO ERROR: Could not find 'log' script in 'cordova' folder, aborting...>&2
|
||||
EXIT /B 1
|
||||
)
|
||||
18
bin/templates/cordova/loggingHelper.js
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
var CordovaLogger = require('cordova-common').CordovaLogger;
|
||||
|
||||
module.exports = {
|
||||
adjustLoggerLevel: function (opts) {
|
||||
if (opts instanceof Array) {
|
||||
opts.silent = opts.indexOf('--silent') !== -1;
|
||||
opts.verbose = opts.indexOf('--verbose') !== -1;
|
||||
}
|
||||
|
||||
if (opts.silent) {
|
||||
CordovaLogger.get().setLevel('error');
|
||||
}
|
||||
|
||||
if (opts.verbose) {
|
||||
CordovaLogger.get().setLevel('verbose');
|
||||
}
|
||||
}
|
||||
};
|
||||
54
bin/templates/cordova/run
Executable file
@@ -0,0 +1,54 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
/*
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
*/
|
||||
|
||||
var Api = require('./Api');
|
||||
var nopt = require('nopt');
|
||||
var path = require('path');
|
||||
|
||||
// Support basic help commands
|
||||
if (['--help', '/?', '-h', 'help', '-help', '/help'].indexOf(process.argv[2]) >= 0) {
|
||||
require('./lib/run').help();
|
||||
}
|
||||
|
||||
// Do some basic argument parsing
|
||||
var runOpts = nopt({
|
||||
verbose: Boolean,
|
||||
silent: Boolean,
|
||||
debug: Boolean,
|
||||
release: Boolean,
|
||||
nobuild: Boolean,
|
||||
buildConfig: path,
|
||||
archs: String,
|
||||
device: Boolean,
|
||||
emulator: Boolean,
|
||||
target: String
|
||||
}, { d: '--verbose' });
|
||||
|
||||
// Make runOptions compatible with PlatformApi run method spec
|
||||
runOpts.argv = runOpts.argv.remain;
|
||||
|
||||
require('./loggingHelper').adjustLoggerLevel(runOpts);
|
||||
|
||||
new Api().run(runOpts)
|
||||
.catch(function (err) {
|
||||
console.error(err, err.stack);
|
||||
process.exit(2);
|
||||
});
|
||||
26
bin/templates/cordova/run.bat
Normal file
@@ -0,0 +1,26 @@
|
||||
:: Licensed to the Apache Software Foundation (ASF) under one
|
||||
:: or more contributor license agreements. See the NOTICE file
|
||||
:: distributed with this work for additional information
|
||||
:: regarding copyright ownership. The ASF licenses this file
|
||||
:: to you under the Apache License, Version 2.0 (the
|
||||
:: "License"); you may not use this file except in compliance
|
||||
:: with the License. You may obtain a copy of the License at
|
||||
::
|
||||
:: http://www.apache.org/licenses/LICENSE-2.0
|
||||
::
|
||||
:: Unless required by applicable law or agreed to in writing,
|
||||
:: software distributed under the License is distributed on an
|
||||
:: "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
:: KIND, either express or implied. See the License for the
|
||||
:: specific language governing permissions and limitations
|
||||
:: under the License.
|
||||
|
||||
@ECHO OFF
|
||||
SET script_path="%~dp0run"
|
||||
IF EXIST %script_path% (
|
||||
node %script_path% %*
|
||||
) ELSE (
|
||||
ECHO.
|
||||
ECHO ERROR: Could not find 'run' script in 'cordova' folder, aborting...>&2
|
||||
EXIT /B 1
|
||||
)
|
||||
26
bin/templates/cordova/version.bat
Normal file
@@ -0,0 +1,26 @@
|
||||
:: Licensed to the Apache Software Foundation (ASF) under one
|
||||
:: or more contributor license agreements. See the NOTICE file
|
||||
:: distributed with this work for additional information
|
||||
:: regarding copyright ownership. The ASF licenses this file
|
||||
:: to you under the Apache License, Version 2.0 (the
|
||||
:: "License"); you may not use this file except in compliance
|
||||
:: with the License. You may obtain a copy of the License at
|
||||
::
|
||||
:: http://www.apache.org/licenses/LICENSE-2.0
|
||||
::
|
||||
:: Unless required by applicable law or agreed to in writing,
|
||||
:: software distributed under the License is distributed on an
|
||||
:: "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
:: KIND, either express or implied. See the License for the
|
||||
:: specific language governing permissions and limitations
|
||||
:: under the License.
|
||||
|
||||
@ECHO OFF
|
||||
SET script_path="%~dp0version"
|
||||
IF EXIST %script_path% (
|
||||
node %script_path% %*
|
||||
) ELSE (
|
||||
ECHO.
|
||||
ECHO ERROR: Could not find 'version' script in 'cordova' folder, aborting...>&2
|
||||
EXIT /B 1
|
||||
)
|
||||
@@ -20,7 +20,6 @@
|
||||
package __ID__;
|
||||
|
||||
import android.os.Bundle;
|
||||
|
||||
import org.apache.cordova.*;
|
||||
|
||||
public class __ACTIVITY__ extends CordovaActivity
|
||||
@@ -18,9 +18,7 @@
|
||||
under the License.
|
||||
-->
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:versionName="1.0"
|
||||
android:versionCode="1"
|
||||
android:hardwareAccelerated="true">
|
||||
package="__PACKAGE__" android:versionName="1.0" android:versionCode="1" android:hardwareAccelerated="true">
|
||||
<supports-screens
|
||||
android:largeScreens="true"
|
||||
android:normalScreens="true"
|
||||
@@ -37,23 +35,13 @@
|
||||
<activity android:name="__ACTIVITY__"
|
||||
android:label="@string/activity_name"
|
||||
android:launchMode="singleTop"
|
||||
android:theme="@style/Theme.App.SplashScreen"
|
||||
android:theme="@android:style/Theme.DeviceDefault.NoActionBar"
|
||||
android:windowSoftInputMode="adjustResize"
|
||||
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|smallestScreenSize|screenLayout|uiMode"
|
||||
android:exported="true">
|
||||
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|smallestScreenSize|screenLayout|uiMode">
|
||||
<intent-filter android:label="@string/launcher_name">
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<provider android:name="androidx.core.content.FileProvider" android:authorities="${applicationId}.cdv.core.file.provider" android:exported="false" android:grantUriPermissions="true">
|
||||
<meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/cdv_core_file_provider_paths" />
|
||||
</provider>
|
||||
</application>
|
||||
|
||||
<queries>
|
||||
<intent>
|
||||
<action android:name="android.media.action.IMAGE_CAPTURE" />
|
||||
</intent>
|
||||
</queries>
|
||||
</manifest>
|
||||
@@ -19,43 +19,58 @@
|
||||
|
||||
apply plugin: 'com.android.application'
|
||||
|
||||
if (cordovaConfig.IS_GRADLE_PLUGIN_KOTLIN_ENABLED) {
|
||||
if (cdvHelpers.getConfigPreference('GradlePluginKotlinEnabled', 'false').toBoolean()) {
|
||||
apply plugin: 'kotlin-android'
|
||||
|
||||
if(!cdvHelpers.isVersionGreaterThanEqual(cordovaConfig.KOTLIN_VERSION, '1.8.0')) {
|
||||
println "Kotlin version < 1.8.0 detected. Applying kotlin-android-extensions plugin."
|
||||
apply plugin: 'kotlin-android-extensions'
|
||||
}
|
||||
apply plugin: 'kotlin-android-extensions'
|
||||
}
|
||||
|
||||
buildscript {
|
||||
apply from: '../CordovaLib/cordova.gradle'
|
||||
|
||||
// Checks if the kotlin version format is valid.
|
||||
if(cordovaConfig.IS_GRADLE_PLUGIN_KOTLIN_ENABLED) {
|
||||
if(!cdvHelpers.isVersionValid(cordovaConfig.KOTLIN_VERSION)) {
|
||||
throw new GradleException("The defined Kotlin version (${cordovaConfig.KOTLIN_VERSION}) does not appear to be a valid version.")
|
||||
if(cdvHelpers.getConfigPreference('GradlePluginKotlinEnabled', 'false').toBoolean()) {
|
||||
String defaultGradlePluginKotlinVersion = kotlin_version
|
||||
|
||||
/**
|
||||
* Fetches the user's defined Kotlin Version from config.xml.
|
||||
* If the version is not set or invalid, it will default to the ${defaultGradlePluginKotlinVersion}
|
||||
*/
|
||||
String gradlePluginKotlinVersion = cdvHelpers.getConfigPreference('GradlePluginKotlinVersion', defaultGradlePluginKotlinVersion)
|
||||
if(!cdvHelpers.isVersionValid(gradlePluginKotlinVersion)) {
|
||||
println("The defined Kotlin version (${gradlePluginKotlinVersion}) does not appear to be a valid version. Falling back to version: ${defaultGradlePluginKotlinVersion}.")
|
||||
gradlePluginKotlinVersion = defaultGradlePluginKotlinVersion
|
||||
}
|
||||
|
||||
// Change the version to be used.
|
||||
ext.kotlin_version = gradlePluginKotlinVersion
|
||||
}
|
||||
|
||||
apply from: 'repositories.gradle'
|
||||
repositories repos
|
||||
|
||||
dependencies {
|
||||
classpath "com.android.tools.build:gradle:${cordovaConfig.AGP_VERSION}"
|
||||
apply from: '../CordovaLib/cordova.gradle'
|
||||
|
||||
if (cordovaConfig.IS_GRADLE_PLUGIN_KOTLIN_ENABLED) {
|
||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${cordovaConfig.KOTLIN_VERSION}"
|
||||
classpath 'com.android.tools.build:gradle:4.0.0'
|
||||
|
||||
if (cdvHelpers.getConfigPreference('GradlePluginKotlinEnabled', 'false').toBoolean()) {
|
||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||
}
|
||||
|
||||
if(cordovaConfig.IS_GRADLE_PLUGIN_GOOGLE_SERVICES_ENABLED) {
|
||||
// Checks if the kotlin version format is valid.
|
||||
if(!cdvHelpers.isVersionValid(cordovaConfig.GRADLE_PLUGIN_GOOGLE_SERVICES_VERSION)) {
|
||||
throw new GradleException("The defined Google Services plugin version (${cordovaConfig.GRADLE_PLUGIN_GOOGLE_SERVICES_VERSION}) does not appear to be a valid version.")
|
||||
if(cdvHelpers.getConfigPreference('GradlePluginGoogleServicesEnabled', 'false').toBoolean()) {
|
||||
String defaultGradlePluginGoogleServicesVersion = '4.2.0'
|
||||
|
||||
/**
|
||||
* Fetches the user's defined Google Services Plugin Version from config.xml.
|
||||
* If the version is not set or invalid, it will default to the ${defaultGradlePluginGoogleServicesVersion}
|
||||
*/
|
||||
String gradlePluginGoogleServicesVersion = cdvHelpers.getConfigPreference('GradlePluginGoogleServicesVersion', defaultGradlePluginGoogleServicesVersion)
|
||||
if(!cdvHelpers.isVersionValid(gradlePluginGoogleServicesVersion)) {
|
||||
println("The defined Google Services plugin version (${gradlePluginGoogleServicesVersion}) does not appear to be a valid version. Falling back to version: ${defaultGradlePluginGoogleServicesVersion}.")
|
||||
gradlePluginGoogleServicesVersion = defaultGradlePluginGoogleServicesVersion
|
||||
}
|
||||
|
||||
// Create the Google Services classpath and set it.
|
||||
String gradlePluginGoogleServicesClassPath = "com.google.gms:google-services:${cordovaConfig.GRADLE_PLUGIN_GOOGLE_SERVICES_VERSION}"
|
||||
String gradlePluginGoogleServicesClassPath = "com.google.gms:google-services:${gradlePluginGoogleServicesVersion}"
|
||||
println "Adding classpath: ${gradlePluginGoogleServicesClassPath}"
|
||||
classpath gradlePluginGoogleServicesClassPath
|
||||
}
|
||||
@@ -64,18 +79,12 @@ buildscript {
|
||||
|
||||
// Allow plugins to declare Maven dependencies via build-extras.gradle.
|
||||
allprojects {
|
||||
def hasRepositoriesGradle = file('repositories.gradle').exists()
|
||||
if (hasRepositoriesGradle) {
|
||||
apply from: 'repositories.gradle'
|
||||
} else {
|
||||
apply from: "${project.rootDir}/repositories.gradle"
|
||||
}
|
||||
|
||||
apply from: 'repositories.gradle'
|
||||
repositories repos
|
||||
}
|
||||
|
||||
task wrapper(type: Wrapper) {
|
||||
gradleVersion = cordovaConfig.GRADLE_VERSION
|
||||
gradleVersion = '6.5'
|
||||
}
|
||||
|
||||
// Configuration properties. Set these via environment variables, build-extras.gradle, or gradle.properties.
|
||||
@@ -83,10 +92,30 @@ task wrapper(type: Wrapper) {
|
||||
ext {
|
||||
apply from: '../CordovaLib/cordova.gradle'
|
||||
|
||||
// The value for android.compileSdkVersion.
|
||||
if (!project.hasProperty('cdvCompileSdkVersion')) {
|
||||
cdvCompileSdkVersion = null;
|
||||
}
|
||||
// The value for android.buildToolsVersion.
|
||||
if (!project.hasProperty('cdvBuildToolsVersion')) {
|
||||
cdvBuildToolsVersion = null;
|
||||
}
|
||||
// Sets the versionCode to the given value.
|
||||
if (!project.hasProperty('cdvVersionCode')) {
|
||||
cdvVersionCode = null
|
||||
}
|
||||
// Sets the minSdkVersion to the given value.
|
||||
if (!project.hasProperty('cdvMinSdkVersion')) {
|
||||
cdvMinSdkVersion = null
|
||||
}
|
||||
// Sets the maxSdkVersion to the given value.
|
||||
if (!project.hasProperty('cdvMaxSdkVersion')) {
|
||||
cdvMaxSdkVersion = null
|
||||
}
|
||||
// The value for android.targetSdkVersion.
|
||||
if (!project.hasProperty('cdvTargetSdkVersion')) {
|
||||
cdvTargetSdkVersion = null;
|
||||
}
|
||||
// Whether to build architecture-specific APKs.
|
||||
if (!project.hasProperty('cdvBuildMultipleApks')) {
|
||||
cdvBuildMultipleApks = null
|
||||
@@ -125,10 +154,17 @@ if (hasBuildExtras2) {
|
||||
apply from: '../build-extras.gradle'
|
||||
}
|
||||
|
||||
// Apply updates that might come from build-extra.
|
||||
privateHelpers.applyCordovaConfigCustomization()
|
||||
|
||||
// Set property defaults after extension .gradle files.
|
||||
ext.cdvCompileSdkVersion = cdvCompileSdkVersion == null ? (
|
||||
defaultCompileSdkVersion == null
|
||||
? privateHelpers.getProjectTarget()
|
||||
: defaultCompileSdkVersion
|
||||
) : Integer.parseInt('' + cdvCompileSdkVersion);
|
||||
|
||||
if (ext.cdvBuildToolsVersion == null) {
|
||||
ext.cdvBuildToolsVersion = privateHelpers.findLatestInstalledBuildTools()
|
||||
//ext.cdvBuildToolsVersion = project.ext.defaultBuildToolsVersion
|
||||
}
|
||||
if (ext.cdvDebugSigningPropertiesFile == null && file('../debug-signing.properties').exists()) {
|
||||
ext.cdvDebugSigningPropertiesFile = '../debug-signing.properties'
|
||||
}
|
||||
@@ -139,6 +175,14 @@ if (ext.cdvReleaseSigningPropertiesFile == null && file('../release-signing.prop
|
||||
// Cast to appropriate types.
|
||||
ext.cdvBuildMultipleApks = cdvBuildMultipleApks == null ? false : cdvBuildMultipleApks.toBoolean();
|
||||
ext.cdvVersionCodeForceAbiDigit = cdvVersionCodeForceAbiDigit == null ? false : cdvVersionCodeForceAbiDigit.toBoolean();
|
||||
|
||||
// minSdkVersion, maxSdkVersion and targetSdkVersion
|
||||
ext.cdvMinSdkVersion = cdvMinSdkVersion == null ? defaultMinSdkVersion : Integer.parseInt('' + cdvMinSdkVersion)
|
||||
if (cdvMaxSdkVersion != null) {
|
||||
ext.cdvMaxSdkVersion = Integer.parseInt('' + cdvMaxSdkVersion)
|
||||
}
|
||||
ext.cdvTargetSdkVersion = cdvTargetSdkVersion == null ? defaultTargetSdkVersion : Integer.parseInt('' + cdvTargetSdkVersion)
|
||||
|
||||
ext.cdvVersionCode = cdvVersionCode == null ? null : Integer.parseInt('' + cdvVersionCode)
|
||||
|
||||
def computeBuildTargetName(debugBuild) {
|
||||
@@ -163,19 +207,18 @@ cdvBuildRelease.dependsOn {
|
||||
|
||||
task cdvPrintProps {
|
||||
doLast {
|
||||
println('cdvCompileSdkVersion=' + cdvCompileSdkVersion)
|
||||
println('cdvBuildToolsVersion=' + cdvBuildToolsVersion)
|
||||
println('cdvVersionCode=' + cdvVersionCode)
|
||||
println('cdvVersionCodeForceAbiDigit=' + cdvVersionCodeForceAbiDigit)
|
||||
println('cdvSdkVersion=' + cdvSdkVersion)
|
||||
println('cdvMinSdkVersion=' + cdvMinSdkVersion)
|
||||
println('cdvMaxSdkVersion=' + cdvMaxSdkVersion)
|
||||
println('cdvTargetSdkVersion=' + cdvTargetSdkVersion)
|
||||
println('cdvBuildMultipleApks=' + cdvBuildMultipleApks)
|
||||
println('cdvReleaseSigningPropertiesFile=' + cdvReleaseSigningPropertiesFile)
|
||||
println('cdvDebugSigningPropertiesFile=' + cdvDebugSigningPropertiesFile)
|
||||
println('cdvBuildArch=' + cdvBuildArch)
|
||||
println('computedVersionCode=' + android.defaultConfig.versionCode)
|
||||
println('cdvAndroidXAppCompatVersion=' + cdvAndroidXAppCompatVersion)
|
||||
println('cdvAndroidXWebKitVersion=' + cdvAndroidXWebKitVersion)
|
||||
android.productFlavors.each { flavor ->
|
||||
println('computed' + flavor.name.capitalize() + 'VersionCode=' + flavor.versionCode)
|
||||
}
|
||||
@@ -183,29 +226,29 @@ task cdvPrintProps {
|
||||
}
|
||||
|
||||
android {
|
||||
namespace cordovaConfig.PACKAGE_NAMESPACE
|
||||
|
||||
buildFeatures {
|
||||
buildConfig true
|
||||
}
|
||||
|
||||
defaultConfig {
|
||||
versionCode cdvVersionCode ?: new BigInteger("" + privateHelpers.extractIntFromManifest("versionCode"))
|
||||
applicationId cordovaConfig.PACKAGE_NAMESPACE
|
||||
applicationId privateHelpers.extractStringFromManifest("package")
|
||||
|
||||
minSdkVersion cordovaConfig.MIN_SDK_VERSION
|
||||
if (cordovaConfig.MAX_SDK_VERSION != null) {
|
||||
maxSdkVersion cordovaConfig.MAX_SDK_VERSION
|
||||
if (cdvMinSdkVersion != null) {
|
||||
minSdkVersion cdvMinSdkVersion
|
||||
}
|
||||
|
||||
if (cdvMaxSdkVersion != null) {
|
||||
maxSdkVersion cdvMaxSdkVersion
|
||||
}
|
||||
|
||||
if(cdvTargetSdkVersion != null) {
|
||||
targetSdkVersion cdvTargetSdkVersion
|
||||
}
|
||||
targetSdkVersion cordovaConfig.SDK_VERSION
|
||||
compileSdkVersion cordovaConfig.COMPILE_SDK_VERSION
|
||||
}
|
||||
|
||||
lintOptions {
|
||||
abortOnError false
|
||||
abortOnError false;
|
||||
}
|
||||
|
||||
buildToolsVersion cordovaConfig.BUILD_TOOLS_VERSION
|
||||
compileSdkVersion cdvCompileSdkVersion
|
||||
buildToolsVersion cdvBuildToolsVersion
|
||||
|
||||
// This code exists for Crosswalk and other Native APIs.
|
||||
// By default, we multiply the existing version code in the
|
||||
@@ -256,39 +299,8 @@ android {
|
||||
}
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility JavaLanguageVersion.of(cordovaConfig.JAVA_SOURCE_COMPATIBILITY)
|
||||
targetCompatibility JavaLanguageVersion.of(cordovaConfig.JAVA_TARGET_COMPATIBILITY)
|
||||
}
|
||||
|
||||
if (cordovaConfig.IS_GRADLE_PLUGIN_KOTLIN_ENABLED) {
|
||||
if (cordovaConfig.KOTLIN_JVM_TARGET == null) {
|
||||
// If the value is null, fallback to JAVA_TARGET_COMPATIBILITY,
|
||||
// as they generally should be equal
|
||||
def javaTarget = JavaLanguageVersion.of(cordovaConfig.JAVA_TARGET_COMPATIBILITY)
|
||||
|
||||
// check if javaTarget is <= 8; if so, we need to prefix it with "1."
|
||||
// Starting with 9 and later, the value can be used as is.
|
||||
if (javaTarget.compareTo(JavaLanguageVersion.of(8)) <= 0) {
|
||||
javaTarget = "1." + javaTarget
|
||||
}
|
||||
|
||||
cordovaConfig.KOTLIN_JVM_TARGET = javaTarget
|
||||
}
|
||||
|
||||
// Similar to above, check if kotlin target is <= 8, if so prefix it.
|
||||
// This allows the user to use consistent set of values in config.xml
|
||||
// Rather than having to be aware whether the "1."" prefix is needed.
|
||||
// This check is only done if the value isn't already prefixed with 1.
|
||||
if (
|
||||
!cordovaConfig.KOTLIN_JVM_TARGET.startsWith("1.") &&
|
||||
JavaLanguageVersion.of(cordovaConfig.KOTLIN_JVM_TARGET).compareTo(JavaLanguageVersion.of(8)) <= 0
|
||||
) {
|
||||
cordovaConfig.KOTLIN_JVM_TARGET = "1." + cordovaConfig.KOTLIN_JVM_TARGET
|
||||
}
|
||||
|
||||
kotlinOptions {
|
||||
jvmTarget = cordovaConfig.KOTLIN_JVM_TARGET
|
||||
}
|
||||
sourceCompatibility JavaVersion.VERSION_1_8
|
||||
targetCompatibility JavaVersion.VERSION_1_8
|
||||
}
|
||||
|
||||
if (cdvReleaseSigningPropertiesFile) {
|
||||
@@ -296,9 +308,9 @@ android {
|
||||
release {
|
||||
// These must be set or Gradle will complain (even if they are overridden).
|
||||
keyAlias = ""
|
||||
keyPassword = ""
|
||||
keyPassword = "__unset" // And these must be set to non-empty in order to have the signing step added to the task graph.
|
||||
storeFile = null
|
||||
storePassword = ""
|
||||
storePassword = "__unset"
|
||||
}
|
||||
}
|
||||
buildTypes {
|
||||
@@ -327,11 +339,9 @@ android {
|
||||
|
||||
dependencies {
|
||||
implementation fileTree(dir: 'libs', include: '*.jar')
|
||||
implementation "androidx.appcompat:appcompat:${cordovaConfig.ANDROIDX_APP_COMPAT_VERSION}"
|
||||
implementation "androidx.core:core-splashscreen:${cordovaConfig.ANDROIDX_CORE_SPLASHSCREEN_VERSION}"
|
||||
|
||||
if (cordovaConfig.IS_GRADLE_PLUGIN_KOTLIN_ENABLED) {
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:${cordovaConfig.KOTLIN_VERSION}"
|
||||
if (cdvHelpers.getConfigPreference('GradlePluginKotlinEnabled', 'false').toBoolean()) {
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
|
||||
}
|
||||
|
||||
// SUB-PROJECT DEPENDENCIES START
|
||||
@@ -340,6 +350,26 @@ dependencies {
|
||||
// SUB-PROJECT DEPENDENCIES END
|
||||
}
|
||||
|
||||
def promptForReleaseKeyPassword() {
|
||||
if (!cdvReleaseSigningPropertiesFile) {
|
||||
return;
|
||||
}
|
||||
if ('__unset'.equals(android.signingConfigs.release.storePassword)) {
|
||||
android.signingConfigs.release.storePassword = privateHelpers.promptForPassword('Enter key store password: ')
|
||||
}
|
||||
if ('__unset'.equals(android.signingConfigs.release.keyPassword)) {
|
||||
android.signingConfigs.release.keyPassword = privateHelpers.promptForPassword('Enter key password: ');
|
||||
}
|
||||
}
|
||||
|
||||
gradle.taskGraph.whenReady { taskGraph ->
|
||||
taskGraph.getAllTasks().each() { task ->
|
||||
if(['validateReleaseSigning', 'validateSigningRelease', 'validateSigningArmv7Release', 'validateSigningX76Release'].contains(task.name)) {
|
||||
promptForReleaseKeyPassword()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def addSigningProps(propsFilePath, signingConfig) {
|
||||
def propsFile = file(propsFilePath)
|
||||
def props = new Properties()
|
||||
@@ -360,7 +390,7 @@ def addSigningProps(propsFilePath, signingConfig) {
|
||||
signingConfig.storePassword = props.get('storePassword', props.get('key.store.password', signingConfig.storePassword))
|
||||
def storeType = props.get('storeType', props.get('key.store.type', ''))
|
||||
if (!storeType) {
|
||||
def filename = storeFile.getName().toLowerCase()
|
||||
def filename = storeFile.getName().toLowerCase();
|
||||
if (filename.endsWith('.p12') || filename.endsWith('.pfx')) {
|
||||
storeType = 'pkcs12'
|
||||
} else {
|
||||
@@ -380,6 +410,6 @@ if (hasProperty('postBuildExtras')) {
|
||||
postBuildExtras()
|
||||
}
|
||||
|
||||
if (cordovaConfig.IS_GRADLE_PLUGIN_GOOGLE_SERVICES_ENABLED) {
|
||||
if (cdvHelpers.getConfigPreference('GradlePluginGoogleServicesEnabled', 'false').toBoolean()) {
|
||||
apply plugin: 'com.google.gms.google-services'
|
||||
}
|
||||
@@ -17,6 +17,7 @@
|
||||
*/
|
||||
|
||||
ext.repos = {
|
||||
google()
|
||||
mavenCentral()
|
||||
google()
|
||||
jcenter()
|
||||
}
|
||||
1904
bin/templates/project/assets/www/cordova.js
vendored
Normal file
|
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 20 KiB |
|
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 21 KiB |
@@ -21,7 +21,7 @@
|
||||
<head>
|
||||
<!--
|
||||
Customize this policy to fit your own app's needs. For more guidance, see:
|
||||
https://cordova.apache.org/docs/en/latest/
|
||||
https://github.com/apache/cordova-plugin-whitelist/blob/master/README.md#content-security-policy
|
||||
Some notes:
|
||||
* gap: is required only on iOS (when using UIWebView) and is needed for JS->native communication
|
||||
* https://ssl.gstatic.com is required only on Android and is needed for TalkBack to function properly
|
||||
@@ -17,29 +17,31 @@
|
||||
*/
|
||||
|
||||
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||
|
||||
buildscript {
|
||||
apply from: 'CordovaLib/cordova.gradle'
|
||||
ext.kotlin_version = '1.3.50'
|
||||
apply from: 'repositories.gradle'
|
||||
repositories repos
|
||||
|
||||
dependencies {
|
||||
classpath "com.android.tools.build:gradle:${cordovaConfig.AGP_VERSION}"
|
||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${cordovaConfig.KOTLIN_VERSION}"
|
||||
classpath 'com.android.tools.build:gradle:4.0.0'
|
||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||
// NOTE: Do not place your application dependencies here; they belong
|
||||
// in the individual module build.gradle files
|
||||
}
|
||||
|
||||
cdvHelpers.verifyCordovaConfigForBuild()
|
||||
}
|
||||
|
||||
allprojects {
|
||||
def hasRepositoriesGradle = file('repositories.gradle').exists()
|
||||
if (hasRepositoriesGradle) {
|
||||
apply from: 'repositories.gradle'
|
||||
} else {
|
||||
apply from: "${project.rootDir}/repositories.gradle"
|
||||
}
|
||||
|
||||
apply from: 'repositories.gradle'
|
||||
repositories repos
|
||||
|
||||
//This replaces project.properties w.r.t. build settings
|
||||
project.ext {
|
||||
defaultBuildToolsVersion="29.0.2" //String
|
||||
defaultMinSdkVersion=22 //Integer - Minimum requirement is Android 5.1
|
||||
defaultTargetSdkVersion=29 //Integer - We ALWAYS target the latest by default
|
||||
defaultCompileSdkVersion=29 //Integer - We ALWAYS compile with the latest by default
|
||||
}
|
||||
}
|
||||
|
||||
task clean(type: Delete) {
|
||||
13
bin/templates/project/project.properties
Normal file
@@ -0,0 +1,13 @@
|
||||
# This file was originally created by the Android Tools, but is now
|
||||
# used by cordova-android to manage the state of the various third party
|
||||
# libraries used in your application
|
||||
|
||||
# This is the Library Module that contains the Cordova Library, this is not
|
||||
# required when using an AAR
|
||||
android.library.reference.1=CordovaLib
|
||||
|
||||
# This is the application project. This is only required for Android Studio Gradle projects
|
||||
android.library.reference.2=app
|
||||
|
||||
# Project target.
|
||||
target=This_gets_replaced
|
||||
@@ -18,5 +18,5 @@
|
||||
|
||||
ext.repos = {
|
||||
google()
|
||||
mavenCentral()
|
||||
jcenter()
|
||||
}
|
||||
BIN
bin/templates/project/res/drawable-land-hdpi/screen.png
Normal file
|
After Width: | Height: | Size: 38 KiB |
BIN
bin/templates/project/res/drawable-land-ldpi/screen.png
Normal file
|
After Width: | Height: | Size: 7.6 KiB |
BIN
bin/templates/project/res/drawable-land-mdpi/screen.png
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
bin/templates/project/res/drawable-land-xhdpi/screen.png
Normal file
|
After Width: | Height: | Size: 78 KiB |
BIN
bin/templates/project/res/drawable-land-xxhdpi/screen.png
Normal file
|
After Width: | Height: | Size: 129 KiB |
BIN
bin/templates/project/res/drawable-land-xxxhdpi/screen.png
Normal file
|
After Width: | Height: | Size: 190 KiB |
BIN
bin/templates/project/res/drawable-port-hdpi/screen.png
Normal file
|
After Width: | Height: | Size: 35 KiB |
BIN
bin/templates/project/res/drawable-port-ldpi/screen.png
Normal file
|
After Width: | Height: | Size: 8.1 KiB |
BIN
bin/templates/project/res/drawable-port-mdpi/screen.png
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
bin/templates/project/res/drawable-port-xhdpi/screen.png
Normal file
|
After Width: | Height: | Size: 75 KiB |
BIN
bin/templates/project/res/drawable-port-xxhdpi/screen.png
Normal file
|
After Width: | Height: | Size: 122 KiB |
BIN
bin/templates/project/res/drawable-port-xxxhdpi/screen.png
Normal file
|
After Width: | Height: | Size: 192 KiB |
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@mipmap/ic_launcher_background" />
|
||||
<foreground android:drawable="@mipmap/ic_launcher_foreground" />
|
||||
</adaptive-icon>
|
||||
|
Before Width: | Height: | Size: 86 B After Width: | Height: | Size: 86 B |
|
Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 2.6 KiB |
|
Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 2.6 KiB |
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@mipmap/ic_launcher_background" />
|
||||
<foreground android:drawable="@mipmap/ic_launcher_foreground" />
|
||||
</adaptive-icon>
|
||||
|
Before Width: | Height: | Size: 83 B After Width: | Height: | Size: 83 B |
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@mipmap/ic_launcher_background" />
|
||||
<foreground android:drawable="@mipmap/ic_launcher_foreground" />
|
||||
</adaptive-icon>
|
||||