EAS cloud build for iOS needs Apple dev ac; PWA support for RN and Expo apps ... etc.

Last updated on 22 Jun 2025
This post is a continuation of the Timestamp Tracker React Native and Expo app work covered in earlier posts.

23:00 20 June 2025
Me: For my Timestamp Tracker React Native and Expo app which I have been discussing with you in previous chats, I now have a web version and an Android app version. I have a Windows 11 PC on which I am doing this development

I believe I can create an iOS build using cloud build like EAS cloud build. But if that is successful, the issue will be how do I run it. I don't have a Mac computer nor an iPhone or other iOS (recent) device. [I have a very old iPod Touch but surely that will not be able to run this app]. Is there some online iPhone emulator where I could try to run the iOS app (if cloud build is successful)?

Gem said EAS cloud build for iOS build is possible.
Regarding testing, while there are some paid iOS emulators, Gem recommended Appetize.io as it has a free trial.

21 June 2025
Me: For my React Native and Expo Timestamp Tracker app, I want to use my Android 256x256 icon (icon.png) as the web app icon too. Can I simply change app.json entry as follows:
    "web": {
      "favicon": "./assets/icon.png"
    },

Gem said yes. But when I used the Android icon for web, it appeared like some large dot. So I downloaded a simple icon from elsewhere, set that up as favicon and now the dev. app browser tab shows that new icon.

Me: About PWA: Create-react-app IIRC sets up a PWA app automatically for React projects created with it. I had presumed that it would be same with React Native and Expo projects created with create-expo-app. Now I think I am wrong in that presumption.

Gem: You are absolutely correct in your revised presumption!

create-react-app is specifically designed for web applications and comes with PWA capabilities (like a service worker and manifest.json) set up by default.

create-expo-app, on the other hand, is primarily focused on creating cross-platform native mobile applications (iOS and Android) using React Native, with web support as an additional target. While Expo does support building for the web, it doesn't automatically configure your project as a full-fledged Progressive Web App (PWA) out of the box in the same way create-react-app does.
...

I had a discussion with Gem on minimal PWA support for my app but eventually I said: Hmm. Quite involved. As of now, I am using only one 256x256 icon for my Android app and a 512x512 icon for my web app I don't want to invest time in creating new icons. Further I see that some amount of service worker code comes into play even for this simple step. I don't want to get into that as of now. So I think I will drop the PWA step.
----

https://appetize.io/pricing -> Free plan offers 30 minutes per month with each session limited to 3 minutes.
Above free plan seems to be very limited but it may be worthwhile to just try it out.

I tried doing an EAS cloud build for iOS. But that tripped up on need for Apple developer account (which is not free)! 

Gem: No, unfortunately, an Apple Developer account required for distributing apps on the App Store (which includes generating release builds with EAS) is not free.

The standard Apple Developer Program costs $99 USD per year (or the equivalent in local currency).

----
I then had a discussion with Gem on it. At end of discussion ...
Me: Got it. It is a nuanced scenario. Very tightly controlled but if one has a Mac computer then one can learn iOS app development and try it out on the simulator on it, and also on personal iOS devices (with such apps expiring in a week). ... OK that's not too bad. ... The barrier is the Mac computer. Not so friendly but one can understand it from a business and tight control point of view (with benefits of good quality and less security issues perhaps).

Then I asked about eas cloud android build - I wanted to try it out.

Gem: You can, and often should, use eas build --platform android --profile production for your Android release builds, even if you've already successfully built locally.

