How to make a completely standalone .apk ?

Hi there, I have an ejected app which needs to run on Android in a restricted environment. I need to build an APK which bundles all assets, including JS bundle, image, font and everything into the APK, so that the app doesn’t need to download anything whatsoever on load or at any other point. I.e., it never does OTA updates, never talks to the CDN in the first place, and has everything it needs bundled into the app.

How do I do this? I’m not at all clear from docs: how or whether to use expo publish to do this; how to get it to copy assets from the expo project into the app/src/main/assets directory (or somewhere else if appropriate) as it doesn’t seem to be doing that, despite setting assetBundlePatterns appropriately; how to put assets directory URLs into the manifest; how to make sure it publishes the JS bundle locally; how to use’s publishedUrl to point to the JS bundle; etc.

Anyone done this before? Could you perhaps give some ideas, a walkthrough, or point to some docs? None of the expo docs seem to do this all the way through.


Hmmmm. I just did a completely fresh eject & build, inserting the native components I need, publishing and then gradlew assembleRelease, and this time it seems to have worked as I expected - install the apk via adb and run it with network disabled on the device and it all worked as planned. This time I didn’t upgrade gradle like Android Studio told me to, because I read a few github issues about this, is it possible that was the problem? The expo.gradle build script just wasn’t compatiable with gradle v5+ ?

You should be able to do this by setting app.json to disable updates, and by setting assetBundlePatterns in app.json to include all assets. But… now that the Bare Workflow exists, you really should look at migrating over to that. One of the few major things missing from the Bare Workflow at this point is OTA updates, and you don’t need them. Switch to the bare workflow, and you get all the Expo API’s, and don’t have to workaround disabling the OTA updates.

Hey @llamaluvr, thanks for the reply! I was already disabling updates and using assetBundlePatterns - it just wasn’t doing what it seemed like it should. Like I said above though it actually all worked as I’d expected once I tried doing it without upgrading gradle.

The Bare Workflow isn’t really what we need, as we really like using the Managed Workflow for development, it’s great - we just have a stage at the end where we eject a git clone and apply a bunch of changes so we can insert native modules and generate the APK.

Thanks for getting back to me :grinning:

Ah, gotcha, cool that you have it working with just doing the eject at the end. I started that route, but found I had too many customizations to apply. If you ever end up in a similar boat where you want to keep the ejected bits around, @slorber details some workarounds for continuing to use the Expo client after ejecting here: The hard truth about Managed v. Bare

Hey, cool, I’ll check that all out. Thanks @llamaluvr!