Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Tutorial #1: How to create a mini app in Electrode Native and embed it within an outer Android native app

Tutorial #1: How to create a mini app in Electrode Native and embed it within an outer Android native app

This is the first in a series of posts around Electrode Native.

Was not able to directly find a "hello world" type of guide that demonstrates all the capabilities of Electrode Native - like mini-app packaging and OTA (Over-The-Air updates) in the documentation here - https://www.electrode.io/site/docs/getting_started.html

Hence, decided to write one as part of my journey. These posts are more focused on getting the code running than on explanation of the underlying concepts. For details on the concepts, please refer to the Electrode Native documentation directly.

Note: Electrode Native version at the time of writing this tutorial - v0.45.5

Note: The tutorial assumes a basic knowledge of Android development

  • First, install Electrode Native with the following command

npm install -g electrode-native

  • Then, create a folder for this tutorial say 'ern'. Change directory into the same and run the following command.

ern create-miniapp app1-miniapp where app1-miniapp is the name of the mini app we are creating.

  • Now, start up the Android emulator.

  • Then, change directory into the app1-miniapp folder that has been created and run

ern run-android

yarn login

yarn publish

Assuming the package/version is app1-miniapp@0.0.1

  • Now, let's create a sub-folder to hold the cauldron repository under the ern folder itself, where all the app metadata will be managed. Let's say it's called ern-outer-app-cauldron

  • Now, create the cauldron itself

ern cauldron repo add ern-outer-app <full path to local cauldron repository directory>

  • Then, create a basic hello-world Android app to be used as the outer wrapper native app in Android Studio. Let's assume its named ErnOuterApp

  • Now, add the same to the cauldron

ern cauldron add nativeapp ErnOuterApp:android:0.0.1

  • Now, add the miniapp created earlier to the same cauldron

ern cauldron add miniapps app1-miniapp@0.0.1

  • Then, lets create the container locally using the cauldron metadata.

ern create-container -d ErnOuterApp:android:0.0.1 -p android

  • Change directory to ~/.ern/containergen/out/android. This directory contains the output of the previous command create-container

  • Then, run the build

./gradlew build

allprojects { repositories { google() jcenter() flatDir { dirs 'libs' } } }

  • In the build.gradle file at the app module level, add the following dependency

api(name:'lib-debug',ext:'aar')

  • Continue on to the next step after verifying the build configuration at the link below

https://native.electrode.io/reference/index-1/container-integration#configure-android-build-configuration-versions

    ElectrodeReactContainer.initialize(
        getApplication() /* Application instance */,
        new ElectrodeReactContainer.Config().isReactNativeDeveloperSupport(BuildConfig.DEBUG)
        /* Additional plugins configuration here */);
    Intent intent = new Intent(this, App1MiniappActivity.class);
    startActivity(intent);

Note: The name of the Activity can be found in the AndroidManifest.xml in the mini-app container repository that was published earlier.

  • Now, launch the app in Android Studio and verify that the mini-app launches on the button press.

  • Surprise! The ElectrodeReactContainer does not launch at this point. It fails with the following error.

java.lang.NoClassDefFoundError Failed resolution of lcom/facebook/soloader/SoLoader

  • This is because the core React-Native "native modules" are not part of the mini-app aar itself. They need to be added as a dependency of the outer app explicitly.

  • Hence, had to provide the required react-native modules to the outer android app namely, ErnOuterApp. The steps followed for the same below are a subset of the instructions at this link https://reactnative.dev/docs/integration-with-existing-apps

Steps

  1. Create a new wrapper folder named ernouterappwrapper.

  2. Move the contents of the existing ErnOuterApp android project to an android sub-folder under ernouterappwrapper

  3. At the root directory of the ernouterappwrapper wrapper folder - create a package.json file with the following content

{
  "name": "ernouterappwrapper",
  "version": "0.0.1",
  "private": true,
  "scripts": {
    "start": "yarn react-native start"
  }
}
  1. Then, run the following yarn commands in the ernouterappwrapper folder to add react and react-native packages to the same.
yarn add react-native
yarn add react@16.13.1

The version used for react in the 2nd command is based on a warning that will have been printed for the first command like the following

warning "react-native@x.x.x" has unmet peer dependency "react@y.y.y".

  1. Now, add the React Native dependency in the build.gradle file in the app module in the ErnOuterApp android app
dependencies {
    implementation 'androidx.appcompat:appcompat:1.2.0'
    ...
    
    implementation "com.facebook.react:react-native:+" // From node_modules
    
    api(name:'lib-debug',ext:'aar')
    ...
}
  1. Add an entry for the local React Native directorie to the top-level build.gradle. Be sure to add it to the “allprojects” block, above other maven repositories so that it looks as follows.
allprojects {
    repositories {
        maven {
            // All of React Native (JS, Android binaries) is installed from npm
            url "$rootDir/../node_modules/react-native/android"
        }
        google()
        jcenter()
        flatDir {
            dirs 'libs'
        }
    }
}
  1. Enable native modules autolinking (Ref: https://reactnative.dev/docs/integration-with-existing-apps#enable-native-modules-autolinking)

To use the power of autolinking, we have to apply it a few places. First add the following entry to settings.gradle:

apply from: file("../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesSettingsGradle(settings)

Next add the following entry at the very bottom of the app/build.gradle:

apply from: file("../../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesAppBuildGradle(project)
  1. Finally, modify the following code snippet in the onCreate method of MainActivity to remove the isReactNativeDeveloperSupport setting so that it renders the content of the mini app directly.
    ElectrodeReactContainer.initialize(
        getApplication() /* Application instance */,
        new ElectrodeReactContainer.Config()
        /* Additional plugins configuration here */);
  1. Finally, launch the app in Android Studio and verify that the mini-app launches on the button press as expected.
@hemanth-manoharan
Copy link
Author

hemanth-manoharan commented Jun 19, 2022

Also, needed to add the following dependencies in the app's build.gradle file if we get the error "Cannot resolve symbol 'ViewModelProviders'"
implementation "android.arch.lifecycle:livedata:1.1.0"
implementation "android.arch.lifecycle:viewmodel:1.1.0"
implementation "android.arch.lifecycle:extensions:1.1.0"

@hemanth-manoharan
Copy link
Author

hemanth-manoharan commented Jun 19, 2022

The following property is critical in gradle.properties

android.enableJetifier=true

An alternate way to refer to the aar directly without having to add "libs" folder in repositories tag is as follows.

api files('libs/lib-debug.aar')

Although ReactNative recommends the same. This import is not needed as there is a JSC inside the aar as well. Hence, commenting the same.

// implementation "org.webkit:android-jsc:+"

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment