Assets not working offline in production?

Hi, I am working on an android app using create-react-native-app and my video assets and when the device is connected to the internet but don’t work when the device is not connected to the internet.

I’ve used the require syntax for every asset as they are all local files.
For instance require(‘…/assets/videos/file1.mp4’)

Can anyone explain this? I used the standalone app docs to generate the apk and also tried the ejecting method in both cases the video assets didn’t work offline. Can anyone explain this??

I’ve been struggling with finding the solution for this for days and am not sure where to go to for support.

Hi, you’re correct, during standalone app building we don’t bundle your assets to work offline (on the first run). I think you can use Expo.Asset.downloadAsync() (docs) to cache them after they are downloaded once, so subequent runs should work offline.

Edited much later: Expo supports offline assets.

@ben Is there any other option that I have other than standalone app that will allow my assets to be available offline? I have quite a number of video assets and I’m not sure that caching them is a solution that will work for that much video data. (I have about 10gb of video assets that I would like to be on the device at all times; note: this is for a store kiosk that autoplays content related to the store not for the average user that’s why we have so much video content).

Is this what you meant essentially by using downloadAsync? If not can you show me how this would work with code

Expo.Asset.fromModule(require('./assets/videos/asthma-1.mp4')).downloadAsync().then((res)=>{
  console.log(res);
 // use this response in the video player i.e < Video source={res}>
})

I think in order to preload gigs of files, your best bet is to detach to ExpoKit, where you can control the native Xcode/Android Studio projects. Unfortunately you lose some of the benefits of Expo when you do this. But it would allow you to bundle all of those files in the binary directly.

Edited much later: Expo supports offline assets.

@ben
I tried detaching, it didn’t work offline, let me know if I did something wrong.

Steps I took:

1. In the root of the project: Exp detach
2. In the root of the project: keytool -genkey -v -keystore my-release-key.keystore -alias my-key-alias -keyalg RSA -keysize 2048 -validity 10000
3. mv root_of_project/my-release-key.keystore root_of_projec/android/app/my-release-key.keystore
4.  in ~/.gradle/gradle.properties write: 
> MYAPP_RELEASE_STORE_FILE=my-release-key.keystore
> MYAPP_RELEASE_KEY_ALIAS=my-key-alias
> MYAPP_RELEASE_STORE_PASSWORD=*****
> MYAPP_RELEASE_KEY_PASSWORD=*****

5. add signing config to android/app/build.gradle

6. cd android && ./gradlew assembleRelease

7. take apk and install on the device

Essentially all I did was exp detach and then follow these steps (Publishing to Google Play Store · React Native)

The video assets did not work offline, did I do something wrong?

By the way why does Expo offer (and pay) for hosting for our apps through their cdn anyway, is Expo using the content (i.e videos/images) ?

Edited much later: Expo supports offline assets.


Detaching to ExpoKit gives you access to the native Xcode and Android Studio projects, so now you have the ability to manually roll your assets into the native projects if you want. Expo isn’t doing this for you-- ExpoKit just gives you more control.

Expo doesn’t use your content. We upload assets to a CDN so that users of your app can download new versions of the assets. (this doesn’t really apply to your use case… in a more typical app, “assets” refers mostly to small images and sounds)

@ben this is something I’ve been curious about for a while now. I have a lot of image assets in my app and occasionally it seems like images/icons disappear. I understand that the app is distributed with no assets and that all assets are downloaded the first time the app is opened on a client device. If at some point, the device loses internet access, will that cause all previously downloaded assets to disappear? Do I have to explicitly tell Expo to cache them locally on the device using Expo.Asset.downloadAsync()?

The way I’m doing this is downloading the assets on the first load in App.js, like so:

import React from 'react';
import { Asset, AppLoading } from 'expo';
// ...

import video1 from './assets/videos/1.mp4';
import video2 from './assets/videos/2.mp4';
// ...

export default class App extends React.Component {
  state = {
    ready: false,
  }
  async componentWillMount() {
    await Asset.loadAsync([
      video1,
      video2,
      // ...
    ]);
   this.setState({ ready: true });
  }
  render() {
    if (!this.state.ready) {
      return <AppLoading />;
    }
    return (
      // Your app
    );
  }
}

Once you’ve downloaded them using Asset.loadAsync you can just import them normally everywhere else in your app, and Expo will use the cached versions. Subsequent launches of your app will also use the cached versions instead of downloading them again, as long as they’re up to date.

Hello! One month ago, in Expo SDK 24, we added support for bundling image assets offline. In SDK 25 we are also extending that to apply to other types of assets besides images.

For details, check out the Offline Support guide, including the section about assetBundlePatterns.