doublesymmetry / react-native-track-player

A fully fledged audio module created for music apps. Provides audio playback, external media controls, background mode and more!
https://rntp.dev/
Apache License 2.0
3.27k stars 1.01k forks source link

API calls on Android fail with "The player is not initialized. Call setupPlayer first." #2355

Closed eedeebee closed 2 months ago

eedeebee commented 2 months ago

Describe the Bug Any API call can fail with this. I've got over 300 events of this happening in sentry. pause(), setVolume(), setRepeatMode(), and others. It would be helpful to know if this error being thrown in Sentry actually means the APi calls are failing...I can't tell.

Steps To Reproduce I see it in the field with my customers. I don't know how to reproduce it. It seems it might be triggered by the ap pgoing to the background and then waking up, but that doesn't cause the issue on our test devices. ' Code To Reproduce Nope, not practical.

Replicable on Example App? That app is wildly complicated.

Environment Info: Real device, 4.0.0 of rntp, all sorts of android devices and OSes.

How I can Help There's some other bug (that was closed, reopened, and then closed because team would asks for using the example app for reproduction, which is frankly often not practical). See https://github.com/doublesymmetry/react-native-track-player/issues/1636. I

SteveWaterfall commented 2 months ago

Seconded. I had this issue

https://github.com/doublesymmetry/react-native-track-player/issues/1636#issuecomment-1962999423

As mentioned it works on some android devices but not all. For me it did not work on OnePlus 10T devices.

lovegaoshi commented 2 months ago

with no reproduction, no logs, ur best bet other than paying someone to debug your complex app for you (SWE contract rate is ~$200/hr?), is quite frankly black magic. I can vouch I've never seen this on my sentry report with my piss poor install base, so it could be your app is simply set up wrong, could be a react native bs, who knows.

and if it occurs to the oneplus family of phones, too bad; u'd have to convince an unpaid maintainer to buy an oneplus 10T out of the kindness of their heart and pocket to debug this for you without any outlined steps to reproduce, which is not going to happen.

SteveWaterfall commented 2 months ago

with no reproduction, no logs, ur best bet other than paying someone to debug your complex app for you (SWE contract rate is ~$200/hr?), is quite frankly black magic. I can vouch I've never seen this on my sentry report with my piss poor install base, so it could be your app is simply set up wrong, could be a react native bs, who knows.

and if it occurs to the oneplus family of phones, too bad; u'd have to convince an unpaid maintainer to buy an oneplus 10T out of the kindness of their heart and pocket to debug this for you without any outlined steps to reproduce, which is not going to happen.

I was merely backing up what the OP said. My app is setup correctly and I have found a workaround for the OnePlus so I'm good but I saw that others had the issue in the previous post which I referenced above. 95% of android users and all iOS do not have this issue for me. If others have it then there must be a common denominator.

lovegaoshi commented 2 months ago

im also merely pointing out the fact this is very likely not going to be resolved based on the very limited amount of information provided and being a unique android vendor specific problem. also if you can outline what you did as an oneplus workaround it would immensely help your peer at this issue.

eedeebee commented 2 months ago

I fully understand I'm not sharing much to go on wrt this bug and appreciate any attention anyone has for it.

Fwiw I believe my app is set up correctly, but see #2344.

I see this issue on both Android 13 and Android 14 OS. Devices include (according to Sentry):

It seems this likely happens in MusicModule.kt where isServiceBound is set to false (because of a call to onServiceDisconnected) and then some other code eventually calls verifyServiceBoundOrReject and that happens before a call to onServiceConnected. I offered up my initialization code from index.js below but I suspect that is not the culprit.

My app does listen to AppState changes and pauses or halts (or fades out) audio when going inactive/background - those include calls to setVolume, setRepeatMode, pause and stop and also does some things when the app comes back into active. Perhaps this would be a fruitful avenue for some code inspection for someone who knows the Android code here better than me... on how this might happen?

/**
 * @format
 */

import {AppRegistry} from 'react-native';
import {NavigationContainer} from '@react-navigation/native';
import App from './src/App';
import {name as appName} from './app.json';
import TrackPlayer, { IOSCategoryOptions, AppKilledPlaybackBehavior } from 'react-native-track-player';
import Audio from './src/components/common/Audio';

import { QueryClient } from '@tanstack/react-query';
import AsyncStorage from '@react-native-async-storage/async-storage'
import { PersistQueryClientProvider } from '@tanstack/react-query-persist-client'
import { createAsyncStoragePersister } from '@tanstack/query-async-storage-persister'
import 'react-native-url-polyfill/auto';
import 'react-native-get-random-values';
import { navigationRef } from './src/components/common/Navigation';

const queryClient = new QueryClient({
  defaultOptions: {
    queries: {
      gcTime: Infinity, // Let's hold things forever
    },
  },
});
const asyncStoragePersister = createAsyncStoragePersister({
  storage: AsyncStorage,
  key: "tanstack"
});

const NotewizeApp = () => (
    <NavigationContainer ref={navigationRef}>
      <PersistQueryClientProvider client={queryClient} persistOptions={{ persister: asyncStoragePersister }}>
        <App/>
      </PersistQueryClientProvider>
    </NavigationContainer>
  );

AppRegistry.registerComponent(appName, () => NotewizeApp);

async function setupTrackPlayerAndLoadModel() {
  TrackPlayer.registerPlaybackService(() => require('./src/components/pages/Player/service.js'));
  await TrackPlayer.setupPlayer({
    iosCategoryOptions: [IOSCategoryOptions.AllowBluetoothA2DP]
  });
  await TrackPlayer.updateOptions({
    android: {
        appKilledPlaybackBehavior: AppKilledPlaybackBehavior.StopPlaybackAndRemoveNotification
    },
  });
  await TrackPlayer.setVolume(0.5);
  const chord = require("./android/app/src/main/res/raw/notewize_chord.mp3");
  await TrackPlayer.add({
    url: chord
  });
  TrackPlayer.play();

  await Audio.loadModel();
} 

setupTrackPlayerAndLoadModel();
lovegaoshi commented 2 months ago

could u monitor eg. musicservice's ondestory to confirm the service is being terminated? and perhaps get the reason why it's killed? otherwise we are just guessing at this point, i'll mention https://github.com/doublesymmetry/react-native-track-player/issues/2244 which is also related to service being killed and then initialized incorrectly.

eedeebee commented 2 months ago

Hm... I guess I should ask this naive question: Is there any configuration or setup to avoid the background service? My app (it's a music teaching and learning app) doesn't need (and specifically doesn't want) to do anything audio-wise when the app is in the background.

lovegaoshi commented 2 months ago

im afraid u used the wrong library. RNTP is specifically a music library that supports a background service (notification). you should be looking into eg. expo-av.

on the other hand, all music players require a background service, which is what RNTP caters to.

eedeebee commented 2 months ago

Thanks for the attention so far and sorry for the noise.

I'm looking more deeply and I see this is likely the app initialization code. I am seeing failures in the startup code occasionally. And, I think these errors are only reported by clients that see this error first "Error: On Android the app must be in the foreground when setting up the player.". I will close this.