In my project I've achieved this by creating a build variant that bundles the generated RN code within the APK.
Generating the bundle.js
Using wget I grab the RN code from the Node.JS local server and save it as bundle.js:
wget "http://127.0.0.1:8081/index.android.bundle?platform=android&dev=false" -O bundle.js
Adding bundle.js to the project
I add the bundle.js file to assets/ dir.
Creating a build variant that points RN to the file
I don;t wanna manually change my code whenever I wanna switch between local (bundle.js) and live versions. So I've created a build variant for this case.
There is an extensive tutorial on build variants here, so I'll just go over the cruicial details only.
In my build.gradle, under the android node, I've added:
productFlavors {
bundled {
buildConfigField 'boolean', 'BUNDLED', 'true'
buildConfigField 'String', 'DEV_HOST', "null"
}
}
This automatically generates BuildConfig.java (more about this here):
public final class BuildConfig {
public static final boolean DEBUG = Boolean.parseBoolean("true");
public static final String APPLICATION_ID = "....";
public static final String BUILD_TYPE = "debug";
public static final String FLAVOR = "bundled";
public static final int VERSION_CODE = ...;
public static final String VERSION_NAME = ...;
// Fields from product flavor: bundled
public static final boolean BUNDLED = true;
}
Pointing RN to bundle.js
So now I fire up RN based on my build variant:
boolean bundled = BuildConfig.BUNDLED;
mReactInstanceManager = ReactInstanceManager.builder()
.setApplication(getApplication())
.setBundleAssetName("bundle.js")
.setJSMainModuleName("index.android")
.setJSBundleFile(bundled ? "assets://bundle.js" : null)
.addPackage(new MainReactPackage(false))
.addPackage(mInnerItemReactPackage)
.setUseDeveloperSupport(bundled ? false : ConfigSupplier.isDebuggable())
.setInitialLifecycleState(LifecycleState.RESUMED)
.build();
Generating the APK
I choose the correct build variant from the Build Variants screen:

And then proceed as usual by clicking Build -> Build APK.
I might add a more detailed blog post later.