Here's why it's a perfectly valid and often advantageous approach:

  1. Consistency: EAS Build provides a consistent, clean build environment. This reduces "it works on my machine" issues and ensures that your app is built using the same process and dependencies every time, regardless of your local setup.
  2. No Local Android Setup Required: Just like with iOS, if you didn't want to maintain your local Android SDK, Gradle, and Java environment, EAS handles all of that for you in the cloud.
  3. Managed Keystore (Optional but Recommended): EAS can securely manage your Android keystore file and credentials. This means you don't need to manually copy your my-release-key.keystore file or edit gradle.properties/build.gradle for every build. You upload it once securely to EAS, and it handles the signing during the cloud build. This is a significant convenience and security benefit.
    • If you've never used EAS for Android before, it will guide you through setting up your keystore or letting EAS generate and manage one for you.
  4. CI/CD Integration: EAS Build is designed to integrate seamlessly into Continuous Integration/Continuous Deployment (CI/CD) workflows. You can trigger builds automatically on code pushes to your repository.
  5. Artifact Management: All your build artifacts (APKs, AABs, logs) are stored in the EAS dashboard, making it easy to track and download past builds.
  6. Build from app.json and eas.json: When you run eas build, it primarily relies on your app.json (for basic app config) and eas.json (for build profiles, e.g., production settings for Android). It doesn't require you to have the android folder present locally if you're doing a purely cloud-based build.

How to use it (and what to expect):

