Using trackplayer 1.20.
I see the app stays in memory even when using StopWithApp = true.
It looks like there are two instances fired and one is going down after app and other stays in memory.
Also i can confirm that the app stays in the background as i get reports data traffic is out in 4 days.
Where do i need to look to solve this?
My part of loading: (maybe buggy haha)
import React, { Component, useEffect, useState } from 'react';
import {
Platform,
StyleSheet,
Text,
View,
Image,
TouchableOpacity,
} from 'react-native';
import { connect } from 'react-redux';
import { togglePlayer } from '../actions';
import NetInfo from '@react-native-community/netinfo';
import TrackPlayer, { usePlaybackState } from 'react-native-track-player';
import * as playerSetting from '../constants/PlayerConstants';
import * as screenSetting from '../constants/ScreenConstants';
const { playerUrl } = playerSetting;
const { width, height } = screenSetting;
function Player(props) {
const playbackState = usePlaybackState();
const [haveInternet, setHaveInternet] = useState(true);
useEffect(
() => {
//Event Listeners
NetInfo.addEventListener(
'connectionChange',
handleFirstConnectivityChange
);
function handleFirstConnectivityChange() {
TrackPlayer.reset();
if (Platform.OS === 'ios') {
togglePlayback();
}
}
NetInfo.isConnected.addEventListener(
'connectionChange',
this.handleConnectivityChange
);
NetInfo.isConnected.fetch().done((isConnected) => {
if (isConnected == true) {
setHaveInternet(true);
}
});
TrackPlayer.setupPlayer({});
TrackPlayer.updateOptions({
stopWithApp: true,
//waitForBuffer: true,
capabilities: [
TrackPlayer.CAPABILITY_PLAY,
TrackPlayer.CAPABILITY_PAUSE,
TrackPlayer.CAPABILITY_STOP,
],
compactCapabilities: [
TrackPlayer.CAPABILITY_PLAY,
TrackPlayer.CAPABILITY_PAUSE,
],
});
return () => {
//TrackPlayer.destroy();
NetInfo.isConnected.removeEventListener(
'connectionChange',
this.handleConnectivityChange
);
NetInfo.removeEventListener(
'connectionChange',
handleFirstConnectivityChange
);
};
},
[TrackPlayer.stop(), TrackPlayer.reset()]
);
handleConnectivityChange = (isConnected) => {
if (isConnected == false) {
setHaveInternet(false);
//togglePlayback();
} else {
setHaveInternet(true);
//togglePlayback();
}
};
renderButton = () => {
if (
playbackState == TrackPlayer.STATE_PAUSED ||
playbackState === TrackPlayer.STATE_STOPPED ||
playbackState === TrackPlayer.STATE_NONE
) {
return (
<Image
source={require('../assets/play.png')}
style={styles.playerButton}
imageStyle={{ resizeMode: 'contain' }}
/>
);
} else {
return (
<Image
source={require('../assets/pauze.png')}
style={styles.playerButton}
imageStyle={{ resizeMode: 'contain' }}
/>
);
}
};
async function togglePlayback() {
const currentTrack = await TrackPlayer.getCurrentTrack();
if (currentTrack == null) {
await TrackPlayer.add({
id: 'HeteHits',
url: playerUrl,
title: 'Loading...',
artist: 'Loading...',
artwork: '../assets/track_image.png',
});
await TrackPlayer.play();
props.togglePlayerState();
} else {
if (playbackState === TrackPlayer.STATE_PAUSED) {
await TrackPlayer.play();
props.togglePlayerState();
} else {
TrackPlayer.pause();
props.togglePlayerState();
}
}
}
return (
<View style={styles.container}>
<TouchableOpacity
disabled={!haveInternet}
onPress={() => togglePlayback()}
>
<View
style={{
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
}}
>
{renderButton()}
<Image
source={require(`../assets/luisterLive.png`)}
style={{
height: height * 0.075,
width: width * 0.175,
resizeMode: 'contain',
}}
imageStyle={{ resizeMode: 'contain' }}
/>
</View>
</TouchableOpacity>
</View>
);
}
const mapStateToProps = (state) => {
return {
speeltNu: state.togglePlayer.speeltNu,
};
};
const mapDispatchToProps = (dispatch) => {
return {
togglePlayerState: () => dispatch(togglePlayer()),
};
};
export default connect(mapStateToProps, mapDispatchToProps)(Player);
const styles = StyleSheet.create({
container: {
justifyContent: 'center',
alignItems: 'center',
},
playerButton: {
height: height * 0.07,
width: width * 0.17,
resizeMode: 'contain',
marginBottom: 10,
},
});
I see the app stays in memory even when using StopWithApp = true.
stopWithApp destroys TrackPlayer instance after application is closed.
Do you see player icon in status bar after app is closed?
I faced with this issue in my phone (Android) for development and debugging - after closing app there still was player icon in status bar.
Did not dive in this, because on other phones with released app it was OK.
Also check if other options (capabilities etc) from updateOptions work. Try to use async/await for setupPlayer and updateOptions.
IT is indeed in Android where an extra icon appears which cannot be deleted somehow. Strange part is iT seems on iOS it stays on the background too. And it keeps using traffic somehow.
What do you recommend for async/await?
I mean you should use async / await with all TrackPlayer methods.
async () => {
...
await TrackPlayer.setupPlayer({});
await TrackPlayer.updateOptions({
stopWithApp: true,
//waitForBuffer: true,
capabilities: [
TrackPlayer.CAPABILITY_PLAY,
TrackPlayer.CAPABILITY_PAUSE,
TrackPlayer.CAPABILITY_STOP,
],
compactCapabilities: [
TrackPlayer.CAPABILITY_PLAY,
TrackPlayer.CAPABILITY_PAUSE,
],
});
...
}
I just supposed that updateOptions may not work properly and so stopWithApp: true will not be set.
@roman-gula Ok, this seems to be helpful. The player icon is disapearing now. The only question is why there are TWO player icons in the status area? Any ideas?
UPDATE: Solution with the await does not work either :(
Problem stays the same. Icon keeps showing and also the lockscreen shows the album what was played. So the app does not be killed at all.
It seems it gets loaded twice somehow.
Hope anyone can help me out as i need to deliver the app :(
No one?
Hello, are you testing with release mode or just the developer version?
I had noticed this same problem when I was in developer mode, but in release mode I did not have this problem.
About the 2 icons: Notification needs a 'communication channel'. which would be a service that communicates between Android and Notification. It may be happening that this channel is active and visible, then its notification appears
Read #729
@maendamedia
Looking at the code I noticed that the communication channel of the Player is not removed.
So when something is finalized I should end the notification and remove the communication channel, I'll be doing some testing to find out if that is the only problem.
We work just as follows.
await TrackPlayer.setupPlayer()
TrackPlayer.updateOptions({
capabilities: [
TrackPlayer.CAPABILITY_PLAY,
TrackPlayer.CAPABILITY_PAUSE,
TrackPlayer.CAPABILITY_JUMP_FORWARD,
TrackPlayer.CAPABILITY_JUMP_BACKWARD,
TrackPlayer.CAPABILITY_STOP,
],
})
We move above codes from local files to top files (App.js).
And write this (in your local files componentWillUnmount())
TrackPlayer.destroy()
Related articles.
reactjs/react-transition-group#79 (comment)
Hope it will work !
componentWillUnmount should destroy the player when the app leaves the foreground (it's still in the task list)
stopWithApp should destroy the player when the app is fully closed (the app is removed from the task list)
Most helpful comment
componentWillUnmountshould destroy the player when the app leaves the foreground (it's still in the task list)stopWithAppshould destroy the player when the app is fully closed (the app is removed from the task list)