Getting null from expoConstants.default.manifest.releaseChannel in recently bare ejected app

Hello everyone

Our team recently ejected from expo to the new bare workflow since we need to add firebase into our app and we are having issues with even trying to run the project with yarn start and yarn android. We’ve read on this thread and this page on the documentation that the expo package should not be imported if you want to use the new bare workflow, and so we did (we were using AppLoading and ScreenOrientation, we are gonna miss them), but after we removed all imports of the expo package, we started getting this issue:

We’ve tried changing import Constants from 'expo-constants'; to import { Constants } from 'react-native-unimodules'; but we are still having that error. I went to the files that the error is showing (at the specific lines) but there is nothing that can give me a hint.

Do you guys know what can it be? What are we missing?

edit: i can provide more info if needed

Have you run expo install expo-constants? You should be importing with import Constants from 'expo-constants';

Could you provide a repro for this? Can share the code via a snack or a gh repo and I’ll run locally

Hi @charliecruzan, thank you for your response.

My project already used expo-constants to display version number and decide the enviroment.
This is my package.json

{
  "private": true,
  "dependencies": {
    "@expo/vector-icons": "^10.0.3",
    "expo": "^34.0.4",
    "expo-asset": "^6.0.0",
    "expo-av": "~6.0.0",
    "expo-blur": "~6.0.0",
    "expo-camera": "~6.0.0",
    "expo-constants": "~6.0.0",
    "expo-document-picker": "~6.0.0",
    "expo-file-system": "~6.0.0",
    "expo-font": "~6.0.1",
    "expo-gl": "~6.0.0",
    "expo-haptics": "~6.0.0",
    "expo-image-manipulator": "~6.0.0",
    "expo-image-picker": "~6.0.0",
    "expo-linear-gradient": "~6.0.0",
    "expo-localization": "~6.0.0",
    "expo-location": "~6.0.0",
    "expo-permissions": "~6.0.0",
    "expo-pixi": "^1.1.0",
    "expo-web-browser": "~6.0.0",
    "geolib": "^2.0.24",
    "lodash": "^4.17.10",
    "moment": "^2.24.0",
    "react": "16.8.3",
    "react-dom": "^16.8.6",
    "react-native": "0.59.8",
    "react-native-custom-actionsheet": "0.0.4",
    "react-native-fullwidth-image": "^0.1.2",
    "react-native-gesture-handler": "~1.3.0",
    "react-native-image-gallery": "^2.1.5",
    "react-native-maps": "~0.24.2",
    "react-native-modal": "^6.5.0",
    "react-native-progress": "^3.6.0",
    "react-native-reanimated": "~1.1.0",
    "react-native-shimmer-placeholder": "https://github.com/tomzaku/react-native-shimmer-placeholder.git#expo",
    "react-native-simple-dialogs": "^1.0.0",
    "react-native-simple-radio-button": "^2.7.2",
    "react-native-snap-carousel": "^3.7.2",
    "react-native-status-bar-height": "^2.1.0",
    "react-native-svg": "~9.5.1",
    "react-native-swiper": "^1.5.14",
    "react-native-tab-view": "^1.2.0",
    "react-native-unimodules": "~0.5.2",
    "react-native-web": "^0.11.4",
    "react-navigation": "^2.18.2",
    "react-redux": "^5.0.7",
    "redux": "^4.0.0",
    "redux-thunk": "^2.3.0"
  },
  "devDependencies": {
    "babel-eslint": "^8.2.3",
    "eslint": "^4.19.1",
    "eslint-config-airbnb": "^16.1.0",
    "eslint-plugin-babel": "^5.2.0",
    "eslint-plugin-import": "^2.12.0",
    "eslint-plugin-jsx-a11y": "^6.0.3",
    "eslint-plugin-react": "^7.11.1",
    "jest": "^23.1.0",
    "jest-expo": "^34.0.0",
    "react-native-console-time-polyfill": "^0.0.6",
    "react-test-renderer": "^16.4.0"
  },
  "scripts": {
    "pretest": "yarn lint",
    "test": "jest",
    "lint": "eslint . --ext .js",
    "start": "react-native start",
    "ios": "react-native run-ios",
    "android": "react-native run-android"
  },
  "jest": {
    "preset": "jest-expo"
  },
  "resolutions": {
    "@expo/browser-polyfill": "~0.1.0"
  }
}

