Apache Cordova allows one to take their pre-existing JavaScript WebApp, bundle it with some additional Cordova JavaScript and native code, and build an app for iOS or Android that can be released as an app in the App Store or Play Store. Cordova works perfectly well with React apps.
For a very simple app, you literally just drop it into Cordova and go, for more complex apps (like ours) there are some changes to be made. See Cordova JavaScript Differences.
We use a very thin Apache Cordova wrapper to encapsulate the We Vote React WebApp. The WeVoteCordova side is so thin, that all it contains is Apache Cordova, some Cordova optional libraries, some Documentation, and the iOS and Android config (and possibly a small amount of native code). All the WebApp's JavaScript and React code, and the libraries that they rely on, remains within the WeVote WebApp, which is wrapped with Cordova for iOS and Android.
This Cordova App has two build targets, iOS and Android, and they each
wrap an identical bundle.js
that is compiled by the We Vote WebApp project.
That's Apple's decision, not ours. So the iOS portions of these instructions assume you have a Mac, so if you use Linux or Windows, you will only be able to develop for Android -- we currently don't have install instructions specifically for Linux or Windows, but we hope that the Android install for Mac will be very similar to what you need.
This section refers to the WebApp, not to WeVoteCordova. These are prerequisite instructions for the WebApp.
To build the bundle.js and associated files in the WebApp that are needed for Cordova, delete the WebApp/build directory, and execute the following one command:
npm run buildCordova
If you haven't done this yet, don't waste your time, go set up the WebApp with current code,
and get it to start up at least once, then build it for Cordova with buildCordova
and then return here when you are done.
If you can't find a file called WebApp/build/bundle.js
on your machine, don't proceed
until you can find it.
As Cordova evolves these instructions have had to change fairly often, so these instructions use the actual directories on one specific computer. You will have to change all file paths in these instructions to match the paths in your setup.
These are the example paths to the WebApp and to the WeVoteCordova, and to the WeVoteCordovaSaveoff (which we will use briefly to merge Cordova supplied code, with our Code from GIT).
/Users/stevepodell/WebstormProjects/WebApp
/Users/stevepodell/WebstormProjects/WeVoteCordova
/Users/stevepodell/WebstormProjects/WeVoteCordovaSaveoff
-
Change to your base "MyProjects" directory which on the example computer is at
/Users/stevepodell/WebstormProject
cd /Users/stevepodell/WebstormProjects
-
Remove any earlier attempts at installation
rm -rf WeVoteCordova rm -rf WeVoteCordovaSaveoff
-
Clone the WeVoteCordova code
git clone https://github.com/wevote/WeVoteCordova.git
-
Rename the directory you just created which contains the latest WeVoteCordova software
stevepodell@Steves-MacBook-Pro-32GB-Oct-2109 WebstormProjects % mv WeVoteCordova WeVoteCordovaSaveoff stevepodell@Steves-MacBook-Pro-32GB-Oct-2109 WebstormProjects %
-
Install the Apache Cordova software. This is the Cordova command line interface (CLI) that is installed globally on your PC or Mac.
First do an uninstall, since any earlier install of the Cordova CLI prior to Version 9, will no longer work. If you have never installed cordova, the uninstall will not do anything (and that is not a problem!).
sudo npm uninstall -g cordova sudo npm install -g cordova
On the example machine that looks like...
stevepodell@Steves-MacBook-Pro WeVoteCordova % sudo npm install -g cordova Password: npm WARN deprecated [email protected]: request has been deprecated, see https://github.com/request/request/issues/3142 /usr/local/bin/cordova -> /usr/local/lib/node_modules/cordova/bin/cordova + [email protected] added 432 packages from 355 contributors in 14.165s stevepodell@Steves-MacBook-Pro WeVoteCordova %
Most version warnings that installing Cordova might have generated, are unlikely to make any difference.
Do not proceed until you are at Cordova V9, or higher.
stevepodell@Steves-MBP-M1-Dec2021 WeVoteCordova % cordova -v 12.0.0 ([email protected]) stevepodell@Steves-MBP-M1-Dec2021 WeVoteCordova %
-
Use
cordova create
to install a new "empty" instance of the WeVoteCordova (with some minimal scaffolding that our copyFromSaveoff script will remove in an upcoming step)This will create a "Hello World" Cordova app, named WeVoteCordova.
stevepodell@Steves-MacBook-Pro-32GB-Oct-2109 WebstormProjects % cordova create WeVoteCordova us.wevote.wevotecordova WeVoteCordova Creating a new cordova project. stevepodell@Steves-MacBook-Pro-32GB-Oct-2109 WebstormProjects %
-
cd the
WeVoteCordovaSaveoff
directory and runnpm install
stevepodell@Steves-MacBook-Pro-32GB-Oct-2109 WebstormProjects % cd WeVoteCordovaSaveoff stevepodell@Steves-MacBook-Pro-32GB-Oct-2109 WeVoteCordovaSaveff % npm install npm WARN [email protected] No repository field. added 84 packages from 65 contributors and audited 84 packages in 2.749s 2 packages are looking for funding run `npm fund` for details found 0 vulnerabilities stevepodell@Steves-MacBook-Pro-32GB-Oct-2109 WeVoteCordovaSaveoff %
Note August 2023: cordova-plugin-screen-orientation needs a temporary patch from cordova-plugin-screen-orientation which is built into the package.json, but should be evaluated and removed as sooon as there is a released fix that supports this plugin on iOS 16.4 and newer.
-
Run the
copyFromSaveoff
script to copy all the source controlled files fromWeVoteCordovaSaveoff
toWeVoteCordova
stevepodell@Steves-MacBook-Pro-32GB-Oct-2109 WeVoteCordovaSaveoff % node copyFromSaveoff __dirname /Users/stevepodell/WebstormProjects/WeVoteCordovaSaveoff Removed scaffolding directory: WeVoteCordova/www ../WeVoteCordova/www Directory created successfully ./.gitignore copied successfully ./.npmignore copied successfully ./copyFromSaveoff.js copied successfully ./buildSymLinks.js copied successfully package-lock.json copied successfully ./www/index.html copied successfully ./config.xml copied successfully README.md copied successfully ./package.json copied successfully Copied the /res dir from ../WeVoteCordovaSaveoff Copied the /docs dir from ../WeVoteCordovaSaveoff stevepodell@Steves-MacBook-Pro-32GB-Oct-2109 WeVoteCordovaSaveoff %
-
cd to the
WeVoteCordova
directory and runnpm install
stevepodell@Steves-MacBook-Pro-32GB-Oct-2109 WeVoteCordovaSaveoff % cd ../WeVoteCordova stevepodell@Steves-MacBook-Pro-32GB-Oct-2109 WeVoteCordova % npm install npm WARN [email protected] No repository field. added 9 packages from 3 contributors and audited 87 packages in 0.868s 2 packages are looking for funding run `npm fund` for details found 0 vulnerabilities stevepodell@Steves-MacBook-Pro-32GB-Oct-2109 WeVoteCordova %
At this point we are done with the
WeVoteCordovaSaveoff
directory, you can delete it whenever you choose to. -
Add the Cordova iOS and Android platforms directories Note: November 18, 2021: Don't use latest for android for now, so we use version 9 instead of version 10 Note: August 2023, need to use ios6.3 or higher to have the app be inspectable with Safari
cordova platform add [email protected] android
Which runs in the terminal like this...
stevepodell@Steves-MacBook-Pro-32GB-Oct-2109 WeVoteCordova % cordova platforms add ios android Using cordova-fetch for cordova-ios@^5.0.0 Adding ios project... Creating Cordova project for the iOS platform: Path: platforms/ios Package: org.wevote.cordova Name: We Vote iOS project created with [email protected] Installing "cordova-plugin-app-version" for ios Installing "cordova-plugin-customurlscheme" for ios Installing "cordova-plugin-device" for ios Installing "cordova-plugin-dialogs" for ios Installing "cordova-plugin-facebook4" for ios Running command: pod install --verbose ... Installing "cordova-plugin-inappbrowser" for ios Installing "cordova-plugin-keyboard" for ios Installing "cordova-plugin-safariviewcontroller" for ios Installing "cordova-plugin-screensize" for ios Installing "cordova-plugin-sign-in-with-apple" for ios Installing "cordova-plugin-splashscreen" for ios Installing "cordova-plugin-statusbar" for ios Installing "cordova-plugin-taptic-engine" for ios Installing "cordova-plugin-whitelist" for ios Installing "cordova-plugin-x-socialsharing" for ios Plugin dependency "[email protected]" already fetched, using that version. Installing "es6-promise-plugin" for ios Installing "cordova-support-android-plugin" for ios Installing "cordova-support-google-services" for ios Installing "cordova.plugins.diagnostic" for ios Dependent plugin "es6-promise-plugin" already installed on ios. Using cordova-fetch for cordova-android Adding android project... Creating Cordova project for the Android platform: Path: platforms/android Package: org.wevote.cordova Name: We_Vote Activity: MainActivity Android target: android-29 Subproject Path: CordovaLib Subproject Path: app Android project created with [email protected] Installing "cordova-plugin-app-version" for android Installing "cordova-plugin-customurlscheme" for android Installing "cordova-plugin-device" for android Installing "cordova-plugin-dialogs" for android Installing "cordova-plugin-facebook4" for android Subproject Path: CordovaLib Subproject Path: app Installing "cordova-plugin-firebase-analytics" for android Plugin dependency "[email protected]" already fetched, using that version. Installing "cordova-support-android-plugin" for android Plugin dependency "[email protected]" already fetched, using that version. Installing "cordova-support-google-services" for android Plugin doesn't support this project's cordova-android version. cordova-android: 9.0.0, failed version requirement: <9.0.0 Skipping 'cordova-support-google-services' for android Subproject Path: CordovaLib Subproject Path: app Installing "cordova-plugin-firebase-messaging" for android Plugin dependency "[email protected]" already fetched, using that version. Dependent plugin "cordova-plugin-firebase-analytics" already installed on android. Plugin dependency "[email protected]" already fetched, using that version. Dependent plugin "cordova-support-android-plugin" already installed on android. Plugin dependency "[email protected]" already fetched, using that version. Installing "cordova-support-google-services" for android Plugin doesn't support this project's cordova-android version. cordova-android: 9.0.0, failed version requirement: <9.0.0 Skipping 'cordova-support-google-services' for android Subproject Path: CordovaLib Subproject Path: app Installing "cordova-plugin-inappbrowser" for android Installing "cordova-plugin-keyboard" for android Installing "cordova-plugin-safariviewcontroller" for android Subproject Path: CordovaLib Subproject Path: app Installing "cordova-plugin-screensize" for android Installing "cordova-plugin-sign-in-with-apple" for android Installing "cordova-plugin-splashscreen" for android Installing "cordova-plugin-statusbar" for android Installing "cordova-plugin-taptic-engine" for android Installing "cordova-plugin-whitelist" for android Installing "cordova-plugin-x-socialsharing" for android Plugin dependency "[email protected]" already fetched, using that version. Installing "es6-promise-plugin" for android Subproject Path: CordovaLib Subproject Path: app Dependent plugin "cordova-support-android-plugin" already installed on android. Installing "cordova-support-google-services" for android Plugin doesn't support this project's cordova-android version. cordova-android: 9.0.0, failed version requirement: <9.0.0 Skipping 'cordova-support-google-services' for android Installing "cordova.plugins.diagnostic" for android Subproject Path: CordovaLib Subproject Path: app Dependent plugin "es6-promise-plugin" already installed on android. stevepodell@Steves-MacBook-Pro-32GB-Oct-2109 WeVoteCordova %
-
ONLY IF the platform install fails with a pod (CocoaPods) error:
Try:
brew update brew upgrade pod repo update
-
ONLY IF the platform install fails on Apple M1 processor (or later) with a "Failed to install 'cordova-plugin-fbsdk':" error
Running command: pod install --verbose Failed to install 'cordova-plugin-fbsdk': Error: pod: Command failed with exit code 1 at ChildProcess.whenDone (/Users/stevepodell/WebstormProjects/WeVoteCordova/platforms/ios/cordova/node_modules/cordova-common/src/superspawn.js:136:25)
try:
sudo arch -arm64 gem install ffi arch -arm64 pod install
-
ONLY IF the platform install fails on Apple M1 processor (or later) with a "Specs satisfying the
FBSDKCoreKit (= 16.0.1)
dependency were found, but they required a higher minimum deployment target." error Manually edit the /Users/stevepodell/WebstormProjects/WeVoteCordova/platforms/ios/Podfile and change theplatform :ios, '11.0'
line toplatform :ios, '12.0'
then runcd platforms/ios arch -arm64 pod install
then
cd ../.. cordova platform add android
-
Run a script to set up the symlinks for iOS and Android and make changes to some build files
In addition to creating the symlinks, this script also makes changes to three Android Gradle (Java/Groovy build scripts) for Firebase Messaging.
node buildSymLinks /Users/stevepodell/WebstormProjects/WebApp/build
These symlinks allow us to access the compiled WebApp and have all the necessary components available for the Cordova builds that need to include our WebApp software.
stevepodell@Steves-MacBook-Pro-32GB-Oct-2109 WeVoteCordova % node buildSymLinks /Users/stevepodell/WebstormProjects/WebApp/build __dirname /Users/stevepodell/WebstormProjects/WeVoteCordova unlink: android index.html unlink: ios index.html rmdir: /Users/stevepodell/WebstormProjects/WeVoteCordova/platforms/android/app/src/main/assets/www/img rmdir: /Users/stevepodell/WebstormProjects/WeVoteCordova/platforms/ios/www/img rmdir: /Users/stevepodell/WebstormProjects/WeVoteCordova/platforms/android/app/src/main/assets/www/css rmdir: /Users/stevepodell/WebstormProjects/WeVoteCordova/platforms/ios/www/css ln ios bundle.js successful ln android css successful ln ios css successful ln android bundle.js successful ln android img successful ln ios img successful ln ios index.html successful ln android index.html successful adding::: android.useAndroidX=true ::: to android/gradle.properties adding::: android.enableJetifier=true ::: to android/gradle.properties adding::: android.enableJetifier=true ::: to android/gradle.properties adding::: classpath 'com.google.gms:google-services:4.3.3' ::: to android/build.gradle adding::: apply plugin: 'com.google.gms.google-services' ::: to android/app/build.gradle adding::: implementation 'com.google.firebase:firebase-analytics:17.5.0' ::: to android/app/build.gradle adding::: implementation 'androidx.browser:browser:1.2.0' ::: to android/app/build.gradle updateGradleProperties changed settings in ./platforms/android/gradle.properties updateProjectBuildGradle added a classpath in ./platforms/android/build.gradle updateAppBuildGradle add an implementation in ./platforms/android/app/build.gradle stevepodell@Steves-MacBook-Pro-32GB-Oct-2109 WeVoteCordova %
If you have installation troubles, you can run
buildSymLinks
as often as you need to, since the script cleans out conflicting links that might already in place, before adding in the new links. -
ONLY IF the install fails with a pod (CocoaPods) error:
Try:
brew update brew upgrade pod repo update
-
Check that cordova requirements have been met (No errors means success)
stevepodell@Steves-MBP-M1-Dec2021 WeVoteCordova % cd www stevepodell@Steves-MBP-M1-Dec2021 www % sudo npm install -g ios-deploy added 1 package, and audited 2 packages in 13s found 0 vulnerabilities stevepodell@Steves-MBP-M1-Dec2021 www % cordova requirements Requirements check results for android: Java JDK: installed 17.0.0 Android SDK: installed true Android target: installed android-Q,android-28,android-27,android-26,android-25,android-24,android-23 Gradle: installed /usr/local/Cellar/gradle/7.2/bin/gradle Requirements check results for ios: Apple macOS: installed darwin Xcode: installed 13.0 ios-deploy: installed 1.10.0 CocoaPods: installed 1.11.0 stevepodell@Steves-MBP-M1-Dec2021 www %
-
Run the WeVoteCordova app from XCode.
In Xcode, Click File/Open and select
/Users/stevepodell/WebstormProjects/WeVoteCordova/platforms/ios/
to open the project in xCode. -
The final step is to start the simulator
Select a simulator that you would like to see the code executing on. In the example below, we have selected the iPhone 11 Pro Max. Then press the Play (Triangular) button, and a minute or two later you should get the WeVoteCordova app running in a simulator.
Note: This screenshot shows the logging with the developer option
LOG_RENDER_EVENTS: true,
set in the webapp.At this point you have a fully working Cordova iOS build.
-
ONLY IF NEEDED: (We hope this step is not necessary.) If the Cordova iOS app loads the html page (White "Loading We Vote" on blue), but crashes in a JQuery regex, and logs
SyntaxError: Invalid regular expression: range out of order in character class
, and never advances to the first React page in the WebApp:In the WebApp, delete
/build /node_modules /package-lock.json
Then (Still in the WebApp!)
npm install npm rebuild node-gyp npm rebuild node-sass npm install npm run prod-singleBundle npm run start-https-singleBundle
At this point you "should" have a fully configured WeVoteCordova app running in your simulator.
The next step is to connect your new WeVoteCordova directory to Git.
This comand only relinks the newly compiled bundle.js and bundle.js.map, and completes quickly
node buildSymLinks /Users/stevepodell/WebstormProjects/WebApp/build bundleOnly
-
On GitHub.com, fork WeVoteCordova to your account.
Navigate to https://github.com/wevote/WeVoteCordova and then click the "Fork" button in the upper right corner.
This will create a new directory on GitHub like ...
https://github.com/SailingSteve/WeVoteCordova.git
-
Execute the following commands from your WeVoteCordova directory on your Mac/PC
Remember to substitute the name of your forked remote for "SailingSteve" in the following commands!
git init git checkout -b develop git add --all git commit --allow-empty -m "initial commit" git remote add upstream https://github.com/wevote/WeVoteCordova.git git remote add origin https://github.com/SailingSteve/WeVoteCordova.git git remote -v git fetch --all git reset --hard upstream/develop git pull upstream develop git push origin develop --force
What it looks like in the terminal:
stevepodell@Steves-MacBook-Pro-32GB-Oct-2109 WeVoteCordova % git init Initialized empty Git repository in /Users/stevepodell/WebstormProjects/WeVoteCordova/.git/ stevepodell@Steves-MacBook-Pro-32GB-Oct-2109 WeVoteCordova % git checkout -b develop Switched to a new branch 'develop' stevepodell@Steves-MacBook-Pro-32GB-Oct-2109 WeVoteCordova % git commit --allow-empty -m "initial commit" [develop (root-commit) 192a375] initial commit stevepodell@Steves-MacBook-Pro-32GB-Oct-2109 WeVoteCordova % git remote add upstream https://github.com/wevote/WeVoteCordova.git stevepodell@Steves-MacBook-Pro-32GB-Oct-2109 WeVoteCordova % git remote add origin https://github.com/SailingSteve/WeVoteCordova.git stevepodell@Steves-MacBook-Pro-32GB-Oct-2109 WeVoteCordova % git remote -v origin https://github.com/SailingSteve/WeVoteCordova.git (fetch) origin https://github.com/SailingSteve/WeVoteCordova.git (push) upstream https://github.com/wevote/WeVoteCordova.git (fetch) upstream https://github.com/wevote/WeVoteCordova.git (push) stevepodell@Steves-MacBook-Pro-32GB-Oct-2109 WeVoteCordova % git fetch --all Fetching upstream remote: Enumerating objects: 31, done. remote: Counting objects: 100% (31/31), done. remote: Compressing objects: 100% (22/22), done. remote: Total 3576 (delta 15), reused 15 (delta 9), pack-reused 3545 Receiving objects: 100% (3576/3576), 87.38 MiB | 20.67 MiB/s, done. Resolving deltas: 100% (1570/1570), done. From https://github.com/wevote/WeVoteCordova * [new branch] develop -> upstream/develop * [new branch] master -> upstream/master * [new branch] revert-138-steveCordovaJuly24-340pm -> upstream/revert-138-steveCordovaJuly24-340pm * [new branch] snyk-fix-e50f77af404aad0d747f31f0eb85c3ba -> upstream/snyk-fix-e50f77af404aad0d747f31f0eb85c3ba Fetching origin remote: Enumerating objects: 47, done. remote: Counting objects: 100% (47/47), done. remote: Compressing objects: 100% (4/4), done. remote: Total 60 (delta 44), reused 46 (delta 43), pack-reused 13 Unpacking objects: 100% (60/60), 1.17 MiB | 4.60 MiB/s, done. From https://github.com/SailingSteve/WeVoteCordova * [new branch] develop -> origin/develop * [new branch] master -> origin/master * [new branch] steveCordovaJul22-835pm -> origin/steveCordovaJul22-835pm * [new branch] steveCordovaJuly15-10am -> origin/steveCordovaJuly15-10am * [new branch] steveCordovaJuly22-1005am -> origin/steveCordovaJuly22-1005am * [new branch] steveCordovaJuly22-541pm -> origin/steveCordovaJuly22-541pm * [new branch] steveCordovaJuly24-1250 -> origin/steveCordovaJuly24-1250 * [new branch] steveCordovaJuly24-235pm -> origin/steveCordovaJuly24-235pm * [new branch] steveCordovaJuly24-340pm -> origin/steveCordovaJuly24-340pm * [new branch] steveCordovaJuly24-noon -> origin/steveCordovaJuly24-noon * [new branch] steveCordovaJune28 -> origin/steveCordovaJune28 * [new branch] steveCordovaJune28-3 -> origin/steveCordovaJune28-3 * [new branch] steveCordovaJusly24150pm -> origin/steveCordovaJusly24150pm * [new branch] steveCordovaRemovePlatformsPluginsJuly14 -> origin/steveCordovaRemovePlatformsPluginsJuly14 * [new branch] steveCordovaUpdateFromScratchJune23 -> origin/steveCordovaUpdateFromScratchJune23 * [new branch] steveCorovaJune29-10 -> origin/steveCorovaJune29-10 * [new branch] steveJul23-135pm -> origin/steveJul23-135pm stevepodell@Steves-MacBook-Pro-32GB-Oct-2109 WeVoteCordova % git reset --hard upstream/develop Updating files: 100% (219/219), done. HEAD is now at b1a1334 Merge pull request #139 from wevote/revert-138-steveCordovaJuly24-340pm stevepodell@Steves-MacBook-Pro-32GB-Oct-2109 WeVoteCordova % git pull upstream develop From https://github.com/wevote/WeVoteCordova * branch develop -> FETCH_HEAD Already up to date. stevepodell@Steves-MacBook-Pro-32GB-Oct-2109 WeVoteCordova %
You will a have different branch list than in this example.
That's it! Cordova iOS Installed from scratch in about an hour.
At this point you can use Git to create branches, use Stash, and use git pull and push to get ready to make pull requests.
You should only have to follow these install from scratch instructions once (unless you delete your WeVoteCordova directory.)
- Confim that buildSymLinks setup we ran initially for the iOS www directory, has set up the Android platform directory properly
If you don't see the symlinks, you can run buildSymLinks again.
stevepodell@Steves-MacBook-Pro-32GB-Oct-2109 WeVoteCordova % ls -la platforms/android/app/src/main/assets/www total 136 drwxr-xr-x 11 stevepodell staff 352 Jun 25 14:52 . drwxr-xr-x 3 stevepodell staff 96 Jun 25 14:01 .. lrwxr-xr-x 1 stevepodell staff 58 Jun 25 14:52 bundle.js -> /Users/stevepodell/WebstormProjects/WebApp/build/bundle.js drwxr-xr-x 6 stevepodell staff 192 Jun 25 14:01 cordova-js-src -rw-r--r-- 1 stevepodell staff 65029 Jun 25 14:01 cordova.js -rw-r--r-- 1 stevepodell staff 3110 Jun 25 14:01 cordova_plugins.js lrwxr-xr-x 1 stevepodell staff 52 Jun 25 14:52 css -> /Users/stevepodell/WebstormProjects/WebApp/build/css lrwxr-xr-x 1 stevepodell staff 52 Jun 25 14:52 img -> /Users/stevepodell/WebstormProjects/WebApp/build/img lrwxr-xr-x 1 stevepodell staff 64 Jun 25 14:52 index.html -> /Users/stevepodell/WebstormProjects/WeVoteCordova/www/index.html drwxr-xr-x 3 stevepodell staff 96 Jun 25 14:01 js drwxr-xr-x 12 stevepodell staff 384 Jun 25 14:01 plugins stevepodell@Steves-MacBook-Pro-32GB-Oct-2109 WeVoteCordova %
You are now done with the Android specific setup.
It is possible to develop for Cordova without IDEs, but you are on your own if you take that path. An important note about both IDEs, is that they are "needed" for running and debugging iOS and Android apps, but there is no need to set up GIT in either of them, all the changes that you make within the IDEs affect files that are in the WeVoteCordova directory that you just made. Checkin any changes from the WeVoteCordova directory with the same tools you use to develope the webapp. Most Cordova changes in this mature app, are version upgrades of included packages, and version changes for the apps we deploy in the Apple iOS App Store and the Google Android Play Store.
Install Apple Xcode from the macOS App Store, you will need a Mac for the iOS part of this project, and a Mac will also be fine for Android development.
For Android, install the Android Studio (a free IDE, from JetBrains, the makers of PyCharm, WebStorm, IntelliJ, etc.)
-
Install Xcode
The easiest way to install Xcode is via the Mac App Store. The Xcode.app download is approximately 10gb in size.
-
Opening the project with Xcode -- Open xcworkspace, not xcodeproj directories (or else)
Be sure to open
/Users/your-username/MyProjects/WeVoteCordova/platforms/ios/WeVoteCordova.xcworkspace
each time, if you forget to do this portions of the app will not be in your build, since you won't have referenced the cocopods (a dependency manger, that pulls in some iOS specific libraries.)Be sure not to open
with Xcode, and don't pick a choice from the history pane ("Don't click these!") in the Welcome to Xcode dialog. The history unfortunately will contain references to/Users/your-username/MyProjects/WeVoteCordova/platforms/ios/WeVoteCordova.xcodeproj
.xcodeproj
and.xcworkspace
files, but the descriptions are too short to tell the difference. (Hint: When that Welcome dialog is displayed, it is possible to open the xcworkspace from the File/"Open Recent" menu, just be sure to open the xcworkspace.)And in the "Welcome to Xcode" dialog, again, don't pick anything from the history list (those are all xcodeproj files), you have to click "Open another project..." and navigate to the 'WeVoteReactNative.xcworkspace' item (which is actually a directory).
Clean Build:
You probably will run into the need to "Clean Build Folder". To do this in XCode, go to the Product menu, hold down the Option button (on your Mac keyboard) and select "Clean Build Folder", after it completes (about 10 seconds), press the triangular Run (Play) button do to a full rebuild
Browsers are single threaded, JavaScript on browsers is also single threaded, but JavaScript running in Cordova is multithreaded. "JavaScript in the WebView does not run on the UI thread, it also has other threads to execute the html component and carry out CSS transitions." This can cause some confusion when debugging Cordova for the first time.
You don't have to actually use Safari for Mac for anything, but launching its remote debugger. You can see it opened on its smallest default page in the picture above, it just has to be running, so you can get to that "Develop" menu. Once you open the "We Vote Cordova" page that is currently being displayed, in the picture it is the "Welcome to We Vote" page. One of the symptoms, of this otherwise good thing (multiple-threads) is tha console.log lines in the resolution of promises often don't make it to the log.
It is easy to get the Safari debugger working, and over time Apple has added almost all the features we are used to from the Chrome Devtools Debugger.
- Enable debugging in Safari, see this article
- Build your 'compiled' javascript app file
bundle.js
, on my Mac it is atbuild/bundle.js
. This file needs to be symlinked into your www directory (see the section on symlinks above).- On my Mac in WebStorm, I have a Gulp task that has a target "build", when I press the play button for that task, it builds the bundle.js in 20 seconds (Two seconds to gather all the js scripts together, and 18 seconds to recompile sass).
- Press the play button in Xcode, which should start the Simulator, load, and then start the WeVote WebApp.
- In Safari open Develop/Simulator/WeVoteCordova/WeVote and the Safari Web Inspector appears.
In Apache Cordova, all the real app code is in that bundle.js
we make in the WebApp setup, but there are some code
changes in the WebApp that are necessary to support cordova.
Cordova JavaScript Differences.
If you are developing a Cordova specific feature, that requires access to the API server running on your Mac, while not using the simulator, some extra setup is required to allow access to your Mac's localhost.
Testing with a Physical Phone and a localhost WeVote API Server
Start recording:
stevepodell@Steves-MacBook-Pro www % xcrun simctl io booted recordVideo myVideo.mov
End the recording with Ctrl-c in the terminal window.
Just change myVideo.mov to a unique name of your choosing, and run the command to make a recording.
It's free! It is based on Intellij, so if you have used PyCharm, WebStorm, RubyMine, or IntelliJ it should be instantly familar.
https://developer.android.com/studio/index.html
August 2023: Needed to update to the latest IDE "Giraffe"
then brew upgrade gradle
from 4.2 to 8.2.1
then in Settings > Build, Execution, Deployment > Build Tools > Gradle
in the Use Gradle From (Specified Location) I had to use /opt/homebrew/Cellar/gradle/8.2.1/libexec
The key was /opt/homebrew/Cellar/gradle/8.2.1/libexec NOT /opt/homebrew/Cellar/gradle/8.2.1/bin
-
In Android Studio run File/'Sync Project With Gradle Files'
-
I needed to upgrade to the latest Java JDK which I got from Amazon, since Oracle wanted too much info, https://docs.aws.amazon.com/corretto/latest/corretto-17-ug/downloads-list.html
-
Then in Android Studio at Preferences | Build, Execution, Deployment | Build Tools | Gradle Change the Gradle JDK to version 17 and Apply
-
On November 16, 2021, I had to set the gradle directory to a place in the library path
-
Confirm the relevant paths
stevepodell@Steves-MacBook-Pro-32GB-Oct-2109 WeVoteCordova % vi ~/.bash_profile
export ANDROID_HOME=/Users/stevepodell/Library/Android/sdk export ANDROID_SDK_ROOT=/Users/stevepodell/Library/Android/sdk export PATH=$PATH:$ANDROID_HOME/tools export PATH=$PATH:$ANDROID_HOME/build-tools/33.0.0 export PATH=$PATH:$ANDROID_HOME/platform-tools export PATH=$PATH:$ANDROID_SDK_ROOT/platform-tools/ export PATH=$PATH:$ANDROID_SDK_ROOT/cmdline-tools/latest/bin/ export PATH=$PATH:$ANDROID_SDK_ROOT/emulator/ export PATH="/usr/local/opt/node@6/bin:$PATH" export GRADLE_USER_HOME=/opt/homebrew/bin/gradle export GRADLE_HOME=/opt/homebrew/bin/gradle
-
If you made any changes, source the edited bash_profile (Can't hurt in any case) stevepodell@Steves-MacBook-Pro-32GB-Oct-2109 WeVoteCordova % source ~/.bash_profile
-
Some changes (JAVA_HOME) might be in the z shell config
stevepodell@StevesM1Dec2021 android % vim ~/.zshrc
export JAVA_HOME=/Library/Java/JavaVirtualMachines/amazon-corretto-17.jdk/Contents/Home
stevepodell@StevesM1Dec2021 android % source ~/.zshrc
-
You may need to use the SDK installer in AndroidStudio to download/update to the latest SDK (Can take 10 minutes)
-
Download and install Android Studio
Click "ok" to downloading and installing any jars or packages that the installer recommends.
-
On the welcome screen, select "open an existing project"
The existing project is the WeVoteCordova project that you have already pulled down from git. Our Android project is contained within the WeVoteCordova project. In the open (file selection) dialog, navigate to your WeVoteCordova working directory, then to platforms, then to android and press Open.
/Users/your-username/MyProjects/WeVoteCordova/platforms/android
-
At that point there will be a series of updates and "syncing" options, where you should follow all the default choices.
-
You will probably be prompted to upgrade Gradle, Genymotion, Cordova plugins, etc.
Update them all before continuing. Restart as recommended.
Don't worry about setting a version control root or remote, all changes that you want to get into git are in the WeVoteCordova enclosing project -- That is where you should do your pull requests, not within Android Studio.
-
Android (Java) projects need a Run configuration to start
Accept the default settings and press "OK"
You might see a warning: "WARNING: Configuration 'compile' is obsolete and has been replaced with 'implementation' and 'api'.", but it is safe to ignore
-
If you get an error relating to accepting the Android SDK license
Run the
sdkmanager
and accept all the licenses (feel free to read them first)stevepodell@Steves-MacBook-Pro-32GB-Oct-2109 android % pwd /Users/stevepodell/WebstormProjects/WeVoteCordova/platforms/android stevepodell@Steves-MacBook-Pro-32GB-Oct-2109 android % cd /Users/stevepodell/Library/Android/sdk/tools/bin stevepodell@Steves-MacBook-Pro-32GB-Oct-2109 bin % ./sdkmanager --licenses Warning: File /Users/stevepodell/.android/repositories.cfg could not be loaded. 7 of 7 SDK package licenses not accepted. 100% Computing updates... Review licenses that have not been accepted (y/N)? y ... 10.8 Open Source Software. In the event Open Source software is included with Evaluation Software, such Open Source software is licensed pursuant to the applicable Open Source software license agreement identified in the Open Source software comments in the applicable source code file(s) and/or file header as indicated in the Evaluation Software. Additional detail may be available (where applicable) in the accompanying on-line documentation. With respect to the Open Source software, nothing in this Agreement limits any rights under, or grants rights that supersede, the terms of any applicable Open Source software license agreement. --------------------------------------- Accept? (y/N): y All SDK package licenses accepted stevepodell@Steves-MacBook-Pro-32GB-Oct-2109 bin %
Then run File/Sync Project with Gradle Files and you "should" see the following success message in the Sync status pane in the lower right corner of the IDE.
KotlinDslScriptsParameter(correlationId=102692066094524, scriptFiles=[]) => StandardKotlinDslScriptsModel(scripts=[], commonModel=CommonKotlinDslScriptModel(classPath=[], sourcePath=[], implicitImports=[]), dehydratedScriptModels={}) - took 0.0 secs Checking the license for package Android SDK Platform 28 in /Users/stevepodell/Library/Android/sdk/licenses License for package Android SDK Platform 28 accepted. Preparing "Install Android SDK Platform 28 (revision: 6)". "Install Android SDK Platform 28 (revision: 6)" ready. Installing Android SDK Platform 28 in /Users/stevepodell/Library/Android/sdk/platforms/android-28 "Install Android SDK Platform 28 (revision: 6)" complete. "Install Android SDK Platform 28 (revision: 6)" finished. CONFIGURE SUCCESSFUL in 24s
-
If you get a red symbol on your run icon, and a "No default run configuration" error or warning
try re-installing npm globally
stevepodell@Steves-MacBook-Pro-32GB-Oct-2109 WeVoteCordova % sudo npm install -g npm
-
You will then need to download some simulator Virtual Devices to test with. Go to Tools/AVD Manager
It is possible that the list will be empty, and you have to use to "+ Create Virtual device..." button to add them from scratch, start with at least one.
If your list contains only entries that require downloading, download those that you can, some will have API versions that need to be increased to the minimum that is configured. These simulators are huge (1GB) and contain most of the commercial boot image for the phone that you will be simulating.
you probably will need to come back here later to add more, but at least get one downloaded, so you can do a test run in the Simulator. -
Invalidate Caches and restart
Go to File/"Invalidate Caches / Restart" and choose the option to restart.
-
The gradle run that is automatically launched failed for me, so I had to upgrade the Android Gradle plugin
Gradle is a build tool for Java, that serves the same purpose as Ant, or Make, or Webpack.
Since the Gradle version that came with Android Studio was
6.1.1
, edited android/build.gradle to load version 4.00 instead of the version3.0.0
that came preinstalled.After making that edit, simply click File/"Sync Project with Gradle Files" which forces a reload of the Android Gradle plugin, and rebuilds the app.
-
Press the green "play" button to attempt to start running
If you have an Android phone or tablet, you can plug it in via USB. Make sure debugging via tethering is enabled (google this. it varies between phone manufacturers). If it is enabled you will see the name of the connected device (Motorola Moto G, in this example) in the dialog. Press "OK", and the CordovaApp should start right up on the phone.
That it! you should have a basic Android Cordova app running in the simulator!
Just like iOS! Use the chrome://inspect/#devices in Chrome, but no need to start the remotedebug_ios_webkit_adapter server, something in Android or Android Studio has done that for us automatically.
Make sure the custom scheme URL Type is still setup in Xcode
Moving the spinner upwards on the iOS Splash screen and changing it from grey to white: Manual step required
In the non-source controlled file /Users/your-username/MyProjects/WeVoteCordova/platforms/ios/WeVoteCordova/Plugins/cordova-plugin-splashscreen/CDVSplashScreen.m
change the line at about line 102:
_activityView.center = CGPointMake(parentView.bounds.size.width / 2, parentView.bounds.size.height / 1 );
to
_activityView.center = CGPointMake(parentView.bounds.size.width / 2, parentView.bounds.size.height * 1 / 5 );
The Cordova project used to have all configuration for platforms, plugins installed, and plugin variables stored in their proprietary config.xml. The WeVoteCordova/config.xml
file is
parsed at build time and rewritten to WeVoteCordova/platforms/ios/WeVoteCordova/config.xml and is used somewhere in Android.
In 2019, it appears that Cordova started using WeVoteCordova/package.json as the
authoritative source of versions of the platform components and plugins
that are used to build the app. For pulling in libraries (plugins, platforms and Cordova core components)Cordova first looks in packages.json, then in config.xml, and
finally it will load plugins that are not configured, but are present in the
plugins directories: WeVoteCordova/platforms/ios/WeVoteCordova/Plugins
and WeVoteCordova/platforms/android/app/src/main/assets/www/plugins
and
WeVoteCordova/Plugins
The safest way to remove a plugin is, for example cordova plugin remove cordova-plugin-foo
which adjusts all the
configuration files, and physically removes the plugin code. cordova plugin add cordova-plugin-foo --save
will add it back in,
and might add the configuration for the plugin version in WeVoteCordova/config.xml
. If it doesn't you
can add it into the WeVoteCordova/config.xml
manually, or just not worry about it and have
the code version picked up from package.json
Running ... (Note: August 2023: Need to use a minimum of ios 6.3 see apache/cordova-ios#1301)
cordova platform remove ios android
cordova platform add [email protected] android
will remove everything from the platforms directory, and rebuild all the config files in the platforms directory, but will also remove all the manual configuration and symlinks that you add. This is a powerful last resort if all else is going wrong.
The WeVote web app that has been developed as described below, can be tested on your Mac. But do not check in these library changes, they are only needed for testing, and the Cordova build without these changes runs on a M1 processor (or later) Mac.
stevepodell@Steves-MBP-M1-Dec2021 WeVoteCordova % brew install cocoapods
stevepodell@Steves-MBP-M1-Dec2021 WeVoteCordova % cd platforms/ios
stevepodell@Steves-MBP-M1-Dec2021 ios % pod install
Analyzing dependencies
Downloading dependencies
Installing FBAEMKit (11.1.0)
Installing FBSDKCoreKit (11.1.0)
Installing FBSDKCoreKit_Basics (11.1.0)
Installing FBSDKLoginKit (11.1.0)
Installing FBSDKShareKit (11.1.0)
Generating Pods project
Integrating client project
Pod installation complete! There are 3 dependencies from the Podfile and 5 total pods installed.
[!] The `We Vote [Debug]` target overrides the `ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES` build setting defined in `Pods/Target Support Files/Pods-We Vote/Pods-We Vote.debug.xcconfig'. This can lead to problems with the CocoaPods installation
- Use the `$(inherited)` flag, or
- Remove the build settings from the target.
[!] The `We Vote [Debug]` target overrides the `LD_RUNPATH_SEARCH_PATHS` build setting defined in `Pods/Target Support Files/Pods-We Vote/Pods-We Vote.debug.xcconfig'. This can lead to problems with the CocoaPods installation
- Use the `$(inherited)` flag, or
- Remove the build settings from the target.
[!] The `We Vote [Release]` target overrides the `ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES` build setting defined in `Pods/Target Support Files/Pods-We Vote/Pods-We Vote.release.xcconfig'. This can lead to problems with the CocoaPods installation
- Use the `$(inherited)` flag, or
- Remove the build settings from the target.
[!] The `We Vote [Release]` target overrides the `LD_RUNPATH_SEARCH_PATHS` build setting defined in `Pods/Target Support Files/Pods-We Vote/Pods-We Vote.release.xcconfig'. This can lead to problems with the CocoaPods installation
- Use the `$(inherited)` flag, or
- Remove the build settings from the target.
stevepodell@Steves-MBP-M1-Dec2021 ios %
I think you will need access to WeVote's [email protected] account to proceed
If you get an error like
The operation couldn’t be completed. Unable to log in with account '[email protected]'. The login details for account '[email protected]' were rejected.
First try to satisfy this requirement with your personal iCloud Apple email address and signin , but if that doesn't work you will need to talk to Dale and get a password for [email protected], and then add it to your Xcodes's "Preferences" -> "Accounts" page
If you get an error like:Provisioning profile "iOS Team Provisioning Profile: org.wevote.cordova" doesn't include the currently selected device "Steve's MBP M1 Dec2021" (identifier 00006001-001451D92102801E).
I had to go to Signing and Capabilities
and add my latest Mac's name.
At this point there are problems compiling the Google notifications code. Calls to the code are disabled if isIOSAppOnMac(), but the binary libraries need to be removed if compiling on Apple Silicon at this time.
In package.json, remove the following lines (DON"T CHECK IN THESE CHANGES):
From "devDependencies":
"cordova-plugin-firebase-analytics": "^6.1.0",
"cordova-plugin-firebase-messaging": "^6.1.0",
From "dependencies":
"cordova-support-google-services": "^1.4.1",
From "cordova": { "plugins":
"cordova-plugin-firebase-messaging": {
"ANDROID_FIREBASE_MESSAGING_VERSION": "21.0.0",
"ANDROIDX_CORE_VERSION": "1.3.+",
"IOS_FIREBASE_MESSAGING_VERSION": "~> 6.31.0",
"IOS_FIREBASE_POD_VERSION": "~> 8.8.0"
},
"cordova-plugin-firebase-analytics": {
"IOS_FIREBASE_POD_VERSION": "~> 8.8.0",
"ANDROID_FIREBASE_CRASHLYTICS_VERSION": "19.0.+",
"ANALYTICS_COLLECTION_ENABLED": "true",
"AUTOMATIC_SCREEN_REPORTING_ENABLED": "true"
},
And it should show up running in a container on the desktop (like a native app, which it kind of is)
stevepodellsilicon@Steves-arm64-Mac WeVoteCordova % cordova platforms remove ios android stevepodellsilicon@Steves-arm64-Mac WeVoteCordova % cordova platform add ios android stevepodellsilicon@Steves-arm64-Mac WeVoteCordova % node buildSymLinks /Users/stevepodellsilicon/WebstormProjects/WebApp/build
This happens too often, here are some steps that usually resolve it.
- Close the "Emulator" window (hopefully, but not always ending the emulator session.) This step is sometimes all it takes.
- Open the device in the Device Manager, and "Change" the named device settings, "Edit the device", and make sure the Memory has not been reset to MB. Set the memory to a very big number like "1 TB" (we don't have a native app, so this does not matter). You will also probably have to reset the "Default Skin" to match the device if it says pull-down says "No Skin".
- Delete any lock files in the emulator directory:
WeVoteCordova % rm ~/.android/avd/Galaxy_Z_Fold_3_Samsung_API_33.avd/*lock
- Sometimes you have to exit out of Android Studio, and restart it.
- Sometimes an old setup, or one that references an old skin, needs to be deleted and recreated.
Setting up your Computer for Android Development
Cordova JavaScript Differences