Skip to content
This repository has been archived by the owner on Oct 6, 2022. It is now read-only.

IOS background mode Play pause controls are disabled but seek bar is moving. #413

Open
2 of 4 tasks
singhiam opened this issue Oct 5, 2022 · 3 comments
Open
2 of 4 tasks

Comments

@singhiam
Copy link

singhiam commented Oct 5, 2022

Description

import React, { Component, useEffect, useState } from 'react';
import {
ActivityIndicator,
Animated,
Platform,
StyleSheet,
TouchableOpacity,
View,
} from 'react-native';
import { connect } from 'react-redux';
import Video from 'react-native-video';
import { withTheme } from 'styled-components';
import { Actions } from 'react-native-router-flux';
import { TFunction, withTranslation } from 'react-i18next';
import MusicControl, { Command } from 'react-native-music-control'

import RewindBtn from './components/RewindBtn/RewindBtn';
import MainBtn from '../_common/buttons/MainBtn/MainBtn';
import PlayBtn from '../_common/buttons/_player/PlayBtn/PlayBtn';
import PlayerSlider from './components/PlayerSlider/PlayerSlider';
import PauseBtn from '../_common/buttons/_player/PauseBtn/PauseBtn';
import DecreaseBtn from '../_common/buttons/_player/DecreaseBtn/DecreaseBtn';
import IncreaseBtn from '../_common/buttons/_player/IncreaseBtn/IncreaseBtn';

import { getActivity } from '../../redux/actions/user';

import { getData } from '../../querys';
import { getFormattedDuration } from '../../helpers/timeHelpers';

import { ITheme } from '../../theme/types/themeTypes';
import { IMeditation } from '../../types/meditationTypes';
import { getItems } from '../../redux/actions/app';

const RN_FS = require('react-native-fs');

export interface Props {
app: any;
network: any;
user: any;
data: IMeditation;
t: TFunction;
theme: ITheme;
dispatch: any;
active: boolean;
download: boolean;
courseId?: number;
scrollBottom: () => void;
}