When you run eas build --platform android --profile production:

  1. EAS CLI will bundle your JS code and assets and upload them to the Expo servers.
  2. It will look at your eas.json for the android.production profile.
  3. If you haven't configured Android signing for EAS yet: It will prompt you about how you want to handle your Android signing key (keystore). You'll typically have options like:
    • Let EAS generate a new key for you (simplest, recommended if you don't have an existing one).
    • Upload your existing my-release-key.keystore file to EAS.
    • Use a local key (less common for cloud builds, as it defeats some of the convenience).
    • Crucially, if you let EAS manage your key, you will no longer need steps 4, 5, and 6 from your local build process.
  4. The build will be queued on an EAS build machine.
  5. Upon successful completion, you'll get a link to download the .apk or .aab (Android App Bundle) from the EAS dashboard. AABs are generally preferred for Google Play Store submissions as they result in smaller downloads for users.
-------------
On my PC:
eas build --platform android --profile production
★ eas-cli@16.12.0 is now available.
To upgrade, run:
npm install -g eas-cli
Proceeding with outdated version.

Resolved "production" environment for the build. Learn more: https://docs.expo.dev/eas/environment-variables/#setting-the-environment-for-your-builds
No environment variables with visibility "Plain text" and "Sensitive" found for the "production" environment on EAS.

✔ Incremented versionCode from 5 to 6.
android.versionCode field in app config is ignored when version source is set to remote, but this value will still be in the manifest available via expo-constants. It's recommended to remove this value from app config.
✔ Using remote Android credentials (Expo server)
√ Generate a new Android Keystore? ... yes
✔ Created keystore

Compressing project files and uploading to EAS Build. Learn more: https://expo.fyi/eas-build-archive
✔ Uploaded to EAS 2s
✔ Computed project fingerprint

Build details: https://expo.dev/accounts/ravisiyer/projects/timestamp-tracker/builds/ec1f657e-db20-4e3b-acdd-1e3a7d22d7ec

Waiting for build to complete.
-----

The build got done successfully on eas. Some extracts from its logs:
Profile: production
Environment: production
Version:  1.2.1 (6) [So eas builds incremented the version no. iOS build attempt followed by Android build]

Build artifact: AAB [Hmm. I used defaults which gave me AAB not APK. Some eas.json config is needed to ask it to generate APK.]
Queue time: 39s
Build time: 7m 18s
Availability: 29 days

No warnings

Gradle build: BUILD SUCCESSFUL in 6m 47s
Application archives:
  - /home/expo/workingdir/build/android/app/build/outputs/bundle/release/app-release.aab (37.7 MB)
-----------
Downloaded the aab file: application-ec1f657e-db20-4e3b-acdd-1e3a7d22d7ec.aab . Windows shows it as 37.6 MB.

This .aab file is suitable to upload to app stores.

Me: My locally built APK is around 57 MB. How is it that the AAB file is only 37 MB?

Gem: This is the core benefit and purpose of the Android App Bundle (AAB)!

Here's the breakdown:

  • APK (Android Package Kit):

    • A single, monolithic file that contains all the necessary code, resources, assets (e.g., images for different screen densities like mdpi, hdpi, xhdpi, xxhdpi, xxxhdpi), and native libraries (for different CPU architectures like armeabi-v7a, arm64-v8a, x86, x86_64).
    • When you build an APK locally, it bundles everything to ensure it can run on virtually any Android device. This leads to a larger file size. Your 57MB APK has all these variants bundled within it.
  • AAB (Android App Bundle):

    • An AAB is a publishing format, not an installation format. It's like a universal container for your app.
    • It contains all the different versions of your app's code and resources, but in a structured way that allows the app store (primarily Google Play) to deliver only what's needed for a specific device.
    • How it works (App Bundle Delivery):
      1. You upload the single AAB to Google Play Console.
      2. When a user downloads your app, Google Play's "Dynamic Delivery" system analyzes the user's device (e.g., screen density, CPU architecture, language).
      3. Google Play then generates a customized APK specifically for that device, containing only the resources and native code that the device actually needs.
      4. This customized APK is significantly smaller than a "universal" APK.
  • Why your AAB is 37 MB and your APK is 57 MB:

    • The 37 MB AAB contains all the various slices (for different densities, architectures) that, when combined into one APK for all devices, would add up to 57 MB.
    • The AAB itself is smaller than a full universal APK because it's optimized for internal storage and parsing by Google Play. It doesn't need to be a fully installable binary. It's more of an archive of components.

In essence, the AAB (37 MB) is a more efficient way to package all your app's variants, allowing the app store to then generate smaller, optimized APKs (which could be, say, 20-30 MB for an individual device) for download.

So, the 37 MB AAB is not directly comparable to the 57 MB APK as an installable file. The 57 MB APK is what a user would download if you provided a single APK that works on all devices, whereas the 37 MB AAB is the source from which Google Play would generate smaller, tailored APKs for users.

Me: I guess I will not be able to test the AAB file by trying to install it on Android emulator or phone?

Gem: You are correct in your guess!

No, you cannot directly test an .aab (Android App Bundle) file by trying to install it on an Android emulator or a physical phone.

As we discussed, an AAB is a publishing format, not an installable format. It's a bundle of all the different components of your app. For an Android device to install an app, it needs a ready-to-install .apk file.

How to Test an AAB (if you want to simulate Play Store behavior):

If you want to test the .aab as it would be delivered by the Play Store, you have two primary options:

  1. Google Play Internal Test Track:

    • This is the recommended way to test your AAB as close to the real user experience as possible.
    • Upload your .aab file to the Google Play Console (you'll need a Google Play Developer account for this, which has a one-time $25 fee).
    • Set up an "Internal Test Track" (or "Internal Testing" as it's now called).
    • Add your own Google accounts (and those of your testers) to this track.
    • Testers will then download the app from the Play Store (just like a regular user) on their devices. Google Play will automatically generate and serve the optimized APKs from your AAB to their specific devices.
    • This allows you to verify that the app behaves correctly when distributed by Google Play, including any optimizations applied by the app bundle.
  2. Bundletool (Command Line Tool):

    • This is a more technical approach for local testing without uploading to Google Play.
    • Google provides a command-line tool called bundletool that can take an .aab file and generate a set of APKs (called "APKs splits" or an "APKs set") that you can then install on a device.
    • You would use bundletool build-apks --bundle=your_app.aab --output=your_app.apks to create an .apks file (which is actually a ZIP archive).
    • Then, to install it, you'd use bundletool install-apks --apks=your_app.apks. Bundletool will automatically select the correct APKs for your connected device and install them.
    • This method is more involved but is useful for deep local testing of the AAB output.
Me: Bundletool is interesting! But you said connected device. Can I not specify what device type APK I want bundletool to create and then get an APK which I can copy over to the device or emulator based on the device type specified?

Gem: You're right that bundletool is used with a "connected device" in its most straightforward install-apks usage. However, it's more powerful than that.

Yes, you absolutely can specify what device type (or more accurately, device configuration) of APKs you want bundletool to create, and then copy those specific APKs over to a device or emulator based on that configuration, without needing the device connected during the build-apks step.

...
=============
=============
19:46 21 June 2025

Ran npm run deploy
Now app icon in deployed GH Pages website uses the new icon.
I did not change app date from 20 Jun 2025 in Info dialog as only the app icon and app.json file has changed which do not really impact the web app's code.

Comments