Search code examples
iosiphonereact-nativeexporeact-native-track-player

How to resolve Invariant Violation: `new NativeEventEmitter()` requires a non-null argument. when using react-native-track player with expo workflow?


I am trying to build a track player in react native. I am using an expo managed workflow. I installed react-native-track player dependency using npx expo install react-native-track-player.

Further, I am starting a dev build using expo dev client with the command npx expo run:ios I get following exceptions once I try to start the app on the ios simulator:

 ERROR  Invariant Violation: `new NativeEventEmitter()` requires a non-null argument., js engine: hermes
 ERROR  Invariant Violation: "main" has not been registered. This can happen if:
* Metro (the local dev server) is run from the wrong folder. Check if Metro is running, stop it and restart it in the current project.
* A module failed to load due to an error and `AppRegistry.registerComponent` wasn't called., js engine: hermes
› Stopped server

We encounter this issue, even before registering the playback service, which leads me to believe that the issue is not caused by my code.

I am using following versions:

  • "react-native-track-player": "^4.0.1",
  • "expo": "^49.0.0",

And IOS version 17.0.1.

We already tried installing the pods with

cd ios && pod install

Solution

  • The issue was that the generated podfile was faulty. It was missing the line registering the react-native-track-player pod. To solve the issue I wrote a expo config plugin:

    const { withDangerousMod, withPlugins } = require('@expo/config-plugins');
    const fs = require('fs');
    const path = require('path');
    
    async function readFile(filePath) {
        return fs.promises.readFile(filePath, 'utf8');
    }
    
    async function saveFile(filePath, content) {
        return fs.promises.writeFile(filePath, content, 'utf8');
    }
    
    module.exports = (config) => withPlugins(config, [
        (config) => {
            return withDangerousMod(config, [
                'ios',
                async (config) => {
                    const filePath = path.join(config.modRequest.platformProjectRoot, 'Podfile');
                    let contents = await readFile(filePath);
    
                    const podLine = "pod 'react-native-track-player', path: '../node_modules/react-native-track-player'";
                    contents = contents.replace(new RegExp(podLine, 'g'), '');
    
                    const insertPosition = contents.indexOf('post_integrate do |installer|');
                    if (insertPosition === -1) {
                        throw new Error("Couldn't find the position to insert the pod line.");
                    }
    
                    contents = contents.slice(0, insertPosition) + podLine + '\n' + contents.slice(insertPosition);
    
                    await saveFile(filePath, contents);
                    return config;
                },
            ]);
        },
    ]);
    

    and then added the plugin to app.config.json

        plugins: ["./plugins/withPodfile"],