const AudioController = (props: Props) => {
let player: any;

const [pause, setPause] = useState(true);
const [muted, setMuted] = useState(false);
const [loader, setLoader] = useState(false);
const [loaded, setLoaded] = useState(false);
const [left, setLeft] = useState('--:--');
const [totalLength, setTotalLength] = useState(1);
const [activity_id, setActivity_id] = useState('');
const [show_loader, setShowLoader] = useState(true);
const [currentPosition, setCurrentPosition] = useState(0);
const [loaded_for_ios, setLoadedforIos] = useState(false);
const [totalLengthFormat, setTotalLengthFormat] = useState('00:00');
const [currentTimeFormat, setCurrentTimeFormat] = useState('00:00');
const [file, setFile] = useState('');
const [fadeAnim, setFadeAnim] = useState(new Animated.Value(0));
const [marginTopAnim, setMarginTopAnim] = useState(new Animated.Value(20));
const [file_bg, setFileBg] = useState(props.data.sound_file_with_bg_music);
useEffect(() => {
MusicControl.enableBackgroundMode(true);
MusicControl.handleAudioInterruptions(true);
// Basic Controls

MusicControl.enableControl('play', true)
MusicControl.enableControl('pause', true)
MusicControl.enableControl('stop', true);
MusicControl.enableControl('nextTrack', false)
MusicControl.enableControl('previousTrack', false)
MusicControl.on(Command.play, () => {
  // player.actions.play()
  console.log('Play Tapped')
  //onPlay();
  setPause(false);
})

MusicControl.on(Command.pause, () => {
  // player.actions.pause()
  // onPause();
  console.log('Pause Tapped');
  setPause(true);
})

// MusicControl.on(Command.stop, () => {
//   // player.actions.pause()
//   onPause();
//   setPause
// })

}, [])

useEffect(() => {
if (pause) {
MusicControl.updatePlayback({
state: MusicControl.STATE_PAUSED,
elapsedTime: currentPosition
})
// MusicControl.enableControl('play', false)
MusicControl.enableControl('pause', true)
} else {
MusicControl.updatePlayback({
state: MusicControl.STATE_PLAYING,
elapsedTime: currentPosition
})
MusicControl.setNowPlaying({
title: 'MyMedi',
duration: totalLength,
artwork: 'https://i.imgur.com/e1cpwdo.png',
});
MusicControl.enableControl('pause', false)
}
}, [pause])

const setDuration = (data) => {
setTotalLength(Math.floor(data.duration));
setTotalLengthFormat(getFormattedDuration(data.duration))
setLoaded(true);
}

const setTime = (data) => {
if (data.currentTime < 0) {
setShowLoader(false);
}

const currentTime = Math.floor(data.currentTime);
const leftTime = totalLength - currentTime;

// this.setState({
//   currentPosition: currentTime,
//   currentTimeFormat: getFormattedDuration(currentTime),
//   left: getFormattedDuration(leftTime),
// });
setCurrentPosition(currentTime);
setCurrentTimeFormat(getFormattedDuration(currentTime));
setLeft(getFormattedDuration(leftTime))
MusicControl.updatePlayback({
  elapsedTime: currentTime
})

}

const seek = (time) => {
time = Math.round(time);
player && player.seek(time);

// this.setState({ currentPosition: time });
setCurrentPosition(time)

}

const increase = () => {
// const currentPosition = currentPosition;
// const totalLength = totalLength;
const time = currentPosition + 10;

if (time > totalLength) {
  player && player.seek(totalLength);
} else {
  player && player.seek(time);
  // this.setState({ currentPosition: time });
  setCurrentPosition(time);
}

}

const decrease = () => {
const time = currentPosition - 10;
player && player.seek(time);
// this.setState({ currentPosition: time });
setCurrentPosition(time);
}

const createActivity = async () => {
const data = {
api_token: props.user.api_token,
item_id: props.data.id + '',
};
const response = await getData('user/activity/create', 'POST', data);
// this.setState({ activity_id: response.activity_id });
setActivity_id(response.activity_id);
}

const moveToAfterScreen = async () => {
const data = {
api_token: props.user.api_token,
activity_id: activity_id + '',
is_complete: true,
};

if (!props.network.isConnected) {
  Actions.after_play({ data: props.data, download: props.download });
  return;
}

const response = await getData('user/activity/edit', 'POST', data);

if (response.status) {
  props.dispatch(getActivity(props.user.api_token));
}
Actions.after_play({ data: props.data, download: props.download });

}

const finishCourseItem = async () => {
if (!props.network.isConnected) return;

props.dispatch(getItems(props.user.api_token));

if (props.active) {
  const data = {
    api_token: props.user.api_token,
    item_id: props.data.id,
    course_id: props.courseId,
  };
  const response = await getData('courses/progress/update', 'POST', data);

  if (response.status) {
    props.dispatch({
      type: 'GET_COURSES',
      api_token: props.user.api_token,
    });
  }
}

}

const show = () => {
// let { loaded } = this.state;
if (loaded) {
// this.setState({ show_loader: false });
setShowLoader(false);
} else {
// this.setState({ show_loader: false });
setShowLoader(false);
}
Animated.timing(marginTopAnim, {
toValue: 0,
duration: 2000,
useNativeDriver: false,
}).start();
Animated.timing(fadeAnim, {
toValue: 1,
duration: 2000,
useNativeDriver: false,
}).start();
}

const subscribe = () => {
Actions.subscribe({ image: props.data.image_file });
}

const onPlay = () => {
// this.setState({ pause: false });
setPause(false);
show();
createActivity();
props.scrollBottom();
MusicControl.setNowPlaying({
title: 'MyMedi',
duration: totalLength,
artwork: 'https://i.imgur.com/e1cpwdo.png',
});
// MusicControl.enableControl('play', true)
MusicControl.enableControl('pause', false)
}

const onPause = () => {
// this.setState({ pause: true });
setPause(true);
}

const onSlidingComplete = (value) => {
seek(value);
// this.setState({ pause: false });
setPause(false)
}

const getIsLock = () => {
const { user } = props;
const isAccess = user.access || user.is_vip || user.access_from_store;

if (isAccess) return !isAccess;
else return !props.data.is_free;

};
// let { file, file_bg, loader, show_loader } = this.state;
const { duration } = props.data;
const { theme, t } = props;

const styles = createStyle(theme);

const isLock = getIsLock();
let fileRef = file;
let file_bgRef = file_bg;

props.download
? (fileRef = 'file://' + RN_FS.DocumentDirectoryPath + '/meditation/' + fileRef)
: null;

props.download
? (file_bgRef = 'file://' + RN_FS.DocumentDirectoryPath + '/meditation/' + file_bgRef)
: null;

const file_to_play = props.app.bg_music ? file_bgRef : file;

// const { pause, fadeAnim, marginTopAnim, left, currentPosition, muted } = this.state;

return (
<View style={{ flex: 1, width: '100%' }}>
<Video
muted={muted}
paused={pause}
audioOnly={true}
playInBackground={true}
ignoreSilentSwitch="ignore"
source={{ uri: file_to_play }}
controls={Platform.OS == 'ios'}
onProgress={data => setTime(data)}
playWhenInactive={true}
mixWithOthers="inherit"
ref={ref => {
player = ref;
}}
onLoad={data => {
setDuration(data);
MusicControl.setNowPlaying({
title: 'MyMedi',
duration: data.duration,
artwork: 'https://i.imgur.com/e1cpwdo.png',
});
}}
onEnd={async () => {
await finishCourseItem();
await moveToAfterScreen();
MusicControl.resetNowPlaying()
MusicControl.stopControl();
}}
/>

<PlayerSlider
fadeAnim={fadeAnim}
isLoading={show_loader}
text={left}
value={currentPosition}
maxValue={duration}
onSlidingComplete={value => onSlidingComplete(value)}
onSlidingStart={() => onPause()}
/>

    {loader && (
      <ActivityIndicator
        size="large"
        color={theme.main}
        style={{
          bottom: Platform.OS === 'ios' ? theme.h(12) : theme.h(13),
        }}
      />
    )}

    {!loader && !isLock ? (
      <Animated.View style={[styles.controller, { bottom: marginTopAnim }]}>
        <RewindBtn
          opacity={fadeAnim}
          onPress={() => increase()}
          text={` +10${t('common.time.sec')}`}
          icon={<IncreaseBtn />}
          revert={!theme.isRTL}
        />

        <TouchableOpacity
          style={{ marginHorizontal: 30 }}
          onPress={pause ? () => onPlay() : () => onPause()}
        >
          {pause ? <PlayBtn /> : <PauseBtn />}
        </TouchableOpacity>

        <RewindBtn
          opacity={fadeAnim}
          onPress={() => decrease()}
          text={` -10${t('common.time.sec')}`}
          icon={<DecreaseBtn />}
          revert={theme.isRTL}
        />
      </Animated.View>
    ) : (
      <View style={{ width: '80%', marginHorizontal: 30 }}>
        <MainBtn text={t(`common.btn.joining`)} onPress={() => subscribe()} withLoading={false} />
      </View>
    )}
  </View>
</View>

);
}

const mapStateToProps = (state: any) => state;

export default connect(mapStateToProps)(withTheme(withTranslation()(AudioController)));

const createStyle = theme => {
return StyleSheet.create({
header_container: {
alignItems: 'center',
width: '100%',
justifyContent: 'center',
},
controller: {
flexDirection: theme.isRTL ? 'row' : 'row-reverse',
alignItems: 'center',
width: '100%',
justifyContent: 'center',
},
});
};

  1. Platform ?

    • iOS
    • Android
  1. Device
  • Simulator
  • Real device

I am using React-Native-Video Player with "'react-native-music-control" but in background mode Play pause controls are disabled. Seek bar moving good, Artwork is also showing but Player play , pause controls are not working.

@singhiam
Copy link
Author

singhiam commented Oct 5, 2022

@bradleyflood Can you please help me here.

@singhiam
Copy link
Author

singhiam commented Oct 5, 2022

IMG_9535

@bradfloodx
Copy link
Collaborator

Hi @singhiam, I recommend switching over to https://github.com/doublesymmetry/react-native-track-player

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants