diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml
index 85b3ee9..9f4f7dd 100644
--- a/android/app/src/main/AndroidManifest.xml
+++ b/android/app/src/main/AndroidManifest.xml
@@ -4,6 +4,8 @@
+
+
+ android:windowSoftInputMode="adjustResize"
+ android:name="com.ryanheise.audioservice.AudioServiceActivity"
+ android:name="com.yalantis.ucrop.UCropActivity"
+ android:screenOrientation="portrait"
+ android:theme="@style/Theme.AppCompat.Light.NoActionBar">
+
diff --git a/ios/Podfile.lock b/ios/Podfile.lock
index 5e2c2df..f1504a2 100644
--- a/ios/Podfile.lock
+++ b/ios/Podfile.lock
@@ -1,5 +1,7 @@
PODS:
- - audio_session (0.0.1):
+ - assets_audio_player (0.0.1):
+ - Flutter
+ - assets_audio_player_web (0.0.1):
- Flutter
- better_player (0.0.1):
- Cache (~> 6.0.0)
@@ -83,8 +85,6 @@ PODS:
- TOCropViewController (~> 2.6.1)
- image_picker (0.0.1):
- Flutter
- - just_audio (0.0.1):
- - Flutter
- nanopb (2.30908.0):
- nanopb/decode (= 2.30908.0)
- nanopb/encode (= 2.30908.0)
@@ -111,15 +111,14 @@ PODS:
- TOCropViewController (2.6.1)
- url_launcher_ios (0.0.1):
- Flutter
- - video_player_avfoundation (0.0.1):
- - Flutter
- wakelock (0.0.1):
- Flutter
- webview_flutter_wkwebview (0.0.1):
- Flutter
DEPENDENCIES:
- - audio_session (from `.symlinks/plugins/audio_session/ios`)
+ - assets_audio_player (from `.symlinks/plugins/assets_audio_player/ios`)
+ - assets_audio_player_web (from `.symlinks/plugins/assets_audio_player_web/ios`)
- better_player (from `.symlinks/plugins/better_player/ios`)
- firebase_core (from `.symlinks/plugins/firebase_core/ios`)
- firebase_messaging (from `.symlinks/plugins/firebase_messaging/ios`)
@@ -128,13 +127,11 @@ DEPENDENCIES:
- flutter_vibrate (from `.symlinks/plugins/flutter_vibrate/ios`)
- image_cropper (from `.symlinks/plugins/image_cropper/ios`)
- image_picker (from `.symlinks/plugins/image_picker/ios`)
- - just_audio (from `.symlinks/plugins/just_audio/ios`)
- path_provider_ios (from `.symlinks/plugins/path_provider_ios/ios`)
- permission_handler_apple (from `.symlinks/plugins/permission_handler_apple/ios`)
- record (from `.symlinks/plugins/record/ios`)
- sqflite (from `.symlinks/plugins/sqflite/ios`)
- url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`)
- - video_player_avfoundation (from `.symlinks/plugins/video_player_avfoundation/ios`)
- wakelock (from `.symlinks/plugins/wakelock/ios`)
- webview_flutter_wkwebview (from `.symlinks/plugins/webview_flutter_wkwebview/ios`)
@@ -158,8 +155,10 @@ SPEC REPOS:
- TOCropViewController
EXTERNAL SOURCES:
- audio_session:
- :path: ".symlinks/plugins/audio_session/ios"
+ assets_audio_player:
+ :path: ".symlinks/plugins/assets_audio_player/ios"
+ assets_audio_player_web:
+ :path: ".symlinks/plugins/assets_audio_player_web/ios"
better_player:
:path: ".symlinks/plugins/better_player/ios"
firebase_core:
@@ -176,8 +175,6 @@ EXTERNAL SOURCES:
:path: ".symlinks/plugins/image_cropper/ios"
image_picker:
:path: ".symlinks/plugins/image_picker/ios"
- just_audio:
- :path: ".symlinks/plugins/just_audio/ios"
path_provider_ios:
:path: ".symlinks/plugins/path_provider_ios/ios"
permission_handler_apple:
@@ -188,15 +185,14 @@ EXTERNAL SOURCES:
:path: ".symlinks/plugins/sqflite/ios"
url_launcher_ios:
:path: ".symlinks/plugins/url_launcher_ios/ios"
- video_player_avfoundation:
- :path: ".symlinks/plugins/video_player_avfoundation/ios"
wakelock:
:path: ".symlinks/plugins/wakelock/ios"
webview_flutter_wkwebview:
:path: ".symlinks/plugins/webview_flutter_wkwebview/ios"
SPEC CHECKSUMS:
- audio_session: 4f3e461722055d21515cf3261b64c973c062f345
+ assets_audio_player: edee322b9cb625571b830b35872ead1a295fd917
+ assets_audio_player_web: 19826380c44375761aa0b9053665c1e3fbc3b86b
better_player: 2406bfe8175203c7a46fa15f9d778d73b12e1646
Cache: 4ca7e00363fca5455f26534e5607634c820ffc2d
Firebase: 7e8fe528c161b9271d365217a74c16aaf834578e
@@ -216,7 +212,6 @@ SPEC CHECKSUMS:
HLSCachingReverseProxyServer: 59935e1e0244ad7f3375d75b5ef46e8eb26ab181
image_cropper: 60c2789d1f1a78c873235d4319ca0c34a69f2d98
image_picker: 541dcbb3b9cf32d87eacbd957845d8651d6c62c3
- just_audio: baa7252489dbcf47a4c7cc9ca663e9661c99aafa
nanopb: a0ba3315591a9ae0a16a309ee504766e90db0c96
path_provider_ios: 14f3d2fd28c4fdb42f44e0f751d12861c43cee02
permission_handler_apple: 44366e37eaf29454a1e7b1b7d736c2cceaeb17ce
@@ -227,7 +222,6 @@ SPEC CHECKSUMS:
sqflite: 6d358c025f5b867b29ed92fc697fd34924e11904
TOCropViewController: edfd4f25713d56905ad1e0b9f5be3fbe0f59c863
url_launcher_ios: 839c58cdb4279282219f5e248c3321761ff3c4de
- video_player_avfoundation: e489aac24ef5cf7af82702979ed16f2a5ef84cff
wakelock: d0fc7c864128eac40eba1617cb5264d9c940b46f
webview_flutter_wkwebview: 005fbd90c888a42c5690919a1527ecc6649e1162
diff --git a/ios/Runner/Info.plist b/ios/Runner/Info.plist
index 17f2a3a..d87332a 100644
--- a/ios/Runner/Info.plist
+++ b/ios/Runner/Info.plist
@@ -28,6 +28,10 @@
Main
FirebaseAppDelegateProxyEnabled
+ UIBackgroundModes
+
+ audio
+
NSMicrophoneUsageDescription
We need to access to the microphone to record audio file
NSPhotoLibraryUsageDescription
diff --git a/lib/services/app_initalizer.dart b/lib/services/app_initalizer.dart
index 33c0170..749460e 100644
--- a/lib/services/app_initalizer.dart
+++ b/lib/services/app_initalizer.dart
@@ -1,5 +1,4 @@
import 'package:didvan/models/settings_data.dart';
-import 'package:didvan/services/media/media.dart';
import 'package:didvan/services/storage/storage.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_messaging/firebase_messaging.dart';
@@ -15,7 +14,6 @@ class AppInitializer {
StorageService.appDocsDir =
(await getApplicationDocumentsDirectory()).path;
StorageService.appTempsDir = (await getTemporaryDirectory()).path;
- MediaService.init();
}
}
diff --git a/lib/services/media/media.dart b/lib/services/media/media.dart
index 5e6d816..e70e2de 100644
--- a/lib/services/media/media.dart
+++ b/lib/services/media/media.dart
@@ -6,22 +6,15 @@ import 'package:didvan/services/network/request_helper.dart';
import 'package:didvan/services/storage/storage.dart';
import 'package:flutter/foundation.dart';
import 'package:image_picker/image_picker.dart';
-import 'package:just_audio/just_audio.dart';
+import 'package:assets_audio_player/assets_audio_player.dart';
class MediaService {
- static final AudioPlayer audioPlayer = AudioPlayer();
+ static final audioPlayer = AssetsAudioPlayer();
static String? audioPlayerTag;
static StudioDetailsData? currentPodcast;
static StudioRequestArgs? podcastPlaylistArgs;
- static void init() {
- audioPlayer.positionStream.listen((event) {
- if (audioPlayer.duration != null && audioPlayer.duration! < event) {
- audioPlayer.stop();
- audioPlayer.seek(const Duration(seconds: 0));
- }
- });
- }
+ static Duration? get duration => audioPlayer.current.value?.audio.duration;
static Future handleAudioPlayback({
required dynamic audioSource,
@@ -37,31 +30,32 @@ class MediaService {
isNetworkAudio = false;
}
if (audioPlayerTag == tag) {
- if (audioPlayer.playing) {
- await audioPlayer.pause();
- } else {
- await audioPlayer.play();
- }
- } else {
- await audioPlayer.stop();
- audioPlayerTag = tag;
- if (isNetworkAudio) {
- await audioPlayer.setUrl(
+ await audioPlayer.playOrPause();
+ return;
+ }
+ await audioPlayer.stop();
+ audioPlayerTag = tag;
+ if (isNetworkAudio) {
+ await audioPlayer.open(
+ Audio.network(
isVoiceMessage
? (RequestHelper.baseUrl +
audioSource +
'?accessToken=${RequestService.token}')
: audioSource,
+ ),
+ );
+ } else {
+ if (kIsWeb) {
+ await audioPlayer.open(
+ Audio.network(audioSource!.replaceAll('%3A', ':')),
);
} else {
- if (kIsWeb) {
- await audioPlayer.setUrl(audioSource!.replaceAll('%3A', ':'));
- } else {
- await audioPlayer.setFilePath(audioSource);
- }
+ await audioPlayer.open(Audio.file(audioSource));
}
- audioPlayer.play();
}
+ audioPlayer.play();
+ audioPlayer.updateCurrentAudioNotification();
}
static Future resetAudioPlayer() async {
diff --git a/lib/views/home/direct/widgets/audio_widget.dart b/lib/views/home/direct/widgets/audio_widget.dart
index 5d99777..5f1c8bd 100644
--- a/lib/views/home/direct/widgets/audio_widget.dart
+++ b/lib/views/home/direct/widgets/audio_widget.dart
@@ -21,7 +21,7 @@ class AudioWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return StreamBuilder(
- stream: MediaService.audioPlayer.playingStream,
+ stream: MediaService.audioPlayer.isPlaying,
builder: (context, snapshot) {
return Row(
children: [
@@ -56,7 +56,7 @@ class _AudioControllerButton extends StatelessWidget {
@override
Widget build(BuildContext context) {
return DidvanIconButton(
- icon: MediaService.audioPlayer.playing == true && _nowPlaying
+ icon: MediaService.audioPlayer.isPlaying.value && _nowPlaying
? DidvanIcons.pause_circle_solid
: DidvanIcons.play_circle_solid,
color: Theme.of(context).colorScheme.focusedBorder,
diff --git a/lib/views/home/studio/studio_details/studio_details_state.dart b/lib/views/home/studio/studio_details/studio_details_state.dart
index 110c93f..14187cf 100644
--- a/lib/views/home/studio/studio_details/studio_details_state.dart
+++ b/lib/views/home/studio/studio_details/studio_details_state.dart
@@ -117,12 +117,12 @@ class StudioDetailsState extends CoreProvier {
);
if (nextStudio != null && !_positionListenerActivated) {
_positionListenerActivated = true;
- MediaService.audioPlayer.positionStream.listen((event) {
+ MediaService.audioPlayer.currentPosition.listen((event) {
if (MediaService.audioPlayerTag?.contains('message') == true) {
return;
}
- final duration = MediaService.audioPlayer.duration ??
- Duration(seconds: studio.duration);
+ final duration =
+ MediaService.duration ?? Duration(seconds: studio.duration);
if (event.compareTo(duration) > 0 && nextStudio != null) {
if (stopOnPodcastEnds) {
MediaService.resetAudioPlayer();
diff --git a/lib/views/home/widgets/audio/audio_player_widget.dart b/lib/views/home/widgets/audio/audio_player_widget.dart
index 5012e47..78db446 100644
--- a/lib/views/home/widgets/audio/audio_player_widget.dart
+++ b/lib/views/home/widgets/audio/audio_player_widget.dart
@@ -107,9 +107,9 @@ class AudioPlayerWidget extends StatelessWidget {
onPressed: () {
MediaService.audioPlayer.seek(
Duration(
- seconds:
- MediaService.audioPlayer.position.inSeconds +
- 30,
+ seconds: MediaService.audioPlayer.currentPosition
+ .value.inSeconds +
+ 30,
),
);
},
@@ -126,7 +126,7 @@ class AudioPlayerWidget extends StatelessWidget {
Expanded(
child: Center(
child: StreamBuilder(
- stream: MediaService.audioPlayer.playingStream,
+ stream: MediaService.audioPlayer.isPlaying,
builder: (context, snapshot) {
return _PlayPouseAnimatedIcon(
audioSource: podcast.link,
@@ -149,7 +149,8 @@ class AudioPlayerWidget extends StatelessWidget {
Duration(
seconds: max(
0,
- MediaService.audioPlayer.position.inSeconds -
+ MediaService.audioPlayer.currentPosition.value
+ .inSeconds -
10,
),
),
@@ -254,16 +255,15 @@ class AudioPlayerWidget extends StatelessWidget {
Padding(
padding: const EdgeInsets.symmetric(horizontal: 64),
child: DidvanButton(
- style: state.timerValue ==
- MediaService.audioPlayer.duration?.inMinutes &&
+ style: state.timerValue == MediaService.duration?.inMinutes &&
state.stopOnPodcastEnds
? ButtonStyleMode.primary
: ButtonStyleMode.flat,
title: 'پایان پادکست',
onPressed: () async {
- state.timerValue =
- MediaService.audioPlayer.duration!.inMinutes -
- MediaService.audioPlayer.position.inMinutes;
+ state.timerValue = MediaService.duration!.inMinutes -
+ MediaService
+ .audioPlayer.currentPosition.value.inMinutes;
await controller.animateTo(
state.timerValue * 10,
duration: DesignConfig.lowAnimationDuration,
@@ -337,7 +337,7 @@ class __PlayPouseAnimatedIconState extends State<_PlayPouseAnimatedIcon>
}
void _handleAnimation() {
- if (MediaService.audioPlayer.playing) {
+ if (MediaService.audioPlayer.isPlaying.value) {
_animationController.forward();
} else {
_animationController.reverse();
diff --git a/lib/views/home/widgets/audio/audio_slider.dart b/lib/views/home/widgets/audio/audio_slider.dart
index a65e126..bf8969e 100644
--- a/lib/views/home/widgets/audio/audio_slider.dart
+++ b/lib/views/home/widgets/audio/audio_slider.dart
@@ -26,7 +26,10 @@ class AudioSlider extends StatelessWidget {
child: Directionality(
textDirection: TextDirection.ltr,
child: StreamBuilder(
- stream: _isPlaying ? MediaService.audioPlayer.positionStream : null,
+ stream:
+ _isPlaying && MediaService.audioPlayer.currentPosition.hasValue
+ ? MediaService.audioPlayer.currentPosition
+ : null,
builder: (context, snapshot) => ProgressBar(
thumbColor: Theme.of(context).colorScheme.title,
progressBarColor: DesignConfig.isDark
@@ -34,12 +37,8 @@ class AudioSlider extends StatelessWidget {
: Theme.of(context).colorScheme.primary,
baseBarColor: Theme.of(context).colorScheme.border,
bufferedBarColor: Theme.of(context).colorScheme.splash,
- total: MediaService.audioPlayer.duration ??
- Duration(seconds: duration ?? 0),
+ total: MediaService.duration ?? Duration(seconds: duration ?? 0),
progress: snapshot.data ?? Duration.zero,
- buffered: _isPlaying
- ? MediaService.audioPlayer.bufferedPosition
- : Duration.zero,
thumbRadius: disableThumb ? 0 : 6,
barHeight: 3,
timeLabelTextStyle: TextStyle(
diff --git a/lib/views/widgets/didvan/bnb.dart b/lib/views/widgets/didvan/bnb.dart
index bcc6682..300ed8f 100644
--- a/lib/views/widgets/didvan/bnb.dart
+++ b/lib/views/widgets/didvan/bnb.dart
@@ -1,3 +1,4 @@
+import 'package:assets_audio_player/assets_audio_player.dart';
import 'package:didvan/config/design_config.dart';
import 'package:didvan/config/theme_data.dart';
import 'package:didvan/constants/app_icons.dart';
@@ -14,7 +15,6 @@ import 'package:didvan/views/widgets/skeleton_image.dart';
import 'package:expandable_bottom_sheet/expandable_bottom_sheet.dart';
import 'package:flutter/material.dart';
import 'package:flutter_spinkit/flutter_spinkit.dart';
-import 'package:just_audio/just_audio.dart';
import 'package:provider/provider.dart';
class DidvanBNB extends StatelessWidget {
@@ -106,7 +106,7 @@ class _PlayerNavBar extends StatelessWidget {
@override
Widget build(BuildContext context) {
return StreamBuilder(
- stream: MediaService.audioPlayer.playingStream,
+ stream: MediaService.audioPlayer.isPlaying,
builder: (context, snapshot) => GestureDetector(
onTap: () => MediaService.currentPodcast == null
? null
@@ -195,12 +195,10 @@ class _PlayerNavBar extends StatelessWidget {
],
),
),
- StreamBuilder(
- stream: MediaService.audioPlayer.playerStateStream,
+ StreamBuilder(
+ stream: MediaService.audioPlayer.onReadyToPlay,
builder: (context, snapshot) {
- final playerState = MediaService
- .audioPlayer.playerState.processingState;
- if (playerState == ProcessingState.loading ||
+ if (snapshot.data == null ||
state.appState == AppState.busy) {
return Padding(
padding: const EdgeInsets.only(
@@ -224,8 +222,7 @@ class _PlayerNavBar extends StatelessWidget {
},
),
if (state.appState != AppState.busy &&
- MediaService.audioPlayer.playerState.processingState !=
- ProcessingState.loading)
+ snapshot.data != null)
Padding(
padding: const EdgeInsets.only(
left: 12,
diff --git a/pubspec.lock b/pubspec.lock
index cbb3c93..f08bc28 100644
--- a/pubspec.lock
+++ b/pubspec.lock
@@ -1,6 +1,20 @@
# Generated by pub
# See https://dart.dev/tools/pub/glossary#lockfile
packages:
+ assets_audio_player:
+ dependency: "direct main"
+ description:
+ name: assets_audio_player
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "3.0.4+1"
+ assets_audio_player_web:
+ dependency: transitive
+ description:
+ name: assets_audio_player_web
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "3.0.4+1"
async:
dependency: transitive
description:
@@ -8,13 +22,6 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "2.8.2"
- audio_session:
- dependency: transitive
- description:
- name: audio_session
- url: "https://pub.dartlang.org"
- source: hosted
- version: "0.1.6+1"
audio_video_progress_bar:
dependency: "direct main"
description:
@@ -406,27 +413,6 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "0.6.3"
- just_audio:
- dependency: "direct main"
- description:
- name: just_audio
- url: "https://pub.dartlang.org"
- source: hosted
- version: "0.9.20"
- just_audio_platform_interface:
- dependency: transitive
- description:
- name: just_audio_platform_interface
- url: "https://pub.dartlang.org"
- source: hosted
- version: "4.1.0"
- just_audio_web:
- dependency: transitive
- description:
- name: just_audio_web
- url: "https://pub.dartlang.org"
- source: hosted
- version: "0.4.7"
lints:
dependency: transitive
description:
diff --git a/pubspec.yaml b/pubspec.yaml
index 63202fa..dfc7dfa 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -50,7 +50,6 @@ dependencies:
flutter_vibrate: ^1.3.0
universal_html: ^2.0.8
record: ^3.0.2
- just_audio: ^0.9.18
record_web: ^0.2.1
persian_datetime_picker: ^2.4.0
persian_number_utility: ^1.1.1
@@ -66,6 +65,7 @@ dependencies:
expandable_bottom_sheet: ^1.1.1+1
permission_handler: ^9.2.0
better_player: ^0.0.81
+ assets_audio_player: ^3.0.4+1
dev_dependencies: