OracleJet:无法在Android平台上构建应用程序?



昨天,我用android平台构建了我的OracleJet应用程序,但我得到了这个错误:

> npx @oracle/ojet-cli@8.0.0 serve android --device
Task index.html theme path injection finished.
Injecting index.html with cordova script.
Error: TypeError [ERR_INVALID_ARG_TYPE]: The "data" argument must be of type string or an instance of Buffer, TypedArray, or DataView. Received an instance of Document

What I tried:

  1. 删除node_modules文件夹并运行nmp install

  2. 升级节点到最新版本18.2.0

但是没有成功

OracleJet版本:8.0.0Cordova版本:11.0.0

包。json:

{
"name": "mobile-electronic",
"version": "1.0.0",
"description": "An Oracle JavaScript Extension Toolkit (JET) mobile app",
"dependencies": {
"@oracle/oraclejet": "~5.0.0"
},
"devDependencies": {
"fs-extra": "0.30.0",
"grunt": "^1.0.1",
"@oracle/oraclejet-tooling": "~8.0.0",
"@oracle/grunt-oraclejet": "~5.0.0",
"load-grunt-config": "0.19.2",
"qunit-reporter-junit": "^1.1.1",
"qunit": "^2.4.1"
},
"engines": {
"node": ">=0.10.0"
},
"private": true

}

index . html:

<!DOCTYPE html>
<!--
Copyright (c) 2014, 2018, Oracle and/or its affiliates.
The Universal Permissive License (UPL), Version 1.0
-->
<!-- ************************ IMPORTANT INFORMATION ************************************
This hybrid navigation drawer template is provided as an example of how to configure
a JET hybrid mobile application with a navigation drawer as a single page application
using ojRouter and oj-module.  It contains the Oracle JET framework and a default
requireJS configuration file to show how JET can be setup in a common application.
This project template can be used in conjunction with demo code from the JET
website to test JET component behavior and interactions.
Any CSS styling with the prefix "demo-" is for demonstration only and is not
provided as part of the JET framework.
Please see the demos under Cookbook/Patterns/App Shell: Hybrid Mobile and the CSS documentation
under Support/API Docs/Non-Component Styling on the JET website for more information on how to use 
the best practice patterns shown in this template.
Aria Landmark role attributes are added to the different sections of the application
for accessibility compliance. If you change the type of content for a specific
section from what is defined, you should also change the role value for that
section to represent the appropriate content type.
***************************** IMPORTANT INFORMATION ************************************ -->
<html lang="en-us">
<head>
<title>Oracle JET Starter Template - Hybrid Nav Drawer</title>
<meta charset="UTF-8">
<meta http-equiv="Content-Security-Policy" content="default-src *; script-src 'self' *.oracle.com 'unsafe-inline' 'unsafe-eval'; style-src 'self' *.oracle.com  'unsafe-inline'; img-src * data:">
<meta name="viewport" content="viewport-fit=cover, width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"/>
<link rel="icon" href="css/images/favicon.ico" type="image/x-icon" />
<!-- This is the main css file for the default Alta theme -->
<!-- injector:theme -->
<link rel="stylesheet" href="css/libs/oj/v5.0.0/alta/oj-alta-min.css" type="text/css"/>
<!-- endinjector -->
<!-- This contains icon fonts used by the starter template -->
<link rel="stylesheet" href="css/demo-alta-site-min.css" type="text/css"/>
<!-- This is where you would add any app specific styling -->
<link rel="stylesheet" href="css/app.css" type="text/css"/>
</head>
<body>
<!-- template for rendering navigation items in the drawer -->
<script type="text/html" id="navTemplate">
<li><a href="#">
<span :class="[[$data['iconClass']]]"></span>
<oj-bind-text value="[[$data['name']]]"></oj-bind-text>
</a></li>
</script>

