Static assets in Expo for React Native

I was confused by Expo’s instructions to use expo-asset for embed my static asset files

It refers to a static asset as something that is bundled with your app’s native binary, but then goes on in the same paragraph to say they can be served locally from your project or remotely over the network.

So is an asset that is served remotely still considered a static asset in this context? I’m confused.

Nevertheless, they explain how it works a little further down:

Locally stored assets are served over HTTP in development. They are automatically bundled into your app binary at the build time for production apps and served from disk on a device.

However, it says they are automatically bundled into your app binary at build time, but right after goes on to say that you can use expo-asset to do that.

So is expo-asset a requirement? or is it automatic? Still a little confusing.

Moving on, I attempted to work with it but struggled to know exactly what path I should be using. Another page that I found explained this:

The paths should be relative to the project root so that the file names, whether specified directly or using a directory, will become the resource names.

What does them being relative to the project directory have to do with the the filename becoming the resource name? The phrasing is a little confusing.

I’m a bit susceptible to poor phrasing that misleads a sentence. In this case, what I find myself wanting explained is “The file names should be unique across directories as they will become the unique resource names”. It seems like that’s what the original sentence is trying to make clear (That or something similar), but I’m left not sure if that’s what it’s getting at or if that’s even correct.

I eventually continued on ignoring the docs and trying paths and combinations of approaches until it worked.

What I did…

I added the needed files to my app.config.js:
(I found that the @ alias didn’t work in this file though)

"plugins": [
  ...
  [
    "expo-asset",
    {
      "assets": [
        "./assets/audio/error.mp3",
        "./assets/audio/recording_start.mp3",
        "./assets/audio/recording_stop.mp3",
        "./assets/audio/processing.mp3"
      ]
    },
  ]
  ...
],

I then created a function that loaded all the assets I needed to use. When the app first starts, I run this function.

export async function preloadAudioAssets() {
    try {
        await Promise.all([
            Asset.loadAsync(require("@/assets/audio/recording_start.mp3")),
            Asset.loadAsync(require("@/assets/audio/recording_stop.mp3")),
            Asset.loadAsync(require("@/assets/audio/processing.mp3")),
            Asset.loadAsync(require("@/assets/audio/error.mp3"))
        ]);
        console.log('Audio assets preloaded successfully');
    } catch (error) {
        console.error('Error preloading audio assets:', error);
    }
}

Then, when I want to run one of the sounds, I pass it to my custom playImmediately function (that takes a URI), like this.

export async function playRecordingStartSound(): Promise<void> {
    try {
        await playImmediately( require('@/assets/audio/recording_start.mp3'), 'Listening' );
    } catch (error) {
        console.error('Error playing recording start sound:', error);
    }
}

At this point I still don’t quite know if this is the best approach, but it worked for me on Android.

Note: I’m pretty sure this won’t work unless you rebuild your project. app.config.js changes often affect the build process (likely bundling those binary assets), so I don’t think you can use the sounds after simply an OTA (Over the Air update), as they won’t be sent over.

I don’t think I tested this, but that would be my guess from the docs.

I could be wrong though, drop a comment if you want to confirm for others.

Thanks…

I also dissect and speculate on design and development.
Digging into subtle details and implications, and exploring broad perspectives and potential paradigm shifts.
Check out my conceptual articles on Substack or find my latest below.


You can also find me on Threads, Bluesky, Mastodon, or xTwitter for more diverse posts about ongoing projects.

My latest articles

Storyboarding Immersive Experiences

Storyboarding 360 degree immersive experiences requires a different approach to traditional media…

Staging XR scenes (Keep doing your crappy little drawings)

Some people create beautiful perspective illustrations to visualise and storyboard their virtual reality designs And it’s tempting to think you’re not a strong designer if you’re not doing that too…

Focal point blocking for XR media

Planning out a linear VR experience requires thinking about where the viewers attention might be. Thinking about the focal points…

Designing immersive experiences

In traditional cinema, TV, or even the more modern phone screen, there’s limited screen real-estate. But removing that limitation creates a design problem…

The future is not prompt engineered

Let’s not pretend the importance of prompt engineering is ubiquitous. The most prevalent power of generative AI is in the way it adapts to us, not the other way around…

The typography of dates, times, & filenames

A deep dive into carefully considered date formatting, line length and general typography attributes of filenames…
Bluesky
Threads
Twitter / X
Mastodon
Instagram


Author:

Date:

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.