Integrating ViroReact with React Native (no Expo)

Below are the instructions you should follow when integrating ViroReact into your React Native app if you are not using Expo.

Linking (You must do this - we do not support auto-linking)

If you're unsure about which file to edit or where to put specified the lines, we have added links to how this is done in our starter-kit repo.

iOS Linking (You must do this - we do not yet support auto-linking)

❗️

iOS Simulators are currently not supported

AR does not work on iOS simulators. If you are getting an error that looks like: ARWorldTrackingConfiguration setAutoFocusEnabled: unrecognised, that is expected. There is not any camera support for the iOS Simulator.

See running-on-device in the official react-native docs.

1. Add the following lines to your ios/Podfile below use_react_native!(:path => config["reactNativePath"]):

pod 'ViroReact', :path => '../node_modules/@reactvision/react-viro/ios/'
pod 'ViroKit', :path => '../node_modules/@reactvision/react-viro/ios/dist/ViroRenderer/'

See this example

2. Install the iOS native pods by running:

$ npx pod-install

or inside the ios directory...

$ pod install

3. If you are going to be doing any AR then you will need to request permissions for using the camera in the ios/APP_NAME/info.plist by adding the following:

    <key>NSCameraUsageDescription</key>
    <string>The camera is needed for AR functionality</string>

The string can be more appropriate to the needs of your app.

See an example here.

4. You're done! You can now run npx react-native ios.

Remember, if you are using AR, you need to run on a real device.

Android Linking (You must do this - we do not yet support auto-linking)

❗️

We currently do not support the Android Emulator

We have this support in our backlog and will address it soon.

1. In your android/build.gradle Bump the minimum SDK version to at least 24, and the gradle plugin to at least 4.1.1:

buildscript{
  ext{
    ...
    minSdkVersion = 24
    ...
  }
  ...
  dependencies{
    classpath('com.android.tools.build:gradle:4.1.1')
  }
}

See an example here.

2. In your android/app/build.gradle Add the following lines to the dependencies section:

dependencies {
  implementation fileTree(dir: "libs", include: ["*.jar"])
  //noinspection GradleDynamicVersion

  implementation "com.facebook.react:react-native:+"  // From node_modules

  // Add these lines
  implementation project(':gvr_common')
  implementation project(':arcore_client')
  implementation project(path: ':react_viro')
  implementation project(path: ':viro_renderer')
  implementation 'androidx.media3:media3-exoplayer:1.1.1'
  implementation 'androidx.media3:media3-exoplayer-dash:1.1.1'
  implementation 'androidx.media3:media3-exoplayer-hls:1.1.1'
  implementation 'androidx.media3:media3-exoplayer-smoothstreaming:1.1.1'
  implementation 'com.google.protobuf.nano:protobuf-javanano:3.1.0'

See an example here.

3. In your android/settings.gradle Add the following lines to the end:

include ':react_viro', ':arcore_client', ':gvr_common', ':viro_renderer'
project(':arcore_client').projectDir = new File('../node_modules/@reactvision/react-viro/android/arcore_client')
project(':gvr_common').projectDir = new File('../node_modules/@reactvision/react-viro/android/gvr_common')
project(':viro_renderer').projectDir = new File('../node_modules/@reactvision/react-viro/android/viro_renderer')
project(':react_viro').projectDir = new File('../node_modules/@reactvision/react-viro/android/react_viro')

See an example here.

4. In your android/gradle/wrapper/gradle-wrapper.properties set the distributionUrl to at least 6.5:

distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-bin.zip

See an example here.

5. Now add the Viro package to your MainApplication:

📘

Viro works with both Kotlin and Java.

If your React Native application has a android/app/src/main/java/.../MainApplication.kt file, follow ONLY the instructions for Kotlin.

If your React Native application has a android/app/src/main/java/.../MainApplication.java file, follow ONLY the instructions for Java.

Kotlin

Add the following line to the end of the import list:

import com.viromedia.bridge.ReactViroPackage

Add the imported package inside the getPackages method:

override fun getPackages(): List<ReactPackage> =
  PackageList(this).packages.apply {
    // Packages that cannot be autolinked yet can be added manually here, for example:
    // add(MyReactNativePackage())

    add(ReactViroPackage(ReactViroPackage.ViroPlatform.valueOf("AR")))
  }

  override fun getJSMainModuleName(): String = "index"
  override fun getUseDeveloperSupport(): Boolean = BuildConfig.DEBUG
  override val isNewArchEnabled: Boolean = BuildConfig.IS_NEW_ARCHITECTURE_ENABLED
  override val isHermesEnabled: Boolean = BuildConfig.IS_HERMES_ENABLED
}

You can replace the string AR with one of the following depending on your needs: GVR, OVR_MOBILE, AR.

See a Kotlin example here.

Java

Add the following line to the end of the import list:

import com.viromedia.bridge.ReactViroPackage;

Add the imported package inside the getPackages method:

@Override
protected List<ReactPackage> getPackages() {
  @SuppressWarnings("UnnecessaryLocalVariable")
  List<ReactPackage> packages = new PackageList(this).getPackages();

  // Add this line
  packages.add(new ReactViroPackage(ReactViroPackage.ViroPlatform.valueOf("AR")));

  return packages;
}

See a Java example here.

You can replace the string AR with one of the following depending on your needs: GVR, OVR_MOBILE, AR.

6. In your android/app/src/main/AndroidManifest.xml:

For AR

Ensure the <manifest> has the tools namespace schema:

<manifest ... xmlns:tools="http://schemas.android.com/tools" ...>

Add the following line to the <application> node, this enables ARCore:

<meta-data android:name="com.google.ar.core" android:value="optional" />

Note: If you want to restrict your app to ARCore-only devices, set the android:value to "required"

Add the camera permission to the <manifest> node below other permissions:

<uses-permission android:name="android.permission.CAMERA" />

There are quite a few other camera-related permissions and features you might also want to specify, depending on your app:

<!-- You may need these if doing any screen recording from within the app -->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<!-- Other camera related features -->
<uses-feature android:name="android.hardware.camera" />
<uses-feature android:name="android.hardware.camera.autofocus" android:required="false" tools:replace="required"/>
<!-- Specifying OpenGL verison or requirements -->
<uses-feature android:glEsVersion="0x00030000" android:required="false" tools:node="remove" tools:replace="required" />
<!-- Usage of accelerometer and gyroscope -->
<uses-feature android:name="android.hardware.sensor.accelerometer" android:required="false" tools:replace="required" />
<uses-feature android:name="android.hardware.sensor.gyroscope" android:required="false" tools:replace="required" />
For VR

If your app supports Cardboard or Daydream, you should add them as a category to the intent-filter in your activity:

<intent-filter>
    <action android:name="android.intent.action.MAIN" />
    <category android:name="android.intent.category.LAUNCHER" />
    <!-- Add the following line for cardboard -->
    <category android:name="com.google.intent.category.CARDBOARD" />
    <!-- Add the following line for daydream -->
    <category android:name="com.google.intent.category.DAYDREAM" />
</intent-filter>

To support GearVR, you need to add the following under the <application> node:

<meta-data android:name="com.samsung.android.vr.application.mode" android:value="vr_only"/>
For API level 30 or above

If you are targetting API Level 30 or above, make sure to add the following lines to the <manifest>:

<queries>
    <package android:name="com.google.ar.core" />
</queries>
Optional - when debugging

Add the following line as an attribute on the <application> node. This should only used when debugging and is not recommended for production (you may want to inject the value using manifestPlaceholders set for specific build types).

<application
    android:usesCleartextTraffic="true"
    ...

See an example here. This example is for AR only.

7. You're done! You can now run npx react-native run-android to upload the app to your device.