This is my build.gradle file:

buildscript {
    ext {
        buildToolsVersion = "28.0.3"
        minSdkVersion = 21
        compileSdkVersion = 28
        targetSdkVersion = 27
        supportLibVersion = "28.0.0"
    }
    repositories {
        google()
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:3.3.0'
    }
}

allprojects {
    repositories {
        mavenLocal()
        google()
        jcenter()
        maven {
            // All of React Native (JS, Obj-C sources, Android binaries) is installed from npm
            url "$rootDir/../node_modules/react-native/android"
        }

        maven {
            // expo-camera bundles a custom com.google.android:cameraview
            url "$rootDir/../node_modules/expo-camera/android/maven"
        }
    }
}


task wrapper(type: Wrapper) {
    gradleVersion = '4.7'
    distributionUrl = distributionUrl.replace("bin", "all")
}

This is my app build.gradle

apply plugin: "com.android.application"

import com.android.build.OutputFile

project.ext.react = [
    entryFile: "index.js"
]

apply from: '../../node_modules/react-native-unimodules/gradle.groovy'
apply from: "../../node_modules/react-native/react.gradle"

def enableSeparateBuildPerCPUArchitecture = false

def enableProguardInReleaseBuilds = false

android {
    compileSdkVersion rootProject.ext.compileSdkVersion
    buildToolsVersion rootProject.ext.buildToolsVersion

    defaultConfig {
        applicationId "<my app id>"
        minSdkVersion rootProject.ext.minSdkVersion
        targetSdkVersion rootProject.ext.targetSdkVersion
        versionCode 1
        versionName "1.0"
    }
    splits {
        abi {
            reset()
            enable enableSeparateBuildPerCPUArchitecture
            universalApk false  // If true, also generate a universal APK
            include "armeabi-v7a", "x86", "arm64-v8a", "x86_64"
        }
    }
    buildTypes {
        release {
            minifyEnabled enableProguardInReleaseBuilds
            proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"
        }
    }
    // applicationVariants are e.g. debug, release
    applicationVariants.all { variant ->
        variant.outputs.each { output ->
            // For each separate APK per architecture, set a unique version code as described here:
            // http://tools.android.com/tech-docs/new-build-system/user-guide/apk-splits
            def versionCodes = ["armeabi-v7a":1, "x86":2, "arm64-v8a": 3, "x86_64": 4]
            def abi = output.getFilter(OutputFile.ABI)
            if (abi != null) {  // null for the universal-debug, universal-release variants
                output.versionCodeOverride =
                        versionCodes.get(abi) * 1048576 + defaultConfig.versionCode
            }
        }
    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
}

dependencies {
    implementation project(':react-native-svg')
    implementation project(':react-native-maps')
    implementation project(':react-native-reanimated')
    implementation project(':react-native-gesture-handler')
    implementation fileTree(dir: "libs", include: ["*.jar"])
    implementation "com.android.support:appcompat-v7:${rootProject.ext.supportLibVersion}"
    implementation "com.facebook.react:react-native:+"  // From node_modules
    addUnimodulesDependencies()
}

task copyDownloadableDepsToLibs(type: Copy) {
    from configurations.compile
    into 'libs'
}

And my settings.gradle

apply from: '../node_modules/react-native-unimodules/gradle.groovy'
includeUnimodulesProjects()

include ':react-native-svg'
project(':react-native-svg').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-svg/android')

include ':react-native-maps'
project(':react-native-maps').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-maps/lib/android')

include ':react-native-reanimated'
project(':react-native-reanimated').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-reanimated/android')

include ':react-native-gesture-handler'
project(':react-native-gesture-handler').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-gesture-handler/android')

rootProject.name = 'figoinsurance.petcloud'

include ':app'

This is my MainApplication.java

public class MainApplication extends Application implements ReactApplication {
  private final ReactModuleRegistryProvider mModuleRegistryProvider = new ReactModuleRegistryProvider(
    new BasePackageList().getPackageList(),
    Arrays.<SingletonModule>asList()
  );

  private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {
    @Override
    public boolean getUseDeveloperSupport() {
      return BuildConfig.DEBUG;
    }

    @Override
    protected List<ReactPackage> getPackages() {
      return Arrays.<ReactPackage>asList(
          new MainReactPackage(),
          new MapsPackage(),
          new ReanimatedPackage(),
          new RNGestureHandlerPackage(),
          new ModuleRegistryAdapter(mModuleRegistryProvider)
      );
    }

    @Override
    protected String getJSMainModuleName() {
      return "index";
    }
  };

  @Override
  public ReactNativeHost getReactNativeHost() {
    return mReactNativeHost;
  }

  @Override
  public void onCreate() {
    super.onCreate();
    SoLoader.init(this, /* native exopackage */ false);
  }
}

I will try to remove expo-constants from my package.json and see what happens when i try to run the app without it.

Btw, this is my expo diagnostics:

  Expo CLI 3.0.9 environment info:
    System:
      OS: Linux 5.0 Ubuntu 19.04 (Disco Dingo)
      Shell: 5.0.3 - /bin/bash
    Binaries:
      Node: 10.16.2 - /usr/bin/node
      Yarn: 1.17.3 - /usr/bin/yarn
      npm: 6.9.0 - /usr/bin/npm
    npmGlobalPackages:
      expo-cli: 3.0.9

Ah just realized this is a bare app. Since the Constants.manifest. object is simply your app’s manifest. I’m not sure that field will exist for a bare app

Since release channels are a managed workflow only feature, I don’t think there’s any reason to check that value in a bare app, but maybe I’m missing something so let me know if there’s something I’m not understanding about this

Hi @charliecruzan, Yes, you were right, that field is always null when running the app with react native.

I went to the generated javascript code from the expo-constants package and changed let manifest = null; to let manifest = {}; and the project is finally running althought, since releaseChannel doesnt exist, i get undefined.

Is there any alternatives in react native to read the manifest file? Should i submit an issue on github for this?

I guess there should be a note on the docs explaining that you lose the release channel once you go bare.

You can import the file to read it, with:

import manifest from "./app.json";

Hi @charliecruzan

Should the expo-constants package crash even when we’re not using the releaseChannel property from the manifest? Because we’ve decided not to use releaseChannel and we are still getting crashes.

My question should be, is the expo-constants package compatible with the bare workflow?

Sorry for the delayed response, we’ve been bussy trying the new workflow and i dont like to ask without knowing anything.

It is compatible, so it shouldn’t crash

What error message are you getting?

It appears that the error is not on releaseChannel anymore, its on expoConstants.default.manifest.version

I seems that manifest is always null

Im trying to get the app version from Constants.manifest.version

I deleted all my Constants.manifest... declarations and the app its working again. Im only using Constants.deviceName, but yeah, it appears that Constants.manifest its null.

This is what i get when i console log the Constants object with console.log('Constants: ', Constants)

Screenshot%20from%202019-08-21%2012-49-18

I think since the manifest is either served through expo-cli or created on expo publish, bare apps wouldn’t have access to it. I’ll confirm this, and if it’s the case I’ll modify the docs to reflect this. Thanks for bringing this up @rogerlopz!

1 Like

This topic was automatically closed 15 days after the last reply. New replies are no longer allowed.