Related
I set up a pipeline on a CI/CD (Azure Devops) to build my react native app, specifically for android.
Even though it builds correctly on my local mac (Mac OS 12.1), and assembles to a valid APK correctly, the same build step throws an error in the pipeline either using a Mac agent (MacOS 10.15 | 11), or Linux agents (Ubuntu 18.04 | 20.04).
This is the error:
> Task :app:bundleProductionReleaseJsAndAssets FAILED
Error: Cannot find module 'babel-plugin-module-resolver'
Require stack:
- /Users/runner/work/1/s/babel.config.js
- /Users/runner/work/1/s/node_modules/#babel/core/lib/config/files/module-types.js
- /Users/runner/work/1/s/node_modules/#babel/core/lib/config/files/configuration.js
- /Users/runner/work/1/s/node_modules/#babel/core/lib/config/files/index.js
- /Users/runner/work/1/s/node_modules/#babel/core/lib/index.js
- /Users/runner/work/1/s/node_modules/metro-react-native-babel-transformer/src/index.js
- /Users/runner/work/1/s/node_modules/metro-transform-worker/src/index.js
- /Users/runner/work/1/s/node_modules/metro/src/DeltaBundler/Worker.js
error index.js: Cannot find module 'babel-plugin-module-resolver'
Require stack:
- /Users/runner/work/1/s/babel.config.js
- /Users/runner/work/1/s/node_modules/#babel/core/lib/config/files/module-types.js
- /Users/runner/work/1/s/node_modules/#babel/core/lib/config/files/configuration.js
- /Users/runner/work/1/s/node_modules/#babel/core/lib/config/files/index.js
- /Users/runner/work/1/s/node_modules/#babel/core/lib/index.js
- /Users/runner/work/1/s/node_modules/metro-react-native-babel-transformer/src/index.js
- /Users/runner/work/1/s/node_modules/metro-transform-worker/src/index.js
- /Users/runner/work/1/s/node_modules/metro/src/DeltaBundler/Worker.js
- /Users/runner/work/1/s/node_modules/metro/node_modules/jest-worker/build/workers/processChild.js.
- /Users/runner/work/1/s/node_modules/metro/node_modules/jest-worker/build/workers/processChild.js
at Function.Module._resolveFilename (internal/modules/cjs/loader.js:902:15)
at Function.resolve (internal/modules/cjs/helpers.js:98:19)
at module.exports (/Users/runner/work/1/s/babel.config.js:7:17)
at readConfigJS (/Users/runner/work/1/s/node_modules/#babel/core/lib/config/files/configuration.js:227:15)
at readConfigJS.next (<anonymous>)
at Function.<anonymous> (/Users/runner/work/1/s/node_modules/#babel/core/lib/gensync-utils/async.js:25:3)
at Generator.next (<anonymous>)
at evaluateSync (/Users/runner/work/1/s/node_modules/gensync/index.js:251:28)
at Function.sync (/Users/runner/work/1/s/node_modules/gensync/index.js:89:14)
This is my babel.config.js:
module.exports = function (api) {
api.cache(true);
return {
presets: ['module:metro-react-native-babel-preset', 'module:#babel/preset-typescript'],
plugins: [
[
require.resolve('babel-plugin-module-resolver'),
{
root: ['./'],
extensions: [
'.ios.ts',
'.android.ts',
'.ts',
'.ios.tsx',
'.android.tsx',
'.tsx',
'.jsx',
'.js',
'.json',
],
alias: {
'#components': ['./src/components'],
'#screens': ['./src/screens/'],
'#shared': ['./src/shared/'],
'#static': ['./src/static/'],
'#stores': ['./src/stores/'],
'#styles': ['./src/styles/'],
},
},
],
[
'module:react-native-dotenv',
{
moduleName: '#env',
path: '.env',
blacklist: null,
whitelist: null,
safe: true,
allowUndefined: true,
},
],
'react-native-reanimated/plugin', // this plugin should be always at the end
],
};
};
And my package.json (a reduced version in terms of dependencies for simplicity):
{
...
"dependencies": {
"react": "17.0.2",
// others not relevant
},
"devDependencies": {
"#babel/core": "7.17.8",
"#babel/preset-env": "7.16.11",
"#babel/runtime": "7.17.8",
"babel-plugin-module-resolver": "4.1.0",
"metro-react-native-babel-preset": "0.70.0",
"react-native-dotenv": "3.3.1",
// others not relevant
},
"resolutions": {
"#types/react": "^17"
}
}
I know that a similar question has been already asked, but it doesn't have any response and it has an issue building the project even in a local machine. I only have this issue in the pipeline.
I am new to app building and I started using nuxt and capacitor to develop both an ios and android app. I was having trouble integrating push notifications with my app. I am using the #capacitor/push-notifications package. Is there any direction on how to integrate push notifications with nuxt and capacitor using this package. It would help if someone could walk through this step by step.
This is my nuxt.config.json file
import colors from 'vuetify/es5/util/colors'
export default {
// Disable server-side rendering (https://go.nuxtjs.dev/ssr-mode)
ssr: false,
// Target (https://go.nuxtjs.dev/config-target)
target: 'static',
// Global page headers (https://go.nuxtjs.dev/config-head)
head: {
titleTemplate: '%s - title',
title: 'title',
meta: [
{ charset: 'utf-8' },
{ name: 'viewport', content:"width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0" },
{ hid: 'description', name: 'description', content: '' },
],
link: [{ rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' }],
},
// Global CSS (https://go.nuxtjs.dev/config-css)
css: [],
// Plugins to run before rendering page (https://go.nuxtjs.dev/config-plugins)
plugins: [
'#/plugins/parse',
'#/plugins/axios',
{ src: '~plugins/leaflet.js', src: '~plugins/vuesocial.js', ssr: false },
],
// Auto import components (https://go.nuxtjs.dev/config-components)
components: true,
// Modules for dev and build (recommended) (https://go.nuxtjs.dev/config-modules)
buildModules: [
// https://go.nuxtjs.dev/eslint
// '#nuxtjs/eslint-module',
// https://go.nuxtjs.dev/vuetify
'#nuxtjs/vuetify',
'#nuxtjs/moment',
],
// Modules (https://go.nuxtjs.dev/config-modules)
modules: [
// https://go.nuxtjs.dev/axios
'#nuxtjs/axios',
// https://go.nuxtjs.dev/pwa
'#nuxtjs/pwa',
'#nuxtjs/toast',
//nuxt-leaflet
'nuxt-leaflet',
['nuxt-stripe-module', {publishableKey:'...',}],
],
// Axios module configuration (https://go.nuxtjs.dev/config-axios)
axios: {},
toast: {
position: 'bottom-left',
duration: 3000,
},
// Vuetify module configuration (https://go.nuxtjs.dev/config-vuetify)
vuetify: {
customVariables: ['~/assets/variables.scss'],
theme: {
dark: false,
themes: {
dark: {
primary: colors.blue.darken2,
accent: colors.grey.darken3,
secondary: colors.amber.darken3,
info: colors.teal.lighten1,
warning: colors.amber.base,
error: colors.deepOrange.accent4,
success: colors.green.accent3,
},
},
},
},
// Build Configuration (https://go.nuxtjs.dev/config-build)
build: {
transpile: ['parse', 'axios'],
},
}
This is my capacitor.config.json
{
"appId":"com.undefined.mobile",
"appName":"undefined",
"bundledWebRuntime":false,
"npmClient": "yarn",
"webDir":"dist",
"plugins": {
"SplashScreen": {
"launchShowDuration": 0
}
},
"cordova": {},
"server": {
"iosScheme": "nuxtmobile"
}
}
This is my Podfile
platform :ios, '13.0'
use_frameworks!
# workaround to avoid Xcode caching of Pods that requires
# Product -> Clean Build Folder after new Cordova plugins installed
# Requires CocoaPods 1.6 or newer
install! 'cocoapods', :disable_input_output_paths => true
def capacitor_pods
pod 'Capacitor', :path => '../../node_modules/#capacitor/ios'
pod 'CapacitorCordova', :path => '../../node_modules/#capacitor/ios'
pod 'CapacitorClipboard', :path => '../../node_modules/#capacitor/clipboard'
pod 'CapacitorGeolocation', :path => '../../node_modules/#capacitor/geolocation'
end
target 'App' do
capacitor_pods
# Add your Pods here
end
I want to differentiate code between Android Q and Android R how do I achieve this in Android.bp?
In Android.mk I did something like this
ifeq ($(PLATFORM_VERSION), R)
LOCAL_CFLAGS += -DANDROID_R_AOSP
else
LOCAL_CFLAGS += -DANDROID_Q_AOSP
How to do above code in Android.bp?
Follow the instructions given here.
Replace this part in the my_defaults.go:
if ctx.AConfig().Getenv("SOME_ENV_VAR") == "some_value" {
cflags = append(cflags, "-DCONDITIONAL")
}
With:
if ctx.AConfig().PlatformVersionName() == "R" {
cflags = append(cflags, "-DANDROID_R_AOSP")
} else {
cflags = append(cflags, "-DANDROID_Q_AOSP")
}
Reference: link. In older versions this function was called PlatformVersion() (link), but for Android 9 or higher you should be fine.
GO
You can write a go script with your conditions. Follow
Is there a way to add/remove module in Android.bp?
What is art.go? And why is it considered a way to write conditionals in bp files?
Conditional compilation
If you just want to include a module conditionally you can define many Android.bp modules and include them based on conditions in Android.mk files.
https://android.googlesource.com/platform/build/soong/+/HEAD/docs/best_practices.md#removing-conditionals
soong_config_modules
You will face parsing errors if any of your Android.bp files include libraries not supported by your AOSP.
To fix that you can use soong_config_modules. Note that this is supported only Android 11 R onwards.
Details are given in https://android.googlesource.com/platform/build/soong/+/refs/heads/master/android/soong_config_modules.go
However, I'll give you an example.
Here I am including special libraries when the AOSP is Android 12. Since these libraries might not be present on lower versions, I will not include iot-camera-system.mk in PRODUCT_PACKAGES so it will not be included as a preinstalled app.
What specifically I will achieve with soong_config_modules is removal of parsing errors when these libraries are not present (Android parses all Android.bp files to form a parse tree, it also checks for the existence of their dependencies and build fails when they are not present).
iot-camera-system.mk
# CameraApp Android Application Package
ifeq ($(PLATFORM_VERSION), $(filter $(PLATFORM_VERSION),S 12))
PRODUCT_PACKAGES += CameraApp
SOONG_CONFIG_NAMESPACES += camera
SOONG_CONFIG_camera += camtargets
SOONG_CONFIG_camera_camtargets := newCameraTarget
else
SOONG_CONFIG_NAMESPACES += camera
SOONG_CONFIG_camera += camtargets
SOONG_CONFIG_camera_camtargets := oldCameraTarget
endif
Android.bp
// This introduces the module type camera_cc_defaults
// If target.mk file contained:
//
// SOONG_CONFIG_NAMESPACES += camera
// SOONG_CONFIG_camera += camtargets
// SOONG_CONFIG_camera_camtargets := newCameraTarget
//
// Then our libs would build with static_libs
soong_config_module_type {
name: "camera_cc_defaults",
module_type: "cc_defaults",
config_namespace: "camera",
variables: ["camtargets"],
properties: ["static_libs"],
}
soong_config_string_variable {
name: "camtargets",
values: ["oldCameraTarget", "newCameraTarget"],
}
camera_cc_defaults {
name: "camera_defaults",
soong_config_variables: {
camtargets: {
oldCameraTarget: {
static_libs: [
],
},
newCameraTarget: {
static_libs: [
"androidx.core_core-ktx",
"androidx.fragment_fragment-ktx",
"androidx.navigation_navigation-fragment-ktx",
"androidx.navigation_navigation-ui-ktx",
"androidx.lifecycle_lifecycle-runtime-ktx",
"kotlinx_coroutines",
"kotlinx_coroutines_android",
],
},
},
},
}
android_library {
name: "utils",
defaults: ["camera_defaults"],
manifest: "utils/src/main/AndroidManifest.xml",
platform_apis: true,
srcs: [
"utils/src/main/java/com/example/android/camera/utils/*.kt",
],
resource_dirs: [
"utils/src/main/res/",
],
static_libs: [
"androidx-constraintlayout_constraintlayout",
"androidx.appcompat_appcompat",
"androidx.localbroadcastmanager_localbroadcastmanager",
"com.google.android.material_material",
"androidx.exifinterface_exifinterface",
"androidx.core_core",
"androidx.preference_preference",
"androidx.fragment_fragment",
"androidx.recyclerview_recyclerview",
"androidx.lifecycle_lifecycle-runtime",
"androidx.lifecycle_lifecycle-extensions",
"kotlin-stdlib",
"kotlin-reflect",
"gson-prebuilt-jar",
],
optimize: {
enabled: false,
},
dex_preopt: {
enabled: false,
},
}
android_app {
name: "CameraApp",
defaults: ["camera_defaults"],
manifest: "app/src/main/AndroidManifest.xml",
privileged: true,
platform_apis: true,
certificate: "platform",
srcs: [
"app/src/main/java/com/example/android/camera2/video/*.kt",
"app/src/main/java/com/example/android/camera2/video/fragments/*.kt",
"app/src/main/java/com/example/android/camera2/video/overlay/*.kt",
],
resource_dirs: [
"app/src/main/res/",
],
static_libs: [
"androidx-constraintlayout_constraintlayout",
"androidx.appcompat_appcompat",
"androidx.localbroadcastmanager_localbroadcastmanager",
"com.google.android.material_material",
"androidx.exifinterface_exifinterface",
"androidx.core_core",
"androidx.preference_preference",
"androidx.fragment_fragment",
"androidx.recyclerview_recyclerview",
"androidx.lifecycle_lifecycle-runtime",
"androidx.lifecycle_lifecycle-extensions",
"kotlin-stdlib",
"kotlin-reflect",
"gson-prebuilt-jar",
"utils",
],
optimize: {
enabled: false,
},
dex_preopt: {
enabled: false,
},
}
I've created a project using expo typescript template. Running on iOS and Android. No web.
I then set up path alias in tsconfig.json as follows:
"paths": {
"#models/*": ["./src/models/*"],
"#navigation/*": ["./src/navigation/*"],
"#services/*": ["./src/services/*"],
"#components/*": ["./tsx/components/*"],
"#screens/*": ["./tsx/screens/*"],
"#assets/*": ["./assets/*"]
}
Correspondingly, I configured babel.config.js as follows:
plugins: [
[
'module-resolver',
{
root: ['./'],
alias: {
'#models': path.resolve(path.dirname('.'), 'src/models'),
'#navigation': path.resolve(path.dirname('.'), 'src/navigation'),
'#services': path.resolve(path.dirname('.'), 'src/services'),
'#screens': path.resolve(path.dirname('.'), 'tsx/screens'),
'#components': path.resolve(path.dirname('.'), 'tsx/components'),
'#assets': path.resolve(path.dirname('.'), 'assets'),
}
}
]
]
The above configuration works. App is bundled and runs fine. However the following non-critical errors are emitted during bundle:
transform[stderr]: Could not resolve "/Users/jblues/mobbiz/LOSMobileApp/src/navigation/AppNavigator" in file /Users/jblues/LOSMobileApp/tsx/App.tsx.
transform[stderr]: Could not resolve "/Users/jblues/LOSMobileApp/tsx/components/BottomTabNavigator" in file /Users/jblues/LOSMobileApp/src/navigation/AppNavigator.ts.
transform[stderr]: Could not resolve "/Users/jblues/mobbiz/LOSMobileApp/tsx/screens/Login" in file /Users/jblues/LOSMobileApp/src/navigation/AppNavigator.ts.
. . and so on. Is there something that I can add to my config to prevent these errors?
You are missing the extensions configuration, for example:
extensions: ['.js', '.ts', '.ios.js', '.ios.ts', '.android.js', '.android.ts', '.json'],
This is a babel.config.js file which i have and it works without error. It might be useful for your reference.
const MODULE_RESOLVER = [
'module-resolver',
{
extensions: ['.js', '.ios.js', '.android.js', '.json'],
alias: {
'#Components': './App/Components',
'#Navigation': './App/Navigation',
'#Constants': './App/Constants',
'#Features': './App/Features',
'#Services': './App/Services',
'#Fixtures': './App/Fixtures',
'#Themes': './App/Themes',
'#Config': './App/Config',
'#Sagas': './App/Sagas',
'#Redux': './App/Redux',
'#Types': './App/Types',
'#I18n': './App/I18n',
'#Lib': './App/Lib',
},
},
];
module.exports = {
plugins: [MODULE_RESOLVER],
presets: ['module:metro-react-native-babel-preset'],
env: {
production: {
plugins: ['ignite-ignore-reactotron', MODULE_RESOLVER],
},
},
};
I'm trying to find a simple tutorial: how to make a simple application for android using gbps. The following links were found:
Stack oferflow. The answer to this question has not been
received, although the version of the cbs has already been updated
to 1.11 and the support of android is included.
AndroidApk Item in QBS Documentation. In this case I get warning: '../Application/src/main/AndroidManifest.xml' does not exist.
I unfortunately could not find any new information. I ask for help.
Update:
For Qmake I just create standard widget project like this one:
QT += core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
TARGET = androidtest
TEMPLATE = app
DEFINES += QT_DEPRECATED_WARNINGS
SOURCES += \
main.cpp \
mainwindow.cpp
HEADERS += \
mainwindow.h
FORMS += \
mainwindow.ui
CONFIG += mobility
MOBILITY =
And this is works and builds fine. QtCreator automatically create all necessary files and than run app on my phone
In Qbs I try to make same application. For this reason I have QBS-file:
import qbs
Project {
CppApplication {
name: "helloworld"
Depends {
name: "Qt"
submodules: [
"core",
"widgets"
]
}
Depends { name: "Android.ndk" }
Android.ndk.appStl: "gnustl_shared"
Group {
name: "src"
files: [
"main*.*"
]
}
}
AndroidApk {
name: "helloworld_android"
Depends {name: "helloworld" }
packageName: "com.example.android.helloworld"
}
}
At the end I have Done with HelloWorld product (libhelloworld.so). But first error of "helloworld_android" is a fail at android manifest. This file is undefined. What I should do next?
qmake has some built-in magic when building for Android, like using resources provided by Qt (including a manifest template) and running the android-deployqt tool. None of this is currently done by qbs.
Ok, I think I made it. It's not a good solution but this is work. Resulting APK you can find in "\install-root\$productName$\build\outputs\apk\$productName$-debug.apk
import qbs
import qbs.TextFile
import qbs.Process
import qbs.File
Project {
//Main Application
CppApplication {
name: "helloworld";
Depends {
name: "Qt"
submodules: [
"core",
"widgets"
]
}
Depends { name: "Android.ndk" }
Android.ndk.appStl: "gnustl_shared"
Group {
name: "src"
files: [
"main*.*"
]
}
Group {
qbs.install: true
fileTagsFilter: "dynamiclibrary"
qbs.installPrefix : product.name+"/libs/"+Android.ndk.abi+"/"
}
}
//Preparation
Product {
name: "Prepared2Deploy"
type: "prepared2deploy"
Depends { name: "helloworld" }
Depends { name: "Qt.core" }
Depends { name: "Android.ndk" }
Depends { name: "Android.sdk" }
Rule {
inputsFromDependencies: "installable"
Artifact {
filePath: input.fileName+".json"
fileTags: "prepared2deploy"
}
prepare: {
var cmd = new JavaScriptCommand();
cmd.description = "prepare for androidDeployQt";
cmd.highlight = "install";
cmd.sourceCode = function() {
var outputFile = new TextFile(output.filePath, TextFile.WriteOnly);
outputFile.writeLine("{");
outputFile.writeLine(" \"qt\": \"" + product.Qt.core.binPath.replace(/\/bin$/,"") + "\",");
outputFile.writeLine(" \"sdk\": \"" + product.Android.sdk.sdkDir + "\",");
outputFile.writeLine(" \"sdkBuildToolsRevision\": \"" + product.Android.sdk.buildToolsVersion + "\",");
var ndkDir = product.Android.ndk.ndkDir.replace(/\\/g,"/"); //why sdk ndk get wrong slashes?
outputFile.writeLine(" \"ndk\": \""+ndkDir+"\",");
var toolchain = product.cpp.toolchainPrefix.replace(/-$/,"");
outputFile.writeLine(" \"toolchain-prefix\": \"" + toolchain + "\",");
outputFile.writeLine(" \"tool-prefix\": \"" + toolchain + "\",");
outputFile.writeLine(" \"toolchain-version\": \"4.9\","); //how I can get it ???
outputFile.writeLine(" \"ndk-host\": \"windows-x86_64\","); //how I can get it ???
var abi = product.Android.ndk.abi
outputFile.writeLine(" \"target-architecture\": \""+abi+"\",");
outputFile.writeLine(" \"stdcpp-path\": \""+ndkDir+"/sources/cxx-stl/gnu-libstdc++/4.9/libs/" + //how I can get it ???
abi+"/lib"+product.Android.ndk.appStl+".so\",");
outputFile.writeLine(" \"application-binary\": \""+ input.filePath+"\"");
outputFile.writeLine("}");
outputFile.close();
}
return cmd;
}
}
}
//Deployer
Product {
name: "AndroidDeployQt"
Depends { name: "helloworld" }
id: androidDeployQt
type: "androidDeployQt"
Depends {name: "Qt.core" }
Rule {
inputsFromDependencies: "prepared2deploy"
alwaysRun: true
Artifact {
filePath: "log.txt"
fileTags: "androidDeployQt"
}
prepare: {
var cmd = new JavaScriptCommand();
cmd.description = "androidDeployQt";
cmd.highlight = "install";
cmd.sourceCode = function() {
var logFile = new TextFile(output.filePath, TextFile.WriteOnly);
logFile.writeLine(input.fileName);
var productName = input.fileName.replace(/.so.json$/,"").replace(/^(lib)/,"");
var androidDeployProcess = new Process();
var exitCode = androidDeployProcess.exec(product.Qt.core.binPath+"/androiddeployqt.exe",
[
"--input", input.filePath,
"--output", project.buildDirectory+"/install-root/"+productName,
"--android-platform", "android-25", //???
"--gradle"
])
if (exitCode) {
console.error("Error at androidDeployProcess. Error code: "+exitCode);
console.error(androidDeployProcess.readStdErr());
console.error("FULL_LOG: ");
console.error(androidDeployProcess.readStdOut());
}
logFile.close();
}
return cmd;
}
}
}
}
QBS 1.13, released on February this year (2019) makes deploying an Android application as simple as with qmake. In practice, you don't need to do anything special. For example, I took the contactlist application from the Qt examples and added this QBS file:
import qbs 1.0
Project {
QtGuiApplication {
name: "contactlist"
install: true
files: [
"contactmodel.h",
"contactmodel.cpp",
"main.cpp",
]
Group {
files: [
"*.qml",
"designer/Backend/*.qml",
"designer/Backend/qmldir",
]
fileTags: ["qt.core.resource_data"]
}
Depends { name: "Qt.quick" }
}
}
As you can see, there's nothing specific to Android here. The only trick I'm using is to assign the tag qt.core.resource_data to the QML files in order to have them compiled as resource files — but it's not even required.
With qbs run the application will be run in your connected Android device.