<div id="globalBody" class="oj-offcanvas-outer-wrapper oj-offcanvas-page">
<!--
** Oracle JET V5.0.0 hybrid mobile application navigation drawer pattern.
** Please see the demos under Cookbook/Patterns/App Shell: Hybrid Mobile 
** and the CSS documentation under Support/API Docs/Non-Component Styling
** on the JET website for more information on how to use this pattern.
-->
<div id="navDrawer" role="navigation" class="oj-hybrid-applayout-offcanvas oj-contrast-marker oj-offcanvas-start">
<!-- User Profile -->
<img alt="profile image" src="css/images/james_avatar.png" class="demo-james-icon">
<h2 class="demo-profile-name">James</h2>
<!-- Navigation -->
<oj-navigation-list class="oj-navigationlist-stack-icon-label"
data="[[navDataSource]]"
edge="start"
item.renderer="[[oj.KnockoutTemplateUtils.getRenderer('navTemplate', true)]]"
on-click="[[toggleDrawer]]"
selection="{{router.stateId}}">
</oj-navigation-list>
<div class="oj-flex-bar oj-sm-justify-content-center">
<h2 class="demo-app-name">Oracle App Name</h2>
</div>
</div>

<oj-module id="pageContent" config="[[moduleConfig]]"></oj-module>
</div>

<script type="text/javascript" src="js/libs/require/require.js"></script>
<script type="text/javascript" src="js/main.js"></script>
</body>
</html>

android build.gradle


buildscript {
apply from: 'CordovaLib/cordova.gradle'
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}"
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
allprojects {
def hasRepositoriesGradle = file('repositories.gradle').exists()
if (hasRepositoriesGradle) {
apply from: 'repositories.gradle'
} else {
apply from: "${project.rootDir}/repositories.gradle"
}
repositories repos
}
task clean(type: Delete) {
delete rootProject.buildDir
}

文件夹平台->android>app build.gradle:

/*
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.
*/
apply plugin: 'com.android.application'
if (cordovaConfig.IS_GRADLE_PLUGIN_KOTLIN_ENABLED) {
apply plugin: 'kotlin-android'
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.")
}
}
apply from: 'repositories.gradle'
repositories repos
dependencies {
classpath "com.android.tools.build:gradle:${cordovaConfig.AGP_VERSION}"
if (cordovaConfig.IS_GRADLE_PLUGIN_KOTLIN_ENABLED) {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${cordovaConfig.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.")
}
// Create the Google Services classpath and set it.
String gradlePluginGoogleServicesClassPath = "com.google.gms:google-services:${cordovaConfig.GRADLE_PLUGIN_GOOGLE_SERVICES_VERSION}"
println "Adding classpath: ${gradlePluginGoogleServicesClassPath}"
classpath gradlePluginGoogleServicesClassPath
}
}
}
// 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"
}
repositories repos
}
task wrapper(type: Wrapper) {
gradleVersion = cordovaConfig.GRADLE_VERSION
}
// Configuration properties. Set these via environment variables, build-extras.gradle, or gradle.properties.
// Refer to: http://www.gradle.org/docs/current/userguide/tutorial_this_and_that.html
ext {
apply from: '../CordovaLib/cordova.gradle'
// Sets the versionCode to the given value.
if (!project.hasProperty('cdvVersionCode')) {
cdvVersionCode = null
}
// Whether to build architecture-specific APKs.
if (!project.hasProperty('cdvBuildMultipleApks')) {
cdvBuildMultipleApks = null
}
// Whether to append a 0 "abi digit" to versionCode when only a single APK is build
if (!project.hasProperty('cdvVersionCodeForceAbiDigit')) {
cdvVersionCodeForceAbiDigit = null
}
// .properties files to use for release signing.
if (!project.hasProperty('cdvReleaseSigningPropertiesFile')) {
cdvReleaseSigningPropertiesFile = null
}
// .properties files to use for debug signing.
if (!project.hasProperty('cdvDebugSigningPropertiesFile')) {
cdvDebugSigningPropertiesFile = null
}
// Set by build.js script.
if (!project.hasProperty('cdvBuildArch')) {
cdvBuildArch = null
}
// Plugin gradle extensions can append to this to have code run at the end.
cdvPluginPostBuildExtras = []
}
// PLUGIN GRADLE EXTENSIONS START
// PLUGIN GRADLE EXTENSIONS END
def hasBuildExtras1 = file('build-extras.gradle').exists()
if (hasBuildExtras1) {
apply from: 'build-extras.gradle'
}
def hasBuildExtras2 = file('../build-extras.gradle').exists()
if (hasBuildExtras2) {
apply from: '../build-extras.gradle'
}
// Apply updates that might come from build-extra.
privateHelpers.applyCordovaConfigCustomization()
// Set property defaults after extension .gradle files.
if (ext.cdvDebugSigningPropertiesFile == null && file('../debug-signing.properties').exists()) {
ext.cdvDebugSigningPropertiesFile = '../debug-signing.properties'
}
if (ext.cdvReleaseSigningPropertiesFile == null && file('../release-signing.properties').exists()) {
ext.cdvReleaseSigningPropertiesFile = '../release-signing.properties'
}
// Cast to appropriate types.
ext.cdvBuildMultipleApks = cdvBuildMultipleApks == null ? false : cdvBuildMultipleApks.toBoolean();
ext.cdvVersionCodeForceAbiDigit = cdvVersionCodeForceAbiDigit == null ? false : cdvVersionCodeForceAbiDigit.toBoolean();
ext.cdvVersionCode = cdvVersionCode == null ? null : Integer.parseInt('' + cdvVersionCode)
def computeBuildTargetName(debugBuild) {
def ret = 'assemble'
if (cdvBuildMultipleApks && cdvBuildArch) {
def arch = cdvBuildArch == 'arm' ? 'armv7' : cdvBuildArch
ret += '' + arch.toUpperCase().charAt(0) + arch.substring(1);
}
return ret + (debugBuild ? 'Debug' : 'Release')
}
// Make cdvBuild a task that depends on the debug/arch-sepecific task.
task cdvBuildDebug
cdvBuildDebug.dependsOn {
return computeBuildTargetName(true)
}
task cdvBuildRelease
cdvBuildRelease.dependsOn {
return computeBuildTargetName(false)
}
task cdvPrintProps {
doLast {
println('cdvBuildToolsVersion=' + cdvBuildToolsVersion)
println('cdvVersionCode=' + cdvVersionCode)
println('cdvVersionCodeForceAbiDigit=' + cdvVersionCodeForceAbiDigit)
println('cdvSdkVersion=' + cdvSdkVersion)
println('cdvMinSdkVersion=' + cdvMinSdkVersion)
println('cdvMaxSdkVersion=' + cdvMaxSdkVersion)
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)
}
}
}
android {
defaultConfig {
versionCode cdvVersionCode ?: new BigInteger("" + privateHelpers.extractIntFromManifest("versionCode"))
applicationId privateHelpers.extractStringFromManifest("package")
minSdkVersion cordovaConfig.MIN_SDK_VERSION
if (cordovaConfig.MAX_SDK_VERSION != null) {
maxSdkVersion cordovaConfig.MAX_SDK_VERSION
}
targetSdkVersion cordovaConfig.SDK_VERSION
compileSdkVersion cordovaConfig.SDK_VERSION
}
lintOptions {
abortOnError false
}
buildToolsVersion cordovaConfig.BUILD_TOOLS_VERSION
// This code exists for Crosswalk and other Native APIs.
// By default, we multiply the existing version code in the
// Android Manifest by 10 and add a number for each architecture.
// If you are not using Crosswalk or SQLite, you can
// ignore this chunk of code, and your version codes will be respected.
if (Boolean.valueOf(cdvBuildMultipleApks)) {
flavorDimensions "default"
productFlavors {
armeabi {
versionCode defaultConfig.versionCode*10 + 1
ndk {
abiFilters = ["armeabi"]
}
}
armv7 {
versionCode defaultConfig.versionCode*10 + 2
ndk {
abiFilters = ["armeabi-v7a"]
}
}
arm64 {
versionCode defaultConfig.versionCode*10 + 3
ndk {
abiFilters = ["arm64-v8a"]
}
}
x86 {
versionCode defaultConfig.versionCode*10 + 4
ndk {
abiFilters = ["x86"]
}
}
x86_64 {
versionCode defaultConfig.versionCode*10 + 5
ndk {
abiFilters = ["x86_64"]
}
}
}
} else if (Boolean.valueOf(cdvVersionCodeForceAbiDigit)) {
// This provides compatibility to the default logic for versionCode before cordova-android 5.2.0
defaultConfig {
versionCode defaultConfig.versionCode*10
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
if (cdvReleaseSigningPropertiesFile) {
signingConfigs {
release {
// These must be set or Gradle will complain (even if they are overridden).
keyAlias = ""
keyPassword = ""
storeFile = null
storePassword = ""
}
}
buildTypes {
release {
signingConfig signingConfigs.release
}
}
addSigningProps(cdvReleaseSigningPropertiesFile, signingConfigs.release)
}
if (cdvDebugSigningPropertiesFile) {
addSigningProps(cdvDebugSigningPropertiesFile, signingConfigs.debug)
}
sourceSets {
main.java.srcDirs += 'src/main/kotlin'
}
}
/*
* WARNING: Cordova Lib and platform scripts do management inside of this code here,
* if you are adding the dependencies manually, do so outside the comments, otherwise
* the Cordova tools will overwrite them
*/

dependencies {
implementation fileTree(dir: 'libs', include: '*.jar')
implementation "androidx.appcompat:appcompat:${cordovaConfig.ANDROIDX_APP_COMPAT_VERSION}"
if (cordovaConfig.IS_GRADLE_PLUGIN_KOTLIN_ENABLED) {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:${cordovaConfig.KOTLIN_VERSION}"
}
// SUB-PROJECT DEPENDENCIES START
implementation(project(path: ":CordovaLib"))
// SUB-PROJECT DEPENDENCIES END
}
def addSigningProps(propsFilePath, signingConfig) {
def propsFile = file(propsFilePath)
def props = new Properties()
propsFile.withReader { reader ->
props.load(reader)
}
def storeFile = new File(props.get('key.store') ?: privateHelpers.ensureValueExists(propsFilePath, props, 'storeFile'))
if (!storeFile.isAbsolute()) {
storeFile = RelativePath.parse(true, storeFile.toString()).getFile(propsFile.getParentFile())
}
if (!storeFile.exists()) {
throw new FileNotFoundException('Keystore file does not exist: ' + storeFile.getAbsolutePath())
}
signingConfig.keyAlias = props.get('key.alias') ?: privateHelpers.ensureValueExists(propsFilePath, props, 'keyAlias')
signingConfig.keyPassword = props.get('keyPassword', props.get('key.alias.password', signingConfig.keyPassword))
signingConfig.storeFile = storeFile
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()
if (filename.endsWith('.p12') || filename.endsWith('.pfx')) {
storeType = 'pkcs12'
} else {
storeType = signingConfig.storeType // "jks"
}
}
signingConfig.storeType = storeType
}
for (def func : cdvPluginPostBuildExtras) {
func()
}
// This can be defined within build-extras.gradle as:
//     ext.postBuildExtras = { ... code here ... }
if (hasProperty('postBuildExtras')) {
postBuildExtras()
}
if (cordovaConfig.IS_GRADLE_PLUGIN_GOOGLE_SERVICES_ENABLED) {
apply plugin: 'com.google.gms.google-services'
}

您面临的错误与非常旧的Oracle JET工具和较新的Cordova &Node.js版本,我不记得到底是哪一个导致了这个问题。通常,起点是hybrid/scripts/hooks/jetInjector.js,这是您的堆栈跟踪应该引导您的地方。你有两个选项:

  • 降级Node.js &科尔多瓦
  • 升级Oracle JET,主要是工具

后者还将从项目的根目录和hybrid的根目录升级脚本,修复fs.writeFileSync调用,这就是导致错误的原因。

另一个选项可能是你正在读取一个文件,然后重写它,文件不存在,所以写入失败,因为内容是null。不过,升级Oracle JET工具将修复任何损坏的路径。

考虑到所有的事情,如果你不想改变你正在使用的版本,我会从jetInjector.js开始,但即使这样,你可能会被迫升级,因为JET 5.0.0和JET工具8.0.0(与Grunt?!)已经有几年了,运行在最新的Node.js LTS上。在ojet buildcordova build上启用一些调试标志可能会让你更详细地了解项目中真正发生的事情。

注。使用一个全局版本和另一个被列为devDependency的版本是很糟糕的。试试npx ojet serve android --device,它将调用本地安装的ojet版本。

编辑:寻找_getIndexHtmlPath_getConfigXmlPath,这就是给我带来问题的原因。我不得不从configXmlPath = "platforms/android/res/xml"更改为configXmlPath = 'platforms/android/app/src/main/res/xml';,我猜它来自较新的Android SDK工具或cordova或两者。

最新更新