Where should app.manifest be found in a react-native project?

Viewed 2624

Where I'm at

After ejecting from a managed expo project and solving a few errors, app will build but crashes immediately when opening on android device and does not show assets on iOS.

I have found some similar issues and followed the "create a new bare project and compare" advice but everything looks the same to me.

Error I get from android logcat

2020-07-16 16:05:09.540 5482-5482/com.pye.android E/EmbeddedLoader: Could not read embedded manifest
    java.io.FileNotFoundException: app.manifest
        at android.content.res.AssetManager.nativeOpenAsset(Native Method)
        at android.content.res.AssetManager.open(AssetManager.java:744)
        at android.content.res.AssetManager.open(AssetManager.java:721)
        at expo.modules.updates.loader.EmbeddedLoader.readEmbeddedManifest(EmbeddedLoader.java:73)
        at expo.modules.updates.UpdatesController.start(UpdatesController.java:285)
        at expo.modules.updates.UpdatesController.initialize(UpdatesController.java:96)
        at com.pye.android.MainApplication.onCreate(MainApplication.java:85)

AndroidManifest.xml

<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.pye">
  <uses-permission android:name="android.permission.INTERNET"/>
  <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
  <uses-permission android:name="android.permission.MANAGE_DOCUMENTS"/>
  <uses-permission android:name="android.permission.READ_INTERNAL_STORAGE"/>
  <uses-permission android:name="android.permission.READ_PHONE_STATE"/>
  <uses-permission android:name="android.permission.USE_FINGERPRINT"/>
  <uses-permission android:name="android.permission.VIBRATE"/>
  <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"/>
  <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
  <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
  <uses-permission android:name="android.permission.CAMERA"/>
  <uses-permission android:name="android.permission.READ_CONTACTS"/>
  <uses-permission android:name="android.permission.READ_CALENDAR"/>
  <uses-permission android:name="android.permission.WRITE_CALENDAR"/>
  <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
  <uses-permission android:name="android.permission.RECORD_AUDIO"/>
  <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
  <uses-permission android:name="android.permission.WRITE_SETTINGS"/>
  <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
  <uses-permission android:name="android.permission.WAKE_LOCK"/>
  <uses-permission android:name="com.google.android.c2dm.permission.RECEIVE"/>
  <application android:name=".MainApplication" android:label="@string/app_name" android:icon="@mipmap/ic_launcher" android:roundIcon="@mipmap/ic_launcher_round" android:allowBackup="false" android:theme="@style/AppTheme">
    <meta-data android:name="expo.modules.updates.EXPO_UPDATE_URL" android:value="https://exp.host/@thehuns/pye" />
    <meta-data android:name="expo.modules.updates.EXPO_SDK_VERSION" android:value="37.0.0" />
    <meta-data android:name="expo.modules.updates.ENABLED" android:value="true"/>
    <meta-data android:name="expo.modules.updates.EXPO_UPDATES_CHECK_ON_LAUNCH" android:value="ALWAYS"/>
    <meta-data android:name="expo.modules.updates.EXPO_UPDATES_LAUNCH_WAIT_MS" android:value="5000"/>
    <meta-data android:name="expo.modules.updates.EXPO_RELEASE_CHANNEL" android:value="default" />

app/build.gradle

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

apply from: '../../node_modules/react-native-unimodules/gradle.groovy'
apply from: "../../node_modules/react-native/react.gradle"
apply from: "../../node_modules/expo-updates/scripts/create-manifest-android.gradle"

package.json

"dependencies": {
    "expo": "~37.0.9",
    "expo-splash-screen": "^0.2.3",
    "expo-updates": "~0.2.0",
    "react": "~16.9.0",
    "react-dom": "~16.9.0",
    "react-native": "~0.61.5",
    "react-native-gesture-handler": "~1.6.0",
    "react-native-reanimated": "~1.7.0",
    "react-native-screens": "~2.2.0",
    "react-native-unimodules": "~0.9.0",
    "react-native-web": "~0.11.7",
    "@expo/vector-icons": "~10.0.6",
    "@react-native-community/masked-view": "0.1.6",
    "@react-navigation/bottom-tabs": "^5.3.1",
    "@react-navigation/native": "^5.2.1",
    "@react-navigation/stack": "^5.2.16",
    "buttercms": "^1.2.2",
    "eslint": "^7.4.0",
    "eslint-plugin-import": "^2.22.0",
    "eslint-plugin-jsx-a11y": "^6.3.1",
    "eslint-plugin-react": "^7.20.3",
    "eslint-plugin-react-hooks": "^4.0.6",
    "expo-asset": "~8.1.0",
    "expo-constants": "~9.0.0",
    "expo-font": "~8.1.0",
    "expo-in-app-purchases": "^8.2.1",
    "expo-linking": "^1.0.1",
    "expo-web-browser": "~8.2.0",
    "react-native-progress": "^4.1.2",
    "react-native-safe-area-context": "0.7.3",
    "react-native-snap-carousel": "^3.9.1"
  },

Let me know if there are any other pieces of code needed. Thanks!

1 Answers

I ran into this problem today and after much digging found the React Native build was actually crashing out when it tried to use the jest-haste-map, somewhere deep inside the Metro class hierarchy somewhere I can't remember, but you could trace it and find out if you're interested. Anyway I could see that jest-haste-map was crashing out and the rest of the code was not getting executed, so the app.manifest was never getting written to the bundle!

However, jest-haste-map was not actually at fault. I had my suspicions about file permissions since Watchman was throwing up the odd warning here and there.

I decided to do a clean setup and build. First off I used (and recommend) sudo expo init since you get the expo-unimodules installed by default which solves the problems associated with installing that by hand (that's another story !) Choose the minimal bare template.

Next I found that if I ran the Metro server with npm start instead of sudo npm start I got a jest-haste-map error/warning (may have been Watchman, can't remember). This led me to believe the original build problem (missing app.manifest) was purely a permissions problem. And indeed it was.

After chown-ing the /tmp folder to root (not sure how safe that is?) and making sure I sudo npm -g installed everything I needed, and made sure to start the Metro server and React Native as root (sudo npm start and sudo react-native run-android) the problem was solved.

I could then easily go ahead and make my production AAB or APK and everything worked fine.

Lesson I learned: don't ignore Watchman. Although React Native may seem to build okay, a Watchman warning/error is actually a clue that something isn't ok!

So the original problem is that the project and tool chain setup had the incorrect permissions, which caused the jest-haste-map module to fail during the React Native build, which meant the app.manifest file was never written out to the AAB or APK file, hence the error.

Note - it's quite possible a sudo chmod -R 777 MyAppFolder will sort the problem.

Related