Expo react-native-track-player

Please provide the following:

  1. SDK Version: 44.0.0
  2. Platforms(Android/iOS/web/all): IOS
  3. Add the appropriate “Tag” based on what Expo library you have a question on.

I am currently trying to install the react-native-track-player with expo, however I can’t seem to fix the error of:

“Native module cannot be null”

It seems that Expo added the ability to use this library back in September according to this post: Audio playback in background | Voters | Expo however there seems to be very little documentation online allowing me to fix this error.

Furthermore, I tried adding the swift file as described in the installation procedures (Installation - react-native-track-player) however I realized that I cannot open my project in xcode, thus I am not sure where the error is coming from, and how to fix it.

First, make sure you installed it with expo install rather than npm or yarn. I’m not sure about the track player specifically, but some react native modules need expo to perform some kind of linking when installing.

Second, you can’t normally use native modules in expo go. You have to build a dev-client and test the feature that way.

If you want to continue using expo go for developing features that don’t use native modules, and you just want to get around the error you described, you can try something like this:

let trackPlayer;
try {
     trackPlayer = require('react-native-track-player');
     // do whatever initialization it may need
} catch (e) {
     console.log("Failed to initialize track player. Mocking it's methods...")
     trackPlayer = {
          playTrack: () => null,
          // mock whatever methods you need to use
     }
}

export default trackPlayer;

Now you can import track player where ever you need it. If for some reason the try block isn’t throwing an error, you can change it to a normal if statement that checks if the result of the require is null.

To reiterate, you’ll need a dev-client build to test your track player. To test other features via expo go, you’ll need to mock the track player like the above code block.

…at least that’s the way I do it. You could also set an environment variable that was present in expo go, but not in dev-client, and then import/mock the track player depending on the value.

2 Likes

Thanks a lot for the help! I am new to expo so I am still trying to figure it out.
I am thinking of switching to the expo-av library as it delivers similar functionality, and will allow me to stay with expo-go which has been really nice until this point.

This is the answer. Expo Go only has a predefined set of native code included. (The native code from the range of Expo SDKs that Expo Go supports.) So if you install a dependency that includes its own native code, that native code is not included in Expo Go, so the JavaScript will get errors when it tries to call it.

Some clarification: expo install doesn’t do any linking. All it does is make sure that the version of the dependency is compatible with the version of the Expo SDK. But it can only do this for the dependencies it’s been told about.
I suppose you could think of Config Plugins as special linking, but that happens at “prebuild” time rather than at install time. Also, it seems that a config plugin is not needed for react-native-track-player.

Using expo install instead of yarn add or npm install is fine, though. If there’s no reference to the package in the above list it will just not specify a version when it calls yarn/npm to install the dependency.

1 Like

The development client that @jrconsole mentioned is basically a customised version of Expo Go that includes all of your dependencies (and only your dependencies). This means that if you build one and later install e.g. expo-file-system will need to rebuild the dev client. Even though expo-file-system is included in the Expo SDK. So the recommendation I’ve seen is to rebuild your dev client whenever you make changes to your dependencies or app.json.

If expo-av does everything you need, that’s great :slight_smile:
If you need to be able to play audio in the background I believe you’ll need to switch to react-native-track-player.

EDIT:

I forgot to add that I believe Expo already does this, so you should not need to do that part.

I currently use expo-av with expo-native-music-controls to enable the audio controls in the native toolbar. I thought it would allow for background audio, and it seems to do so most of the time, but I’ve still gotten some user reports of audio stopping, so I may end up switching to react-native-track-player soon.

1 Like

@wodin @jrconsole So from the information listed above, I seem to understand that react-native-track-player uses native code and that Expo Go doesn’t support it, thus why I am receiving such an error.

However it seems that in the post the Expo staff members state that Expo has now added the ability to use react-native-track-player (see screenshot)

So what exactly did they mean by this?

Yes.

The part that makes it possible is building with EAS Build instead of expo build.
To get an experience like Expo Go you need to build a custom development client (with --profile development). Then instead of running Expo Go, you install and run the dev client and use that with expo start --dev-client
When you build a version to submit to the App/Play stores you build a production version of the app with eas build --profile production.

1 Like

I am facing same issue and after building with eas for android it gives qrcode but it shows no usable data found…

Can u give step by step procedure for react-native-track-player with expo??It will be helpful

And those links for the ios and android are not working… And how to register playback service actually?

Try making sure you’re logged into the same account in expo-cli and in the dev client. Then you should see the project listed in the dev client without having to scan a QR code.

I’m not sure what exactly you mean by the above.

It’s explained here:

I have not tried it myself, but the following should work:

Remove the “main” entry from package.json:

diff --git package.json package.json
index 8fb99a1..138531f 100644
--- package.json
+++ package.json
@@ -1,7 +1,6 @@
 {
   "name": "app-name",
   "version": "1.0.0",
-  "main": "node_modules/expo/AppEntry.js",
   "scripts": {
     "start": "expo start",
     "android": "expo start --android",

Then create a file called index.js at the root of your project with the following contents:

import { registerRootComponent } from 'expo';
import TrackPlayer from 'react-native-track-player';

import App from './App';

// registerRootComponent calls AppRegistry.registerComponent('main', () => App);
// It also ensures that whether you load the app in Expo Go or in a native build,
// the environment is set up appropriately
registerRootComponent(App);
TrackPlayer.registerPlaybackService(() => require('./service'));

Then create a service.js file. Here’s the example from the above link:

// service.js
module.exports = async function() {

    TrackPlayer.addEventListener('remote-play', () => TrackPlayer.play());

    TrackPlayer.addEventListener('remote-pause', () => TrackPlayer.pause());

    TrackPlayer.addEventListener('remote-stop', () => TrackPlayer.destroy());

    // ...

};

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