├── starter ├── ios │ ├── Flutter │ │ ├── Debug.xcconfig │ │ ├── Release.xcconfig │ │ └── AppFrameworkInfo.plist │ ├── Runner │ │ ├── Runner-Bridging-Header.h │ │ ├── Assets.xcassets │ │ │ ├── LaunchImage.imageset │ │ │ │ ├── LaunchImage.png │ │ │ │ ├── LaunchImage@2x.png │ │ │ │ ├── LaunchImage@3x.png │ │ │ │ ├── README.md │ │ │ │ └── Contents.json │ │ │ └── AppIcon.appiconset │ │ │ │ ├── Icon-App-20x20@1x.png │ │ │ │ ├── Icon-App-20x20@2x.png │ │ │ │ ├── Icon-App-20x20@3x.png │ │ │ │ ├── Icon-App-29x29@1x.png │ │ │ │ ├── Icon-App-29x29@2x.png │ │ │ │ ├── Icon-App-29x29@3x.png │ │ │ │ ├── Icon-App-40x40@1x.png │ │ │ │ ├── Icon-App-40x40@2x.png │ │ │ │ ├── Icon-App-40x40@3x.png │ │ │ │ ├── Icon-App-60x60@2x.png │ │ │ │ ├── Icon-App-60x60@3x.png │ │ │ │ ├── Icon-App-76x76@1x.png │ │ │ │ ├── Icon-App-76x76@2x.png │ │ │ │ ├── Icon-App-1024x1024@1x.png │ │ │ │ ├── Icon-App-83.5x83.5@2x.png │ │ │ │ └── Contents.json │ │ ├── AppDelegate.swift │ │ ├── Base.lproj │ │ │ ├── Main.storyboard │ │ │ └── LaunchScreen.storyboard │ │ └── Info.plist │ ├── Runner.xcodeproj │ │ ├── project.xcworkspace │ │ │ ├── contents.xcworkspacedata │ │ │ └── xcshareddata │ │ │ │ ├── WorkspaceSettings.xcsettings │ │ │ │ └── IDEWorkspaceChecks.plist │ │ └── xcshareddata │ │ │ └── xcschemes │ │ │ └── Runner.xcscheme │ ├── Runner.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ ├── WorkspaceSettings.xcsettings │ │ │ └── IDEWorkspaceChecks.plist │ ├── RunnerTests │ │ └── RunnerTests.swift │ └── .gitignore ├── macos │ ├── Flutter │ │ ├── Flutter-Debug.xcconfig │ │ ├── Flutter-Release.xcconfig │ │ └── GeneratedPluginRegistrant.swift │ ├── Runner │ │ ├── Configs │ │ │ ├── Debug.xcconfig │ │ │ ├── Release.xcconfig │ │ │ ├── Warnings.xcconfig │ │ │ └── AppInfo.xcconfig │ │ ├── Assets.xcassets │ │ │ └── AppIcon.appiconset │ │ │ │ ├── app_icon_16.png │ │ │ │ ├── app_icon_32.png │ │ │ │ ├── app_icon_64.png │ │ │ │ ├── app_icon_1024.png │ │ │ │ ├── app_icon_128.png │ │ │ │ ├── app_icon_256.png │ │ │ │ ├── app_icon_512.png │ │ │ │ └── Contents.json │ │ ├── Release.entitlements │ │ ├── AppDelegate.swift │ │ ├── DebugProfile.entitlements │ │ ├── MainFlutterWindow.swift │ │ └── Info.plist │ ├── .gitignore │ ├── Runner.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ ├── Runner.xcodeproj │ │ ├── project.xcworkspace │ │ │ └── xcshareddata │ │ │ │ └── IDEWorkspaceChecks.plist │ │ └── xcshareddata │ │ │ └── xcschemes │ │ │ └── Runner.xcscheme │ └── RunnerTests │ │ └── RunnerTests.swift ├── web │ ├── favicon.png │ ├── icons │ │ ├── Icon-192.png │ │ ├── Icon-512.png │ │ ├── Icon-maskable-192.png │ │ └── Icon-maskable-512.png │ ├── manifest.json │ └── index.html ├── android │ ├── app │ │ ├── src │ │ │ ├── main │ │ │ │ ├── res │ │ │ │ │ ├── mipmap-hdpi │ │ │ │ │ │ └── ic_launcher.png │ │ │ │ │ ├── mipmap-mdpi │ │ │ │ │ │ └── ic_launcher.png │ │ │ │ │ ├── mipmap-xhdpi │ │ │ │ │ │ └── ic_launcher.png │ │ │ │ │ ├── mipmap-xxhdpi │ │ │ │ │ │ └── ic_launcher.png │ │ │ │ │ ├── mipmap-xxxhdpi │ │ │ │ │ │ └── ic_launcher.png │ │ │ │ │ ├── drawable │ │ │ │ │ │ └── launch_background.xml │ │ │ │ │ ├── drawable-v21 │ │ │ │ │ │ └── launch_background.xml │ │ │ │ │ ├── values │ │ │ │ │ │ └── styles.xml │ │ │ │ │ └── values-night │ │ │ │ │ │ └── styles.xml │ │ │ │ ├── kotlin │ │ │ │ │ └── com │ │ │ │ │ │ └── example │ │ │ │ │ │ └── flutter_audio_service_demo │ │ │ │ │ │ └── MainActivity.kt │ │ │ │ └── AndroidManifest.xml │ │ │ ├── debug │ │ │ │ └── AndroidManifest.xml │ │ │ └── profile │ │ │ │ └── AndroidManifest.xml │ │ └── build.gradle.kts │ ├── gradle.properties │ ├── gradle │ │ └── wrapper │ │ │ └── gradle-wrapper.properties │ ├── .gitignore │ ├── build.gradle.kts │ └── settings.gradle.kts ├── analysis_options.yaml ├── lib │ ├── notifiers │ │ ├── play_button_notifier.dart │ │ ├── repeat_button_notifier.dart │ │ └── progress_notifier.dart │ ├── services │ │ ├── service_locator.dart │ │ └── playlist_repository.dart │ ├── page_manager.dart │ └── main.dart ├── pubspec.yaml ├── README.md ├── .gitignore ├── .metadata └── pubspec.lock ├── final ├── ios │ ├── Runner │ │ ├── Runner-Bridging-Header.h │ │ ├── Assets.xcassets │ │ │ ├── LaunchImage.imageset │ │ │ │ ├── LaunchImage.png │ │ │ │ ├── LaunchImage@2x.png │ │ │ │ ├── LaunchImage@3x.png │ │ │ │ ├── README.md │ │ │ │ └── Contents.json │ │ │ └── AppIcon.appiconset │ │ │ │ ├── Icon-App-20x20@1x.png │ │ │ │ ├── Icon-App-20x20@2x.png │ │ │ │ ├── Icon-App-20x20@3x.png │ │ │ │ ├── Icon-App-29x29@1x.png │ │ │ │ ├── Icon-App-29x29@2x.png │ │ │ │ ├── Icon-App-29x29@3x.png │ │ │ │ ├── Icon-App-40x40@1x.png │ │ │ │ ├── Icon-App-40x40@2x.png │ │ │ │ ├── Icon-App-40x40@3x.png │ │ │ │ ├── Icon-App-60x60@2x.png │ │ │ │ ├── Icon-App-60x60@3x.png │ │ │ │ ├── Icon-App-76x76@1x.png │ │ │ │ ├── Icon-App-76x76@2x.png │ │ │ │ ├── Icon-App-1024x1024@1x.png │ │ │ │ ├── Icon-App-83.5x83.5@2x.png │ │ │ │ └── Contents.json │ │ ├── AppDelegate.swift │ │ ├── Base.lproj │ │ │ ├── Main.storyboard │ │ │ └── LaunchScreen.storyboard │ │ └── Info.plist │ ├── Flutter │ │ ├── Debug.xcconfig │ │ ├── Release.xcconfig │ │ └── AppFrameworkInfo.plist │ ├── Runner.xcodeproj │ │ ├── project.xcworkspace │ │ │ ├── contents.xcworkspacedata │ │ │ └── xcshareddata │ │ │ │ ├── WorkspaceSettings.xcsettings │ │ │ │ └── IDEWorkspaceChecks.plist │ │ └── xcshareddata │ │ │ └── xcschemes │ │ │ └── Runner.xcscheme │ ├── Runner.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ ├── WorkspaceSettings.xcsettings │ │ │ └── IDEWorkspaceChecks.plist │ ├── .gitignore │ ├── Podfile │ └── Podfile.lock ├── web │ ├── favicon.png │ ├── icons │ │ ├── Icon-192.png │ │ ├── Icon-512.png │ │ ├── Icon-maskable-192.png │ │ └── Icon-maskable-512.png │ ├── manifest.json │ └── index.html ├── android │ ├── gradle.properties │ ├── app │ │ ├── src │ │ │ ├── main │ │ │ │ ├── res │ │ │ │ │ ├── mipmap-hdpi │ │ │ │ │ │ └── ic_launcher.png │ │ │ │ │ ├── mipmap-mdpi │ │ │ │ │ │ └── ic_launcher.png │ │ │ │ │ ├── mipmap-xhdpi │ │ │ │ │ │ └── ic_launcher.png │ │ │ │ │ ├── mipmap-xxhdpi │ │ │ │ │ │ └── ic_launcher.png │ │ │ │ │ ├── mipmap-xxxhdpi │ │ │ │ │ │ └── ic_launcher.png │ │ │ │ │ ├── drawable │ │ │ │ │ │ └── launch_background.xml │ │ │ │ │ ├── drawable-v21 │ │ │ │ │ │ └── launch_background.xml │ │ │ │ │ ├── values │ │ │ │ │ │ └── styles.xml │ │ │ │ │ └── values-night │ │ │ │ │ │ └── styles.xml │ │ │ │ ├── kotlin │ │ │ │ │ └── dev │ │ │ │ │ │ └── suragch │ │ │ │ │ │ └── flutter_audio_service_demo │ │ │ │ │ │ └── MainActivity.kt │ │ │ │ └── AndroidManifest.xml │ │ │ ├── debug │ │ │ │ └── AndroidManifest.xml │ │ │ └── profile │ │ │ │ └── AndroidManifest.xml │ │ └── build.gradle │ ├── gradle │ │ └── wrapper │ │ │ └── gradle-wrapper.properties │ ├── .gitignore │ ├── settings.gradle │ └── build.gradle ├── macos │ ├── Runner │ │ ├── Configs │ │ │ ├── Debug.xcconfig │ │ │ ├── Release.xcconfig │ │ │ ├── Warnings.xcconfig │ │ │ └── AppInfo.xcconfig │ │ ├── Assets.xcassets │ │ │ └── AppIcon.appiconset │ │ │ │ ├── app_icon_16.png │ │ │ │ ├── app_icon_32.png │ │ │ │ ├── app_icon_64.png │ │ │ │ ├── app_icon_1024.png │ │ │ │ ├── app_icon_128.png │ │ │ │ ├── app_icon_256.png │ │ │ │ ├── app_icon_512.png │ │ │ │ └── Contents.json │ │ ├── AppDelegate.swift │ │ ├── Release.entitlements │ │ ├── MainFlutterWindow.swift │ │ ├── DebugProfile.entitlements │ │ └── Info.plist │ ├── .gitignore │ ├── Flutter │ │ ├── Flutter-Debug.xcconfig │ │ ├── Flutter-Release.xcconfig │ │ └── GeneratedPluginRegistrant.swift │ ├── Runner.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ ├── Runner.xcodeproj │ │ ├── project.xcworkspace │ │ │ └── xcshareddata │ │ │ │ └── IDEWorkspaceChecks.plist │ │ └── xcshareddata │ │ │ └── xcschemes │ │ │ └── Runner.xcscheme │ ├── Podfile │ └── Podfile.lock ├── analysis_options.yaml ├── lib │ ├── notifiers │ │ ├── play_button_notifier.dart │ │ ├── repeat_button_notifier.dart │ │ └── progress_notifier.dart │ ├── services │ │ ├── service_locator.dart │ │ ├── playlist_repository.dart │ │ └── audio_handler.dart │ ├── page_manager.dart │ └── main.dart ├── pubspec.yaml ├── README.md ├── .gitignore ├── .metadata └── pubspec.lock ├── README.md ├── .gitignore └── LICENSE /starter/ios/Flutter/Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Generated.xcconfig" 2 | -------------------------------------------------------------------------------- /starter/ios/Flutter/Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Generated.xcconfig" 2 | -------------------------------------------------------------------------------- /final/ios/Runner/Runner-Bridging-Header.h: -------------------------------------------------------------------------------- 1 | #import "GeneratedPluginRegistrant.h" 2 | -------------------------------------------------------------------------------- /starter/ios/Runner/Runner-Bridging-Header.h: -------------------------------------------------------------------------------- 1 | #import "GeneratedPluginRegistrant.h" 2 | -------------------------------------------------------------------------------- /starter/macos/Flutter/Flutter-Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include "ephemeral/Flutter-Generated.xcconfig" 2 | -------------------------------------------------------------------------------- /starter/macos/Flutter/Flutter-Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include "ephemeral/Flutter-Generated.xcconfig" 2 | -------------------------------------------------------------------------------- /final/web/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/suragch/flutter_audio_service_demo/HEAD/final/web/favicon.png -------------------------------------------------------------------------------- /starter/web/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/suragch/flutter_audio_service_demo/HEAD/starter/web/favicon.png -------------------------------------------------------------------------------- /final/android/gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.jvmargs=-Xmx1536M 2 | android.useAndroidX=true 3 | android.enableJetifier=true 4 | -------------------------------------------------------------------------------- /final/macos/Runner/Configs/Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include "../../Flutter/Flutter-Debug.xcconfig" 2 | #include "Warnings.xcconfig" 3 | -------------------------------------------------------------------------------- /final/web/icons/Icon-192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/suragch/flutter_audio_service_demo/HEAD/final/web/icons/Icon-192.png -------------------------------------------------------------------------------- /final/web/icons/Icon-512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/suragch/flutter_audio_service_demo/HEAD/final/web/icons/Icon-512.png -------------------------------------------------------------------------------- /starter/macos/Runner/Configs/Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include "../../Flutter/Flutter-Debug.xcconfig" 2 | #include "Warnings.xcconfig" 3 | -------------------------------------------------------------------------------- /final/macos/Runner/Configs/Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include "../../Flutter/Flutter-Release.xcconfig" 2 | #include "Warnings.xcconfig" 3 | -------------------------------------------------------------------------------- /starter/macos/Runner/Configs/Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include "../../Flutter/Flutter-Release.xcconfig" 2 | #include "Warnings.xcconfig" 3 | -------------------------------------------------------------------------------- /starter/web/icons/Icon-192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/suragch/flutter_audio_service_demo/HEAD/starter/web/icons/Icon-192.png -------------------------------------------------------------------------------- /starter/web/icons/Icon-512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/suragch/flutter_audio_service_demo/HEAD/starter/web/icons/Icon-512.png -------------------------------------------------------------------------------- /final/macos/.gitignore: -------------------------------------------------------------------------------- 1 | # Flutter-related 2 | **/Flutter/ephemeral/ 3 | **/Pods/ 4 | 5 | # Xcode-related 6 | **/dgph 7 | **/xcuserdata/ 8 | -------------------------------------------------------------------------------- /starter/macos/.gitignore: -------------------------------------------------------------------------------- 1 | # Flutter-related 2 | **/Flutter/ephemeral/ 3 | **/Pods/ 4 | 5 | # Xcode-related 6 | **/dgph 7 | **/xcuserdata/ 8 | -------------------------------------------------------------------------------- /final/ios/Flutter/Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" 2 | #include "Generated.xcconfig" 3 | -------------------------------------------------------------------------------- /final/web/icons/Icon-maskable-192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/suragch/flutter_audio_service_demo/HEAD/final/web/icons/Icon-maskable-192.png -------------------------------------------------------------------------------- /final/web/icons/Icon-maskable-512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/suragch/flutter_audio_service_demo/HEAD/final/web/icons/Icon-maskable-512.png -------------------------------------------------------------------------------- /starter/web/icons/Icon-maskable-192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/suragch/flutter_audio_service_demo/HEAD/starter/web/icons/Icon-maskable-192.png -------------------------------------------------------------------------------- /starter/web/icons/Icon-maskable-512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/suragch/flutter_audio_service_demo/HEAD/starter/web/icons/Icon-maskable-512.png -------------------------------------------------------------------------------- /final/ios/Flutter/Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" 2 | #include "Generated.xcconfig" 3 | -------------------------------------------------------------------------------- /final/macos/Flutter/Flutter-Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" 2 | #include "ephemeral/Flutter-Generated.xcconfig" 3 | -------------------------------------------------------------------------------- /final/macos/Flutter/Flutter-Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" 2 | #include "ephemeral/Flutter-Generated.xcconfig" 3 | -------------------------------------------------------------------------------- /final/android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/suragch/flutter_audio_service_demo/HEAD/final/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /final/android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/suragch/flutter_audio_service_demo/HEAD/final/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /final/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/suragch/flutter_audio_service_demo/HEAD/final/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /final/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/suragch/flutter_audio_service_demo/HEAD/final/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /final/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/suragch/flutter_audio_service_demo/HEAD/final/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /starter/android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/suragch/flutter_audio_service_demo/HEAD/starter/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /starter/android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/suragch/flutter_audio_service_demo/HEAD/starter/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /starter/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/suragch/flutter_audio_service_demo/HEAD/starter/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /starter/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/suragch/flutter_audio_service_demo/HEAD/starter/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /starter/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/suragch/flutter_audio_service_demo/HEAD/starter/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /final/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/suragch/flutter_audio_service_demo/HEAD/final/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png -------------------------------------------------------------------------------- /final/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/suragch/flutter_audio_service_demo/HEAD/final/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png -------------------------------------------------------------------------------- /final/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/suragch/flutter_audio_service_demo/HEAD/final/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png -------------------------------------------------------------------------------- /final/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/suragch/flutter_audio_service_demo/HEAD/final/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png -------------------------------------------------------------------------------- /final/analysis_options.yaml: -------------------------------------------------------------------------------- 1 | include: package:flutter_lints/flutter.yaml 2 | 3 | analyzer: 4 | exclude: [build/**] 5 | language: 6 | strict-raw-types: true 7 | strong-mode: 8 | implicit-casts: false -------------------------------------------------------------------------------- /final/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/suragch/flutter_audio_service_demo/HEAD/final/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png -------------------------------------------------------------------------------- /final/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/suragch/flutter_audio_service_demo/HEAD/final/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png -------------------------------------------------------------------------------- /final/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/suragch/flutter_audio_service_demo/HEAD/final/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png -------------------------------------------------------------------------------- /final/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/suragch/flutter_audio_service_demo/HEAD/final/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png -------------------------------------------------------------------------------- /starter/android/gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.jvmargs=-Xmx8G -XX:MaxMetaspaceSize=4G -XX:ReservedCodeCacheSize=512m -XX:+HeapDumpOnOutOfMemoryError 2 | android.useAndroidX=true 3 | android.enableJetifier=true 4 | -------------------------------------------------------------------------------- /starter/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/suragch/flutter_audio_service_demo/HEAD/starter/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png -------------------------------------------------------------------------------- /starter/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/suragch/flutter_audio_service_demo/HEAD/starter/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png -------------------------------------------------------------------------------- /starter/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/suragch/flutter_audio_service_demo/HEAD/starter/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png -------------------------------------------------------------------------------- /starter/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/suragch/flutter_audio_service_demo/HEAD/starter/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png -------------------------------------------------------------------------------- /final/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/suragch/flutter_audio_service_demo/HEAD/final/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png -------------------------------------------------------------------------------- /final/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/suragch/flutter_audio_service_demo/HEAD/final/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png -------------------------------------------------------------------------------- /final/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/suragch/flutter_audio_service_demo/HEAD/final/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png -------------------------------------------------------------------------------- /final/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/suragch/flutter_audio_service_demo/HEAD/final/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png -------------------------------------------------------------------------------- /final/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/suragch/flutter_audio_service_demo/HEAD/final/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png -------------------------------------------------------------------------------- /final/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/suragch/flutter_audio_service_demo/HEAD/final/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png -------------------------------------------------------------------------------- /final/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/suragch/flutter_audio_service_demo/HEAD/final/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png -------------------------------------------------------------------------------- /final/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/suragch/flutter_audio_service_demo/HEAD/final/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png -------------------------------------------------------------------------------- /final/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/suragch/flutter_audio_service_demo/HEAD/final/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png -------------------------------------------------------------------------------- /final/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/suragch/flutter_audio_service_demo/HEAD/final/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png -------------------------------------------------------------------------------- /final/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/suragch/flutter_audio_service_demo/HEAD/final/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png -------------------------------------------------------------------------------- /final/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/suragch/flutter_audio_service_demo/HEAD/final/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png -------------------------------------------------------------------------------- /final/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/suragch/flutter_audio_service_demo/HEAD/final/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png -------------------------------------------------------------------------------- /final/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/suragch/flutter_audio_service_demo/HEAD/final/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png -------------------------------------------------------------------------------- /final/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/suragch/flutter_audio_service_demo/HEAD/final/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png -------------------------------------------------------------------------------- /starter/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/suragch/flutter_audio_service_demo/HEAD/starter/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png -------------------------------------------------------------------------------- /starter/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/suragch/flutter_audio_service_demo/HEAD/starter/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png -------------------------------------------------------------------------------- /starter/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/suragch/flutter_audio_service_demo/HEAD/starter/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png -------------------------------------------------------------------------------- /starter/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/suragch/flutter_audio_service_demo/HEAD/starter/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png -------------------------------------------------------------------------------- /starter/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/suragch/flutter_audio_service_demo/HEAD/starter/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png -------------------------------------------------------------------------------- /starter/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/suragch/flutter_audio_service_demo/HEAD/starter/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png -------------------------------------------------------------------------------- /starter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/suragch/flutter_audio_service_demo/HEAD/starter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png -------------------------------------------------------------------------------- /starter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/suragch/flutter_audio_service_demo/HEAD/starter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png -------------------------------------------------------------------------------- /starter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/suragch/flutter_audio_service_demo/HEAD/starter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png -------------------------------------------------------------------------------- /starter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/suragch/flutter_audio_service_demo/HEAD/starter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png -------------------------------------------------------------------------------- /starter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/suragch/flutter_audio_service_demo/HEAD/starter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png -------------------------------------------------------------------------------- /starter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/suragch/flutter_audio_service_demo/HEAD/starter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png -------------------------------------------------------------------------------- /starter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/suragch/flutter_audio_service_demo/HEAD/starter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png -------------------------------------------------------------------------------- /starter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/suragch/flutter_audio_service_demo/HEAD/starter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png -------------------------------------------------------------------------------- /starter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/suragch/flutter_audio_service_demo/HEAD/starter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png -------------------------------------------------------------------------------- /starter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/suragch/flutter_audio_service_demo/HEAD/starter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png -------------------------------------------------------------------------------- /starter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/suragch/flutter_audio_service_demo/HEAD/starter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png -------------------------------------------------------------------------------- /starter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/suragch/flutter_audio_service_demo/HEAD/starter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png -------------------------------------------------------------------------------- /starter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/suragch/flutter_audio_service_demo/HEAD/starter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png -------------------------------------------------------------------------------- /final/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/suragch/flutter_audio_service_demo/HEAD/final/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png -------------------------------------------------------------------------------- /final/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/suragch/flutter_audio_service_demo/HEAD/final/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png -------------------------------------------------------------------------------- /starter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/suragch/flutter_audio_service_demo/HEAD/starter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png -------------------------------------------------------------------------------- /starter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/suragch/flutter_audio_service_demo/HEAD/starter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png -------------------------------------------------------------------------------- /final/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /starter/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /starter/ios/Runner.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /starter/macos/Runner.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /starter/android/app/src/main/kotlin/com/example/flutter_audio_service_demo/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package com.example.flutter_audio_service_demo 2 | 3 | import io.flutter.embedding.android.FlutterActivity 4 | 5 | class MainActivity : FlutterActivity() 6 | -------------------------------------------------------------------------------- /starter/macos/Flutter/GeneratedPluginRegistrant.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Generated file. Do not edit. 3 | // 4 | 5 | import FlutterMacOS 6 | import Foundation 7 | 8 | 9 | func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { 10 | } 11 | -------------------------------------------------------------------------------- /final/android/app/src/main/kotlin/dev/suragch/flutter_audio_service_demo/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package dev.suragch.flutter_audio_service_demo 2 | 3 | import io.flutter.embedding.android.FlutterActivity 4 | 5 | class MainActivity: FlutterActivity() { 6 | } 7 | -------------------------------------------------------------------------------- /starter/analysis_options.yaml: -------------------------------------------------------------------------------- 1 | include: package:flutter_lints/flutter.yaml 2 | 3 | analyzer: 4 | exclude: [build/**] 5 | language: 6 | strict-raw-types: true 7 | strong-mode: 8 | implicit-casts: false 9 | 10 | formatter: 11 | page_width: 80 -------------------------------------------------------------------------------- /final/android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | zipStoreBase=GRADLE_USER_HOME 4 | zipStorePath=wrapper/dists 5 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-all.zip 6 | -------------------------------------------------------------------------------- /starter/android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | zipStoreBase=GRADLE_USER_HOME 4 | zipStorePath=wrapper/dists 5 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.12-all.zip 6 | -------------------------------------------------------------------------------- /final/macos/Runner/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | import Cocoa 2 | import FlutterMacOS 3 | 4 | @NSApplicationMain 5 | class AppDelegate: FlutterAppDelegate { 6 | override func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool { 7 | return true 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /starter/macos/Runner/Release.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.app-sandbox 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /final/ios/Runner.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /final/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreviewsEnabled 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /final/macos/Runner.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /starter/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreviewsEnabled 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /starter/lib/notifiers/play_button_notifier.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/foundation.dart'; 2 | 3 | class PlayButtonNotifier extends ValueNotifier { 4 | PlayButtonNotifier() : super(_initialValue); 5 | static const _initialValue = ButtonState.paused; 6 | } 7 | 8 | enum ButtonState { paused, playing, loading } 9 | -------------------------------------------------------------------------------- /final/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /final/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /starter/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /starter/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /final/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreviewsEnabled 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /starter/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreviewsEnabled 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /starter/android/.gitignore: -------------------------------------------------------------------------------- 1 | gradle-wrapper.jar 2 | /.gradle 3 | /captures/ 4 | /gradlew 5 | /gradlew.bat 6 | /local.properties 7 | GeneratedPluginRegistrant.java 8 | .cxx/ 9 | 10 | # Remember to never publicly share your keystore. 11 | # See https://flutter.dev/to/reference-keystore 12 | key.properties 13 | **/*.keystore 14 | **/*.jks 15 | -------------------------------------------------------------------------------- /final/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /final/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /starter/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /starter/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /final/lib/notifiers/play_button_notifier.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/foundation.dart'; 2 | 3 | class PlayButtonNotifier extends ValueNotifier { 4 | PlayButtonNotifier() : super(_initialValue); 5 | static const _initialValue = ButtonState.paused; 6 | } 7 | 8 | enum ButtonState { 9 | paused, 10 | playing, 11 | loading, 12 | } 13 | -------------------------------------------------------------------------------- /final/android/.gitignore: -------------------------------------------------------------------------------- 1 | gradle-wrapper.jar 2 | /.gradle 3 | /captures/ 4 | /gradlew 5 | /gradlew.bat 6 | /local.properties 7 | GeneratedPluginRegistrant.java 8 | 9 | # Remember to never publicly share your keystore. 10 | # See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app 11 | key.properties 12 | **/*.keystore 13 | **/*.jks 14 | -------------------------------------------------------------------------------- /final/macos/Runner/Release.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.app-sandbox 6 | 7 | com.apple.security.network.client 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /starter/ios/RunnerTests/RunnerTests.swift: -------------------------------------------------------------------------------- 1 | import Flutter 2 | import UIKit 3 | import XCTest 4 | 5 | class RunnerTests: XCTestCase { 6 | 7 | func testExample() { 8 | // If you add code to the Runner application, consider adding tests here. 9 | // See https://developer.apple.com/documentation/xctest for more information about using XCTest. 10 | } 11 | 12 | } 13 | -------------------------------------------------------------------------------- /starter/macos/RunnerTests/RunnerTests.swift: -------------------------------------------------------------------------------- 1 | import Cocoa 2 | import FlutterMacOS 3 | import XCTest 4 | 5 | class RunnerTests: XCTestCase { 6 | 7 | func testExample() { 8 | // If you add code to the Runner application, consider adding tests here. 9 | // See https://developer.apple.com/documentation/xctest for more information about using XCTest. 10 | } 11 | 12 | } 13 | -------------------------------------------------------------------------------- /final/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md: -------------------------------------------------------------------------------- 1 | # Launch Screen Assets 2 | 3 | You can customize the launch screen with your own desired assets by replacing the image files in this directory. 4 | 5 | You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images. -------------------------------------------------------------------------------- /starter/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md: -------------------------------------------------------------------------------- 1 | # Launch Screen Assets 2 | 3 | You can customize the launch screen with your own desired assets by replacing the image files in this directory. 4 | 5 | You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images. -------------------------------------------------------------------------------- /starter/macos/Runner/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | import Cocoa 2 | import FlutterMacOS 3 | 4 | @main 5 | class AppDelegate: FlutterAppDelegate { 6 | override func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool { 7 | return true 8 | } 9 | 10 | override func applicationSupportsSecureRestorableState(_ app: NSApplication) -> Bool { 11 | return true 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /starter/android/app/src/debug/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /starter/android/app/src/profile/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /starter/lib/services/service_locator.dart: -------------------------------------------------------------------------------- 1 | import '../page_manager.dart'; 2 | import 'playlist_repository.dart'; 3 | import 'package:get_it/get_it.dart'; 4 | 5 | GetIt getIt = GetIt.instance; 6 | 7 | Future setupServiceLocator() async { 8 | // services 9 | getIt.registerLazySingleton(() => DemoPlaylist()); 10 | 11 | // page state 12 | getIt.registerLazySingleton(() => PageManager()); 13 | } 14 | -------------------------------------------------------------------------------- /starter/macos/Runner/DebugProfile.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.app-sandbox 6 | 7 | com.apple.security.cs.allow-jit 8 | 9 | com.apple.security.network.server 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /starter/ios/Runner/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | import Flutter 2 | import UIKit 3 | 4 | @main 5 | @objc class AppDelegate: FlutterAppDelegate { 6 | override func application( 7 | _ application: UIApplication, 8 | didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? 9 | ) -> Bool { 10 | GeneratedPluginRegistrant.register(with: self) 11 | return super.application(application, didFinishLaunchingWithOptions: launchOptions) 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /starter/lib/notifiers/repeat_button_notifier.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/foundation.dart'; 2 | 3 | class RepeatButtonNotifier extends ValueNotifier { 4 | RepeatButtonNotifier() : super(_initialValue); 5 | static const _initialValue = RepeatState.off; 6 | 7 | void nextState() { 8 | final next = (value.index + 1) % RepeatState.values.length; 9 | value = RepeatState.values[next]; 10 | } 11 | } 12 | 13 | enum RepeatState { off, repeatSong, repeatPlaylist } 14 | -------------------------------------------------------------------------------- /starter/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: flutter_audio_service_demo 2 | description: Companion project for tutorial on audio_service plugin. 3 | publish_to: 'none' 4 | 5 | version: 1.0.0+1 6 | 7 | environment: 8 | sdk: ^3.8.0 9 | 10 | dependencies: 11 | flutter: 12 | sdk: flutter 13 | audio_video_progress_bar: ^2.0.3 14 | get_it: ^8.0.3 15 | 16 | dev_dependencies: 17 | flutter_lints: any 18 | flutter_test: 19 | sdk: flutter 20 | 21 | flutter: 22 | uses-material-design: true -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # flutter_audio_service_demo 2 | 3 | This is a companion project for the tutorial [Background audio in Flutter with Audio Service and Just Audio](https://suragch.medium.com/background-audio-in-flutter-with-audio-service-and-just-audio-3cce17b4a7d) about the [audio_service](https://pub.dev/packages/audio_service) plugin. 4 | 5 | Open the **starter** project to follow along with the tutorial or the **final** project to see the end results. [Here](https://vimeo.com/575737609) is a video demo. -------------------------------------------------------------------------------- /final/ios/Runner/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | import Flutter 3 | 4 | @UIApplicationMain 5 | @objc class AppDelegate: FlutterAppDelegate { 6 | override func application( 7 | _ application: UIApplication, 8 | didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? 9 | ) -> Bool { 10 | GeneratedPluginRegistrant.register(with: self) 11 | return super.application(application, didFinishLaunchingWithOptions: launchOptions) 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /starter/macos/Runner/MainFlutterWindow.swift: -------------------------------------------------------------------------------- 1 | import Cocoa 2 | import FlutterMacOS 3 | 4 | class MainFlutterWindow: NSWindow { 5 | override func awakeFromNib() { 6 | let flutterViewController = FlutterViewController() 7 | let windowFrame = self.frame 8 | self.contentViewController = flutterViewController 9 | self.setFrame(windowFrame, display: true) 10 | 11 | RegisterGeneratedPlugins(registry: flutterViewController) 12 | 13 | super.awakeFromNib() 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /final/android/app/src/debug/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /final/android/app/src/profile/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /final/macos/Runner/MainFlutterWindow.swift: -------------------------------------------------------------------------------- 1 | import Cocoa 2 | import FlutterMacOS 3 | 4 | class MainFlutterWindow: NSWindow { 5 | override func awakeFromNib() { 6 | let flutterViewController = FlutterViewController.init() 7 | let windowFrame = self.frame 8 | self.contentViewController = flutterViewController 9 | self.setFrame(windowFrame, display: true) 10 | 11 | RegisterGeneratedPlugins(registry: flutterViewController) 12 | 13 | super.awakeFromNib() 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /final/macos/Runner/DebugProfile.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.app-sandbox 6 | 7 | com.apple.security.cs.allow-jit 8 | 9 | com.apple.security.network.server 10 | 11 | com.apple.security.network.client 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /final/lib/notifiers/repeat_button_notifier.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/foundation.dart'; 2 | 3 | class RepeatButtonNotifier extends ValueNotifier { 4 | RepeatButtonNotifier() : super(_initialValue); 5 | static const _initialValue = RepeatState.off; 6 | 7 | void nextState() { 8 | final next = (value.index + 1) % RepeatState.values.length; 9 | value = RepeatState.values[next]; 10 | } 11 | } 12 | 13 | enum RepeatState { 14 | off, 15 | repeatSong, 16 | repeatPlaylist, 17 | } 18 | -------------------------------------------------------------------------------- /final/android/settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | 3 | def localPropertiesFile = new File(rootProject.projectDir, "local.properties") 4 | def properties = new Properties() 5 | 6 | assert localPropertiesFile.exists() 7 | localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) } 8 | 9 | def flutterSdkPath = properties.getProperty("flutter.sdk") 10 | assert flutterSdkPath != null, "flutter.sdk not set in local.properties" 11 | apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle" 12 | -------------------------------------------------------------------------------- /final/android/app/src/main/res/drawable/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /starter/android/app/src/main/res/drawable/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /final/android/app/src/main/res/drawable-v21/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /final/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: flutter_audio_service_demo 2 | description: Companion project for tutorial on audio_service plugin. 3 | publish_to: 'none' 4 | 5 | version: 1.0.0+1 6 | 7 | environment: 8 | sdk: ">=2.19.0 <3.0.0" 9 | 10 | dependencies: 11 | flutter: 12 | sdk: flutter 13 | audio_video_progress_bar: ^1.0.0 14 | get_it: ^7.2.0 15 | just_audio: ^0.9.31 16 | audio_service: ^0.18.9 17 | 18 | dev_dependencies: 19 | flutter_lints: any 20 | flutter_test: 21 | sdk: flutter 22 | 23 | flutter: 24 | uses-material-design: true -------------------------------------------------------------------------------- /starter/android/app/src/main/res/drawable-v21/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /final/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "LaunchImage.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "LaunchImage@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "LaunchImage@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /starter/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "LaunchImage.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "LaunchImage@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "LaunchImage@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /final/lib/services/service_locator.dart: -------------------------------------------------------------------------------- 1 | import 'package:audio_service/audio_service.dart'; 2 | 3 | import '../page_manager.dart'; 4 | import 'audio_handler.dart'; 5 | import 'playlist_repository.dart'; 6 | import 'package:get_it/get_it.dart'; 7 | 8 | GetIt getIt = GetIt.instance; 9 | 10 | Future setupServiceLocator() async { 11 | // services 12 | getIt.registerSingleton(await initAudioService()); 13 | getIt.registerLazySingleton(() => DemoPlaylist()); 14 | 15 | // page state 16 | getIt.registerLazySingleton(() => PageManager()); 17 | } 18 | -------------------------------------------------------------------------------- /starter/android/build.gradle.kts: -------------------------------------------------------------------------------- 1 | allprojects { 2 | repositories { 3 | google() 4 | mavenCentral() 5 | } 6 | } 7 | 8 | val newBuildDir: Directory = rootProject.layout.buildDirectory.dir("../../build").get() 9 | rootProject.layout.buildDirectory.value(newBuildDir) 10 | 11 | subprojects { 12 | val newSubprojectBuildDir: Directory = newBuildDir.dir(project.name) 13 | project.layout.buildDirectory.value(newSubprojectBuildDir) 14 | } 15 | subprojects { 16 | project.evaluationDependsOn(":app") 17 | } 18 | 19 | tasks.register("clean") { 20 | delete(rootProject.layout.buildDirectory) 21 | } 22 | -------------------------------------------------------------------------------- /final/lib/notifiers/progress_notifier.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/foundation.dart'; 2 | 3 | class ProgressNotifier extends ValueNotifier { 4 | ProgressNotifier() : super(_initialValue); 5 | static const _initialValue = ProgressBarState( 6 | current: Duration.zero, 7 | buffered: Duration.zero, 8 | total: Duration.zero, 9 | ); 10 | } 11 | 12 | class ProgressBarState { 13 | const ProgressBarState({ 14 | required this.current, 15 | required this.buffered, 16 | required this.total, 17 | }); 18 | final Duration current; 19 | final Duration buffered; 20 | final Duration total; 21 | } 22 | -------------------------------------------------------------------------------- /starter/lib/notifiers/progress_notifier.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/foundation.dart'; 2 | 3 | class ProgressNotifier extends ValueNotifier { 4 | ProgressNotifier() : super(_initialValue); 5 | static const _initialValue = ProgressBarState( 6 | current: Duration.zero, 7 | buffered: Duration.zero, 8 | total: Duration.zero, 9 | ); 10 | } 11 | 12 | class ProgressBarState { 13 | const ProgressBarState({ 14 | required this.current, 15 | required this.buffered, 16 | required this.total, 17 | }); 18 | final Duration current; 19 | final Duration buffered; 20 | final Duration total; 21 | } 22 | -------------------------------------------------------------------------------- /final/README.md: -------------------------------------------------------------------------------- 1 | # flutter_audio_service_demo 2 | 3 | A new Flutter project. 4 | 5 | ## Getting Started 6 | 7 | This project is a starting point for a Flutter application. 8 | 9 | A few resources to get you started if this is your first Flutter project: 10 | 11 | - [Lab: Write your first Flutter app](https://docs.flutter.dev/get-started/codelab) 12 | - [Cookbook: Useful Flutter samples](https://docs.flutter.dev/cookbook) 13 | 14 | For help getting started with Flutter development, view the 15 | [online documentation](https://docs.flutter.dev/), which offers tutorials, 16 | samples, guidance on mobile development, and a full API reference. 17 | -------------------------------------------------------------------------------- /starter/README.md: -------------------------------------------------------------------------------- 1 | # flutter_audio_service_demo 2 | 3 | A new Flutter project. 4 | 5 | ## Getting Started 6 | 7 | This project is a starting point for a Flutter application. 8 | 9 | A few resources to get you started if this is your first Flutter project: 10 | 11 | - [Lab: Write your first Flutter app](https://docs.flutter.dev/get-started/codelab) 12 | - [Cookbook: Useful Flutter samples](https://docs.flutter.dev/cookbook) 13 | 14 | For help getting started with Flutter development, view the 15 | [online documentation](https://docs.flutter.dev/), which offers tutorials, 16 | samples, guidance on mobile development, and a full API reference. 17 | -------------------------------------------------------------------------------- /final/macos/Runner/Configs/Warnings.xcconfig: -------------------------------------------------------------------------------- 1 | WARNING_CFLAGS = -Wall -Wconditional-uninitialized -Wnullable-to-nonnull-conversion -Wmissing-method-return-type -Woverlength-strings 2 | GCC_WARN_UNDECLARED_SELECTOR = YES 3 | CLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY = YES 4 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE 5 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES 6 | CLANG_WARN_PRAGMA_PACK = YES 7 | CLANG_WARN_STRICT_PROTOTYPES = YES 8 | CLANG_WARN_COMMA = YES 9 | GCC_WARN_STRICT_SELECTOR_MATCH = YES 10 | CLANG_WARN_OBJC_REPEATED_USE_OF_WEAK = YES 11 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES 12 | GCC_WARN_SHADOW = YES 13 | CLANG_WARN_UNREACHABLE_CODE = YES 14 | -------------------------------------------------------------------------------- /starter/macos/Runner/Configs/Warnings.xcconfig: -------------------------------------------------------------------------------- 1 | WARNING_CFLAGS = -Wall -Wconditional-uninitialized -Wnullable-to-nonnull-conversion -Wmissing-method-return-type -Woverlength-strings 2 | GCC_WARN_UNDECLARED_SELECTOR = YES 3 | CLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY = YES 4 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE 5 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES 6 | CLANG_WARN_PRAGMA_PACK = YES 7 | CLANG_WARN_STRICT_PROTOTYPES = YES 8 | CLANG_WARN_COMMA = YES 9 | GCC_WARN_STRICT_SELECTOR_MATCH = YES 10 | CLANG_WARN_OBJC_REPEATED_USE_OF_WEAK = YES 11 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES 12 | GCC_WARN_SHADOW = YES 13 | CLANG_WARN_UNREACHABLE_CODE = YES 14 | -------------------------------------------------------------------------------- /final/macos/Runner/Configs/AppInfo.xcconfig: -------------------------------------------------------------------------------- 1 | // Application-level settings for the Runner target. 2 | // 3 | // This may be replaced with something auto-generated from metadata (e.g., pubspec.yaml) in the 4 | // future. If not, the values below would default to using the project name when this becomes a 5 | // 'flutter create' template. 6 | 7 | // The application's name. By default this is also the title of the Flutter window. 8 | PRODUCT_NAME = flutter_audio_service_demo 9 | 10 | // The application's bundle identifier 11 | PRODUCT_BUNDLE_IDENTIFIER = dev.suragch.flutterAudioServiceDemo 12 | 13 | // The copyright displayed in application information 14 | PRODUCT_COPYRIGHT = Copyright © 2023 dev.suragch. All rights reserved. 15 | -------------------------------------------------------------------------------- /starter/macos/Runner/Configs/AppInfo.xcconfig: -------------------------------------------------------------------------------- 1 | // Application-level settings for the Runner target. 2 | // 3 | // This may be replaced with something auto-generated from metadata (e.g., pubspec.yaml) in the 4 | // future. If not, the values below would default to using the project name when this becomes a 5 | // 'flutter create' template. 6 | 7 | // The application's name. By default this is also the title of the Flutter window. 8 | PRODUCT_NAME = flutter_audio_service_demo 9 | 10 | // The application's bundle identifier 11 | PRODUCT_BUNDLE_IDENTIFIER = com.example.flutterAudioServiceDemo 12 | 13 | // The copyright displayed in application information 14 | PRODUCT_COPYRIGHT = Copyright © 2025 com.example. All rights reserved. 15 | -------------------------------------------------------------------------------- /final/ios/.gitignore: -------------------------------------------------------------------------------- 1 | **/dgph 2 | *.mode1v3 3 | *.mode2v3 4 | *.moved-aside 5 | *.pbxuser 6 | *.perspectivev3 7 | **/*sync/ 8 | .sconsign.dblite 9 | .tags* 10 | **/.vagrant/ 11 | **/DerivedData/ 12 | Icon? 13 | **/Pods/ 14 | **/.symlinks/ 15 | profile 16 | xcuserdata 17 | **/.generated/ 18 | Flutter/App.framework 19 | Flutter/Flutter.framework 20 | Flutter/Flutter.podspec 21 | Flutter/Generated.xcconfig 22 | Flutter/ephemeral/ 23 | Flutter/app.flx 24 | Flutter/app.zip 25 | Flutter/flutter_assets/ 26 | Flutter/flutter_export_environment.sh 27 | ServiceDefinitions.json 28 | Runner/GeneratedPluginRegistrant.* 29 | 30 | # Exceptions to above rules. 31 | !default.mode1v3 32 | !default.mode2v3 33 | !default.pbxuser 34 | !default.perspectivev3 35 | -------------------------------------------------------------------------------- /starter/ios/.gitignore: -------------------------------------------------------------------------------- 1 | **/dgph 2 | *.mode1v3 3 | *.mode2v3 4 | *.moved-aside 5 | *.pbxuser 6 | *.perspectivev3 7 | **/*sync/ 8 | .sconsign.dblite 9 | .tags* 10 | **/.vagrant/ 11 | **/DerivedData/ 12 | Icon? 13 | **/Pods/ 14 | **/.symlinks/ 15 | profile 16 | xcuserdata 17 | **/.generated/ 18 | Flutter/App.framework 19 | Flutter/Flutter.framework 20 | Flutter/Flutter.podspec 21 | Flutter/Generated.xcconfig 22 | Flutter/ephemeral/ 23 | Flutter/app.flx 24 | Flutter/app.zip 25 | Flutter/flutter_assets/ 26 | Flutter/flutter_export_environment.sh 27 | ServiceDefinitions.json 28 | Runner/GeneratedPluginRegistrant.* 29 | 30 | # Exceptions to above rules. 31 | !default.mode1v3 32 | !default.mode2v3 33 | !default.pbxuser 34 | !default.perspectivev3 35 | -------------------------------------------------------------------------------- /final/android/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | ext.kotlin_version = '1.7.10' 3 | repositories { 4 | google() 5 | mavenCentral() 6 | } 7 | 8 | dependencies { 9 | classpath 'com.android.tools.build:gradle:7.2.0' 10 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" 11 | } 12 | } 13 | 14 | allprojects { 15 | repositories { 16 | google() 17 | mavenCentral() 18 | } 19 | } 20 | 21 | rootProject.buildDir = '../build' 22 | subprojects { 23 | project.buildDir = "${rootProject.buildDir}/${project.name}" 24 | } 25 | subprojects { 26 | project.evaluationDependsOn(':app') 27 | } 28 | 29 | task clean(type: Delete) { 30 | delete rootProject.buildDir 31 | } 32 | -------------------------------------------------------------------------------- /final/macos/Flutter/GeneratedPluginRegistrant.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Generated file. Do not edit. 3 | // 4 | 5 | import FlutterMacOS 6 | import Foundation 7 | 8 | import audio_service 9 | import audio_session 10 | import just_audio 11 | import path_provider_foundation 12 | import sqflite 13 | 14 | func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { 15 | AudioServicePlugin.register(with: registry.registrar(forPlugin: "AudioServicePlugin")) 16 | AudioSessionPlugin.register(with: registry.registrar(forPlugin: "AudioSessionPlugin")) 17 | JustAudioPlugin.register(with: registry.registrar(forPlugin: "JustAudioPlugin")) 18 | PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin")) 19 | SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin")) 20 | } 21 | -------------------------------------------------------------------------------- /starter/android/settings.gradle.kts: -------------------------------------------------------------------------------- 1 | pluginManagement { 2 | val flutterSdkPath = run { 3 | val properties = java.util.Properties() 4 | file("local.properties").inputStream().use { properties.load(it) } 5 | val flutterSdkPath = properties.getProperty("flutter.sdk") 6 | require(flutterSdkPath != null) { "flutter.sdk not set in local.properties" } 7 | flutterSdkPath 8 | } 9 | 10 | includeBuild("$flutterSdkPath/packages/flutter_tools/gradle") 11 | 12 | repositories { 13 | google() 14 | mavenCentral() 15 | gradlePluginPortal() 16 | } 17 | } 18 | 19 | plugins { 20 | id("dev.flutter.flutter-plugin-loader") version "1.0.0" 21 | id("com.android.application") version "8.7.3" apply false 22 | id("org.jetbrains.kotlin.android") version "2.1.0" apply false 23 | } 24 | 25 | include(":app") 26 | -------------------------------------------------------------------------------- /final/ios/Flutter/AppFrameworkInfo.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | App 9 | CFBundleIdentifier 10 | io.flutter.flutter.app 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | App 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1.0 23 | MinimumOSVersion 24 | 11.0 25 | 26 | 27 | -------------------------------------------------------------------------------- /starter/ios/Flutter/AppFrameworkInfo.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | App 9 | CFBundleIdentifier 10 | io.flutter.flutter.app 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | App 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1.0 23 | MinimumOSVersion 24 | 12.0 25 | 26 | 27 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Miscellaneous 2 | *.class 3 | *.log 4 | *.pyc 5 | *.swp 6 | .DS_Store 7 | .atom/ 8 | .buildlog/ 9 | .history 10 | .svn/ 11 | 12 | # IntelliJ related 13 | *.iml 14 | *.ipr 15 | *.iws 16 | .idea/ 17 | 18 | # The .vscode folder contains launch configuration and tasks you configure in 19 | # VS Code which you may wish to be included in version control, so this line 20 | # is commented out by default. 21 | #.vscode/ 22 | 23 | # Flutter/Dart/Pub related 24 | **/doc/api/ 25 | **/ios/Flutter/.last_build_id 26 | .dart_tool/ 27 | .flutter-plugins 28 | .flutter-plugins-dependencies 29 | .packages 30 | .pub-cache/ 31 | .pub/ 32 | /build/ 33 | 34 | # Web related 35 | lib/generated_plugin_registrant.dart 36 | 37 | # Symbolication related 38 | app.*.symbols 39 | 40 | # Obfuscation related 41 | app.*.map.json 42 | 43 | # Android Studio will place build artifacts here 44 | /android/app/debug 45 | /android/app/profile 46 | /android/app/release 47 | -------------------------------------------------------------------------------- /final/.gitignore: -------------------------------------------------------------------------------- 1 | # Miscellaneous 2 | *.class 3 | *.log 4 | *.pyc 5 | *.swp 6 | .DS_Store 7 | .atom/ 8 | .buildlog/ 9 | .history 10 | .svn/ 11 | 12 | # IntelliJ related 13 | *.iml 14 | *.ipr 15 | *.iws 16 | .idea/ 17 | 18 | # The .vscode folder contains launch configuration and tasks you configure in 19 | # VS Code which you may wish to be included in version control, so this line 20 | # is commented out by default. 21 | #.vscode/ 22 | 23 | # Flutter/Dart/Pub related 24 | **/doc/api/ 25 | **/ios/Flutter/.last_build_id 26 | .dart_tool/ 27 | .flutter-plugins 28 | .flutter-plugins-dependencies 29 | .packages 30 | .pub-cache/ 31 | .pub/ 32 | /build/ 33 | 34 | # Web related 35 | lib/generated_plugin_registrant.dart 36 | 37 | # Symbolication related 38 | app.*.symbols 39 | 40 | # Obfuscation related 41 | app.*.map.json 42 | 43 | # Android Studio will place build artifacts here 44 | /android/app/debug 45 | /android/app/profile 46 | /android/app/release 47 | -------------------------------------------------------------------------------- /starter/.gitignore: -------------------------------------------------------------------------------- 1 | # Miscellaneous 2 | *.class 3 | *.log 4 | *.pyc 5 | *.swp 6 | .DS_Store 7 | .atom/ 8 | .buildlog/ 9 | .history 10 | .svn/ 11 | 12 | # IntelliJ related 13 | *.iml 14 | *.ipr 15 | *.iws 16 | .idea/ 17 | 18 | # The .vscode folder contains launch configuration and tasks you configure in 19 | # VS Code which you may wish to be included in version control, so this line 20 | # is commented out by default. 21 | #.vscode/ 22 | 23 | # Flutter/Dart/Pub related 24 | **/doc/api/ 25 | **/ios/Flutter/.last_build_id 26 | .dart_tool/ 27 | .flutter-plugins 28 | .flutter-plugins-dependencies 29 | .packages 30 | .pub-cache/ 31 | .pub/ 32 | /build/ 33 | 34 | # Web related 35 | lib/generated_plugin_registrant.dart 36 | 37 | # Symbolication related 38 | app.*.symbols 39 | 40 | # Obfuscation related 41 | app.*.map.json 42 | 43 | # Android Studio will place build artifacts here 44 | /android/app/debug 45 | /android/app/profile 46 | /android/app/release 47 | -------------------------------------------------------------------------------- /final/lib/services/playlist_repository.dart: -------------------------------------------------------------------------------- 1 | abstract class PlaylistRepository { 2 | Future>> fetchInitialPlaylist(); 3 | Future> fetchAnotherSong(); 4 | } 5 | 6 | class DemoPlaylist extends PlaylistRepository { 7 | @override 8 | Future>> fetchInitialPlaylist( 9 | {int length = 3}) async { 10 | return List.generate(length, (index) => _nextSong()); 11 | } 12 | 13 | @override 14 | Future> fetchAnotherSong() async { 15 | return _nextSong(); 16 | } 17 | 18 | var _songIndex = 0; 19 | static const _maxSongNumber = 16; 20 | 21 | Map _nextSong() { 22 | _songIndex = (_songIndex % _maxSongNumber) + 1; 23 | return { 24 | 'id': _songIndex.toString().padLeft(3, '0'), 25 | 'title': 'Song $_songIndex', 26 | 'album': 'SoundHelix', 27 | 'url': 28 | 'https://www.soundhelix.com/examples/mp3/SoundHelix-Song-$_songIndex.mp3', 29 | }; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /starter/lib/services/playlist_repository.dart: -------------------------------------------------------------------------------- 1 | abstract class PlaylistRepository { 2 | Future>> fetchInitialPlaylist(); 3 | Future> fetchAnotherSong(); 4 | } 5 | 6 | class DemoPlaylist extends PlaylistRepository { 7 | @override 8 | Future>> fetchInitialPlaylist({ 9 | int length = 3, 10 | }) async { 11 | return List.generate(length, (index) => _nextSong()); 12 | } 13 | 14 | @override 15 | Future> fetchAnotherSong() async { 16 | return _nextSong(); 17 | } 18 | 19 | var _songIndex = 0; 20 | static const _maxSongNumber = 16; 21 | 22 | Map _nextSong() { 23 | _songIndex = (_songIndex % _maxSongNumber) + 1; 24 | return { 25 | 'id': _songIndex.toString().padLeft(3, '0'), 26 | 'title': 'Song $_songIndex', 27 | 'album': 'SoundHelix', 28 | 'url': 29 | 'https://www.soundhelix.com/examples/mp3/SoundHelix-Song-$_songIndex.mp3', 30 | }; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /final/.metadata: -------------------------------------------------------------------------------- 1 | # This file tracks properties of this Flutter project. 2 | # Used by Flutter tool to assess capabilities and perform upgrades etc. 3 | # 4 | # This file should be version controlled. 5 | 6 | version: 7 | revision: 9944297138845a94256f1cf37beb88ff9a8e811a 8 | channel: stable 9 | 10 | project_type: app 11 | 12 | # Tracks metadata for the flutter migrate command 13 | migration: 14 | platforms: 15 | - platform: root 16 | create_revision: 9944297138845a94256f1cf37beb88ff9a8e811a 17 | base_revision: 9944297138845a94256f1cf37beb88ff9a8e811a 18 | - platform: web 19 | create_revision: 9944297138845a94256f1cf37beb88ff9a8e811a 20 | base_revision: 9944297138845a94256f1cf37beb88ff9a8e811a 21 | 22 | # User provided section 23 | 24 | # List of Local paths (relative to this file) that should be 25 | # ignored by the migrate tool. 26 | # 27 | # Files that are not part of the templates will be ignored by default. 28 | unmanaged_files: 29 | - 'lib/main.dart' 30 | - 'ios/Runner.xcodeproj/project.pbxproj' 31 | -------------------------------------------------------------------------------- /final/android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 15 | 18 | 19 | -------------------------------------------------------------------------------- /starter/android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 15 | 18 | 19 | -------------------------------------------------------------------------------- /final/android/app/src/main/res/values-night/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 15 | 18 | 19 | -------------------------------------------------------------------------------- /starter/android/app/src/main/res/values-night/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 15 | 18 | 19 | -------------------------------------------------------------------------------- /final/web/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "flutter_audio_service_demo", 3 | "short_name": "flutter_audio_service_demo", 4 | "start_url": ".", 5 | "display": "standalone", 6 | "background_color": "#0175C2", 7 | "theme_color": "#0175C2", 8 | "description": "A new Flutter project.", 9 | "orientation": "portrait-primary", 10 | "prefer_related_applications": false, 11 | "icons": [ 12 | { 13 | "src": "icons/Icon-192.png", 14 | "sizes": "192x192", 15 | "type": "image/png" 16 | }, 17 | { 18 | "src": "icons/Icon-512.png", 19 | "sizes": "512x512", 20 | "type": "image/png" 21 | }, 22 | { 23 | "src": "icons/Icon-maskable-192.png", 24 | "sizes": "192x192", 25 | "type": "image/png", 26 | "purpose": "maskable" 27 | }, 28 | { 29 | "src": "icons/Icon-maskable-512.png", 30 | "sizes": "512x512", 31 | "type": "image/png", 32 | "purpose": "maskable" 33 | } 34 | ] 35 | } 36 | -------------------------------------------------------------------------------- /starter/web/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "flutter_audio_service_demo", 3 | "short_name": "flutter_audio_service_demo", 4 | "start_url": ".", 5 | "display": "standalone", 6 | "background_color": "#0175C2", 7 | "theme_color": "#0175C2", 8 | "description": "A new Flutter project.", 9 | "orientation": "portrait-primary", 10 | "prefer_related_applications": false, 11 | "icons": [ 12 | { 13 | "src": "icons/Icon-192.png", 14 | "sizes": "192x192", 15 | "type": "image/png" 16 | }, 17 | { 18 | "src": "icons/Icon-512.png", 19 | "sizes": "512x512", 20 | "type": "image/png" 21 | }, 22 | { 23 | "src": "icons/Icon-maskable-192.png", 24 | "sizes": "192x192", 25 | "type": "image/png", 26 | "purpose": "maskable" 27 | }, 28 | { 29 | "src": "icons/Icon-maskable-512.png", 30 | "sizes": "512x512", 31 | "type": "image/png", 32 | "purpose": "maskable" 33 | } 34 | ] 35 | } 36 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 suragch 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /starter/lib/page_manager.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/foundation.dart'; 2 | import 'notifiers/play_button_notifier.dart'; 3 | import 'notifiers/progress_notifier.dart'; 4 | import 'notifiers/repeat_button_notifier.dart'; 5 | import 'services/playlist_repository.dart'; 6 | 7 | class PageManager { 8 | // Listeners: Updates going to the UI 9 | final currentSongTitleNotifier = ValueNotifier(''); 10 | final playlistNotifier = ValueNotifier>([]); 11 | final progressNotifier = ProgressNotifier(); 12 | final repeatButtonNotifier = RepeatButtonNotifier(); 13 | final isFirstSongNotifier = ValueNotifier(true); 14 | final playButtonNotifier = PlayButtonNotifier(); 15 | final isLastSongNotifier = ValueNotifier(true); 16 | final isShuffleModeEnabledNotifier = ValueNotifier(false); 17 | 18 | // Events: Calls coming from the UI 19 | void init() {} 20 | void play() {} 21 | void pause() {} 22 | void seek(Duration position) {} 23 | void previous() {} 24 | void next() {} 25 | void repeat() {} 26 | void shuffle() {} 27 | void add() {} 28 | void remove() {} 29 | void dispose() {} 30 | } 31 | -------------------------------------------------------------------------------- /final/macos/Runner/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIconFile 10 | 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | $(FLUTTER_BUILD_NAME) 21 | CFBundleVersion 22 | $(FLUTTER_BUILD_NUMBER) 23 | LSMinimumSystemVersion 24 | $(MACOSX_DEPLOYMENT_TARGET) 25 | NSHumanReadableCopyright 26 | $(PRODUCT_COPYRIGHT) 27 | NSMainNibFile 28 | MainMenu 29 | NSPrincipalClass 30 | NSApplication 31 | 32 | 33 | -------------------------------------------------------------------------------- /starter/macos/Runner/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIconFile 10 | 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | $(FLUTTER_BUILD_NAME) 21 | CFBundleVersion 22 | $(FLUTTER_BUILD_NUMBER) 23 | LSMinimumSystemVersion 24 | $(MACOSX_DEPLOYMENT_TARGET) 25 | NSHumanReadableCopyright 26 | $(PRODUCT_COPYRIGHT) 27 | NSMainNibFile 28 | MainMenu 29 | NSPrincipalClass 30 | NSApplication 31 | 32 | 33 | -------------------------------------------------------------------------------- /starter/web/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | flutter_audio_service_demo 33 | 34 | 35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /final/macos/Podfile: -------------------------------------------------------------------------------- 1 | platform :osx, '10.14' 2 | 3 | # CocoaPods analytics sends network stats synchronously affecting flutter build latency. 4 | ENV['COCOAPODS_DISABLE_STATS'] = 'true' 5 | 6 | project 'Runner', { 7 | 'Debug' => :debug, 8 | 'Profile' => :release, 9 | 'Release' => :release, 10 | } 11 | 12 | def flutter_root 13 | generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'ephemeral', 'Flutter-Generated.xcconfig'), __FILE__) 14 | unless File.exist?(generated_xcode_build_settings_path) 15 | raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure \"flutter pub get\" is executed first" 16 | end 17 | 18 | File.foreach(generated_xcode_build_settings_path) do |line| 19 | matches = line.match(/FLUTTER_ROOT\=(.*)/) 20 | return matches[1].strip if matches 21 | end 22 | raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Flutter-Generated.xcconfig, then run \"flutter pub get\"" 23 | end 24 | 25 | require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) 26 | 27 | flutter_macos_podfile_setup 28 | 29 | target 'Runner' do 30 | use_frameworks! 31 | use_modular_headers! 32 | 33 | flutter_install_all_macos_pods File.dirname(File.realpath(__FILE__)) 34 | end 35 | 36 | post_install do |installer| 37 | installer.pods_project.targets.each do |target| 38 | flutter_additional_macos_build_settings(target) 39 | end 40 | end 41 | -------------------------------------------------------------------------------- /starter/android/app/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("com.android.application") 3 | id("kotlin-android") 4 | // The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins. 5 | id("dev.flutter.flutter-gradle-plugin") 6 | } 7 | 8 | android { 9 | namespace = "com.example.flutter_audio_service_demo" 10 | compileSdk = flutter.compileSdkVersion 11 | ndkVersion = flutter.ndkVersion 12 | 13 | compileOptions { 14 | sourceCompatibility = JavaVersion.VERSION_11 15 | targetCompatibility = JavaVersion.VERSION_11 16 | } 17 | 18 | kotlinOptions { 19 | jvmTarget = JavaVersion.VERSION_11.toString() 20 | } 21 | 22 | defaultConfig { 23 | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). 24 | applicationId = "com.example.flutter_audio_service_demo" 25 | // You can update the following values to match your application needs. 26 | // For more information, see: https://flutter.dev/to/review-gradle-config. 27 | minSdk = flutter.minSdkVersion 28 | targetSdk = flutter.targetSdkVersion 29 | versionCode = flutter.versionCode 30 | versionName = flutter.versionName 31 | } 32 | 33 | buildTypes { 34 | release { 35 | // TODO: Add your own signing config for the release build. 36 | // Signing with the debug keys for now, so `flutter run --release` works. 37 | signingConfig = signingConfigs.getByName("debug") 38 | } 39 | } 40 | } 41 | 42 | flutter { 43 | source = "../.." 44 | } 45 | -------------------------------------------------------------------------------- /final/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "16x16", 5 | "idiom" : "mac", 6 | "filename" : "app_icon_16.png", 7 | "scale" : "1x" 8 | }, 9 | { 10 | "size" : "16x16", 11 | "idiom" : "mac", 12 | "filename" : "app_icon_32.png", 13 | "scale" : "2x" 14 | }, 15 | { 16 | "size" : "32x32", 17 | "idiom" : "mac", 18 | "filename" : "app_icon_32.png", 19 | "scale" : "1x" 20 | }, 21 | { 22 | "size" : "32x32", 23 | "idiom" : "mac", 24 | "filename" : "app_icon_64.png", 25 | "scale" : "2x" 26 | }, 27 | { 28 | "size" : "128x128", 29 | "idiom" : "mac", 30 | "filename" : "app_icon_128.png", 31 | "scale" : "1x" 32 | }, 33 | { 34 | "size" : "128x128", 35 | "idiom" : "mac", 36 | "filename" : "app_icon_256.png", 37 | "scale" : "2x" 38 | }, 39 | { 40 | "size" : "256x256", 41 | "idiom" : "mac", 42 | "filename" : "app_icon_256.png", 43 | "scale" : "1x" 44 | }, 45 | { 46 | "size" : "256x256", 47 | "idiom" : "mac", 48 | "filename" : "app_icon_512.png", 49 | "scale" : "2x" 50 | }, 51 | { 52 | "size" : "512x512", 53 | "idiom" : "mac", 54 | "filename" : "app_icon_512.png", 55 | "scale" : "1x" 56 | }, 57 | { 58 | "size" : "512x512", 59 | "idiom" : "mac", 60 | "filename" : "app_icon_1024.png", 61 | "scale" : "2x" 62 | } 63 | ], 64 | "info" : { 65 | "version" : 1, 66 | "author" : "xcode" 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /starter/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "16x16", 5 | "idiom" : "mac", 6 | "filename" : "app_icon_16.png", 7 | "scale" : "1x" 8 | }, 9 | { 10 | "size" : "16x16", 11 | "idiom" : "mac", 12 | "filename" : "app_icon_32.png", 13 | "scale" : "2x" 14 | }, 15 | { 16 | "size" : "32x32", 17 | "idiom" : "mac", 18 | "filename" : "app_icon_32.png", 19 | "scale" : "1x" 20 | }, 21 | { 22 | "size" : "32x32", 23 | "idiom" : "mac", 24 | "filename" : "app_icon_64.png", 25 | "scale" : "2x" 26 | }, 27 | { 28 | "size" : "128x128", 29 | "idiom" : "mac", 30 | "filename" : "app_icon_128.png", 31 | "scale" : "1x" 32 | }, 33 | { 34 | "size" : "128x128", 35 | "idiom" : "mac", 36 | "filename" : "app_icon_256.png", 37 | "scale" : "2x" 38 | }, 39 | { 40 | "size" : "256x256", 41 | "idiom" : "mac", 42 | "filename" : "app_icon_256.png", 43 | "scale" : "1x" 44 | }, 45 | { 46 | "size" : "256x256", 47 | "idiom" : "mac", 48 | "filename" : "app_icon_512.png", 49 | "scale" : "2x" 50 | }, 51 | { 52 | "size" : "512x512", 53 | "idiom" : "mac", 54 | "filename" : "app_icon_512.png", 55 | "scale" : "1x" 56 | }, 57 | { 58 | "size" : "512x512", 59 | "idiom" : "mac", 60 | "filename" : "app_icon_1024.png", 61 | "scale" : "2x" 62 | } 63 | ], 64 | "info" : { 65 | "version" : 1, 66 | "author" : "xcode" 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /final/ios/Runner/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /starter/ios/Runner/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /final/ios/Podfile: -------------------------------------------------------------------------------- 1 | # Uncomment this line to define a global platform for your project 2 | # platform :ios, '11.0' 3 | 4 | # CocoaPods analytics sends network stats synchronously affecting flutter build latency. 5 | ENV['COCOAPODS_DISABLE_STATS'] = 'true' 6 | 7 | project 'Runner', { 8 | 'Debug' => :debug, 9 | 'Profile' => :release, 10 | 'Release' => :release, 11 | } 12 | 13 | def flutter_root 14 | generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__) 15 | unless File.exist?(generated_xcode_build_settings_path) 16 | raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first" 17 | end 18 | 19 | File.foreach(generated_xcode_build_settings_path) do |line| 20 | matches = line.match(/FLUTTER_ROOT\=(.*)/) 21 | return matches[1].strip if matches 22 | end 23 | raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get" 24 | end 25 | 26 | require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) 27 | 28 | flutter_ios_podfile_setup 29 | 30 | target 'Runner' do 31 | use_frameworks! 32 | use_modular_headers! 33 | 34 | flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__)) 35 | end 36 | 37 | post_install do |installer| 38 | installer.pods_project.targets.each do |target| 39 | flutter_additional_ios_build_settings(target) 40 | # Remove microphone APIs 41 | target.build_configurations.each do |config| 42 | config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] ||= [ 43 | '$(inherited)', 44 | 'AUDIO_SESSION_MICROPHONE=0' 45 | ] 46 | end 47 | end 48 | end 49 | -------------------------------------------------------------------------------- /final/ios/Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - audio_service (0.0.1): 3 | - Flutter 4 | - audio_session (0.0.1): 5 | - Flutter 6 | - Flutter (1.0.0) 7 | - FMDB (2.7.5): 8 | - FMDB/standard (= 2.7.5) 9 | - FMDB/standard (2.7.5) 10 | - just_audio (0.0.1): 11 | - Flutter 12 | - path_provider_foundation (0.0.1): 13 | - Flutter 14 | - FlutterMacOS 15 | - sqflite (0.0.2): 16 | - Flutter 17 | - FMDB (>= 2.7.5) 18 | 19 | DEPENDENCIES: 20 | - audio_service (from `.symlinks/plugins/audio_service/ios`) 21 | - audio_session (from `.symlinks/plugins/audio_session/ios`) 22 | - Flutter (from `Flutter`) 23 | - just_audio (from `.symlinks/plugins/just_audio/ios`) 24 | - path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/ios`) 25 | - sqflite (from `.symlinks/plugins/sqflite/ios`) 26 | 27 | SPEC REPOS: 28 | trunk: 29 | - FMDB 30 | 31 | EXTERNAL SOURCES: 32 | audio_service: 33 | :path: ".symlinks/plugins/audio_service/ios" 34 | audio_session: 35 | :path: ".symlinks/plugins/audio_session/ios" 36 | Flutter: 37 | :path: Flutter 38 | just_audio: 39 | :path: ".symlinks/plugins/just_audio/ios" 40 | path_provider_foundation: 41 | :path: ".symlinks/plugins/path_provider_foundation/ios" 42 | sqflite: 43 | :path: ".symlinks/plugins/sqflite/ios" 44 | 45 | SPEC CHECKSUMS: 46 | audio_service: f509d65da41b9521a61f1c404dd58651f265a567 47 | audio_session: 4f3e461722055d21515cf3261b64c973c062f345 48 | Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854 49 | FMDB: 2ce00b547f966261cd18927a3ddb07cb6f3db82a 50 | just_audio: baa7252489dbcf47a4c7cc9ca663e9661c99aafa 51 | path_provider_foundation: 37748e03f12783f9de2cb2c4eadfaa25fe6d4852 52 | sqflite: 6d358c025f5b867b29ed92fc697fd34924e11904 53 | 54 | PODFILE CHECKSUM: efc9dbfbbd11e0626b0c981585dd40d203718727 55 | 56 | COCOAPODS: 1.11.3 57 | -------------------------------------------------------------------------------- /starter/.metadata: -------------------------------------------------------------------------------- 1 | # This file tracks properties of this Flutter project. 2 | # Used by Flutter tool to assess capabilities and perform upgrades etc. 3 | # 4 | # This file should be version controlled and should not be manually edited. 5 | 6 | version: 7 | revision: "fcf2c11572af6f390246c056bc905eca609533a0" 8 | channel: "stable" 9 | 10 | project_type: app 11 | 12 | # Tracks metadata for the flutter migrate command 13 | migration: 14 | platforms: 15 | - platform: root 16 | create_revision: fcf2c11572af6f390246c056bc905eca609533a0 17 | base_revision: fcf2c11572af6f390246c056bc905eca609533a0 18 | - platform: android 19 | create_revision: fcf2c11572af6f390246c056bc905eca609533a0 20 | base_revision: fcf2c11572af6f390246c056bc905eca609533a0 21 | - platform: ios 22 | create_revision: fcf2c11572af6f390246c056bc905eca609533a0 23 | base_revision: fcf2c11572af6f390246c056bc905eca609533a0 24 | - platform: linux 25 | create_revision: fcf2c11572af6f390246c056bc905eca609533a0 26 | base_revision: fcf2c11572af6f390246c056bc905eca609533a0 27 | - platform: macos 28 | create_revision: fcf2c11572af6f390246c056bc905eca609533a0 29 | base_revision: fcf2c11572af6f390246c056bc905eca609533a0 30 | - platform: web 31 | create_revision: fcf2c11572af6f390246c056bc905eca609533a0 32 | base_revision: fcf2c11572af6f390246c056bc905eca609533a0 33 | - platform: windows 34 | create_revision: fcf2c11572af6f390246c056bc905eca609533a0 35 | base_revision: fcf2c11572af6f390246c056bc905eca609533a0 36 | 37 | # User provided section 38 | 39 | # List of Local paths (relative to this file) that should be 40 | # ignored by the migrate tool. 41 | # 42 | # Files that are not part of the templates will be ignored by default. 43 | unmanaged_files: 44 | - 'lib/main.dart' 45 | - 'ios/Runner.xcodeproj/project.pbxproj' 46 | -------------------------------------------------------------------------------- /starter/ios/Runner/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleDisplayName 8 | Flutter Audio Service Demo 9 | CFBundleExecutable 10 | $(EXECUTABLE_NAME) 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | flutter_audio_service_demo 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | $(FLUTTER_BUILD_NAME) 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | $(FLUTTER_BUILD_NUMBER) 25 | LSRequiresIPhoneOS 26 | 27 | UILaunchStoryboardName 28 | LaunchScreen 29 | UIMainStoryboardFile 30 | Main 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | UISupportedInterfaceOrientations~ipad 38 | 39 | UIInterfaceOrientationPortrait 40 | UIInterfaceOrientationPortraitUpsideDown 41 | UIInterfaceOrientationLandscapeLeft 42 | UIInterfaceOrientationLandscapeRight 43 | 44 | CADisableMinimumFrameDurationOnPhone 45 | 46 | UIApplicationSupportsIndirectInputEvents 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /final/ios/Runner/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleDisplayName 8 | Flutter Audio Service Demo 9 | CFBundleExecutable 10 | $(EXECUTABLE_NAME) 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | flutter_audio_service_demo 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | $(FLUTTER_BUILD_NAME) 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | $(FLUTTER_BUILD_NUMBER) 25 | LSRequiresIPhoneOS 26 | 27 | UILaunchStoryboardName 28 | LaunchScreen 29 | UIMainStoryboardFile 30 | Main 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | UISupportedInterfaceOrientations~ipad 38 | 39 | UIInterfaceOrientationPortrait 40 | UIInterfaceOrientationPortraitUpsideDown 41 | UIInterfaceOrientationLandscapeLeft 42 | UIInterfaceOrientationLandscapeRight 43 | 44 | UIViewControllerBasedStatusBarAppearance 45 | 46 | CADisableMinimumFrameDurationOnPhone 47 | 48 | UIApplicationSupportsIndirectInputEvents 49 | 50 | UIBackgroundModes 51 | 52 | audio 53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /final/macos/Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - audio_service (0.14.1): 3 | - FlutterMacOS 4 | - audio_session (0.0.1): 5 | - FlutterMacOS 6 | - FlutterMacOS (1.0.0) 7 | - FMDB (2.7.5): 8 | - FMDB/standard (= 2.7.5) 9 | - FMDB/standard (2.7.5) 10 | - just_audio (0.0.1): 11 | - FlutterMacOS 12 | - path_provider_foundation (0.0.1): 13 | - Flutter 14 | - FlutterMacOS 15 | - sqflite (0.0.2): 16 | - FlutterMacOS 17 | - FMDB (>= 2.7.5) 18 | 19 | DEPENDENCIES: 20 | - audio_service (from `Flutter/ephemeral/.symlinks/plugins/audio_service/macos`) 21 | - audio_session (from `Flutter/ephemeral/.symlinks/plugins/audio_session/macos`) 22 | - FlutterMacOS (from `Flutter/ephemeral`) 23 | - just_audio (from `Flutter/ephemeral/.symlinks/plugins/just_audio/macos`) 24 | - path_provider_foundation (from `Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/macos`) 25 | - sqflite (from `Flutter/ephemeral/.symlinks/plugins/sqflite/macos`) 26 | 27 | SPEC REPOS: 28 | trunk: 29 | - FMDB 30 | 31 | EXTERNAL SOURCES: 32 | audio_service: 33 | :path: Flutter/ephemeral/.symlinks/plugins/audio_service/macos 34 | audio_session: 35 | :path: Flutter/ephemeral/.symlinks/plugins/audio_session/macos 36 | FlutterMacOS: 37 | :path: Flutter/ephemeral 38 | just_audio: 39 | :path: Flutter/ephemeral/.symlinks/plugins/just_audio/macos 40 | path_provider_foundation: 41 | :path: Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/macos 42 | sqflite: 43 | :path: Flutter/ephemeral/.symlinks/plugins/sqflite/macos 44 | 45 | SPEC CHECKSUMS: 46 | audio_service: b88ff778e0e3915efd4cd1a5ad6f0beef0c950a9 47 | audio_session: dea1f41890dbf1718f04a56f1d6150fd50039b72 48 | FlutterMacOS: 8f6f14fa908a6fb3fba0cd85dbd81ec4b251fb24 49 | FMDB: 2ce00b547f966261cd18927a3ddb07cb6f3db82a 50 | just_audio: 9b67ca7b97c61cfc9784ea23cd8cc55eb226d489 51 | path_provider_foundation: 37748e03f12783f9de2cb2c4eadfaa25fe6d4852 52 | sqflite: a5789cceda41d54d23f31d6de539d65bb14100ea 53 | 54 | PODFILE CHECKSUM: 353c8bcc5d5b0994e508d035b5431cfe18c1dea7 55 | 56 | COCOAPODS: 1.11.3 57 | -------------------------------------------------------------------------------- /final/web/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | flutter_audio_service_demo 33 | 34 | 35 | 39 | 40 | 41 | 42 | 43 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /starter/android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 15 | 19 | 23 | 24 | 25 | 26 | 27 | 28 | 30 | 33 | 34 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /final/ios/Runner/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /starter/ios/Runner/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /final/android/app/build.gradle: -------------------------------------------------------------------------------- 1 | def localProperties = new Properties() 2 | def localPropertiesFile = rootProject.file('local.properties') 3 | if (localPropertiesFile.exists()) { 4 | localPropertiesFile.withReader('UTF-8') { reader -> 5 | localProperties.load(reader) 6 | } 7 | } 8 | 9 | def flutterRoot = localProperties.getProperty('flutter.sdk') 10 | if (flutterRoot == null) { 11 | throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") 12 | } 13 | 14 | def flutterVersionCode = localProperties.getProperty('flutter.versionCode') 15 | if (flutterVersionCode == null) { 16 | flutterVersionCode = '1' 17 | } 18 | 19 | def flutterVersionName = localProperties.getProperty('flutter.versionName') 20 | if (flutterVersionName == null) { 21 | flutterVersionName = '1.0' 22 | } 23 | 24 | apply plugin: 'com.android.application' 25 | apply plugin: 'kotlin-android' 26 | apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" 27 | 28 | android { 29 | compileSdkVersion 31 30 | ndkVersion flutter.ndkVersion 31 | 32 | compileOptions { 33 | sourceCompatibility JavaVersion.VERSION_1_8 34 | targetCompatibility JavaVersion.VERSION_1_8 35 | } 36 | 37 | kotlinOptions { 38 | jvmTarget = '1.8' 39 | } 40 | 41 | sourceSets { 42 | main.java.srcDirs += 'src/main/kotlin' 43 | } 44 | 45 | defaultConfig { 46 | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). 47 | applicationId "dev.suragch.flutter_audio_service_demo" 48 | // You can update the following values to match your application needs. 49 | // For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration. 50 | minSdkVersion flutter.minSdkVersion 51 | targetSdkVersion flutter.targetSdkVersion 52 | versionCode flutterVersionCode.toInteger() 53 | versionName flutterVersionName 54 | multiDexEnabled true 55 | } 56 | 57 | buildTypes { 58 | release { 59 | // TODO: Add your own signing config for the release build. 60 | // Signing with the debug keys for now, so `flutter run --release` works. 61 | signingConfig signingConfigs.debug 62 | } 63 | } 64 | } 65 | 66 | flutter { 67 | source '../..' 68 | } 69 | 70 | dependencies { 71 | implementation "androidx.multidex:multidex:2.0.1" 72 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" 73 | } 74 | -------------------------------------------------------------------------------- /final/android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 7 | 8 | 9 | 13 | 21 | 25 | 29 | 30 | 31 | 32 | 33 | 34 | 36 | 39 | 40 | 45 | 46 | 47 | 48 | 49 | 50 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /final/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "20x20", 5 | "idiom" : "iphone", 6 | "filename" : "Icon-App-20x20@2x.png", 7 | "scale" : "2x" 8 | }, 9 | { 10 | "size" : "20x20", 11 | "idiom" : "iphone", 12 | "filename" : "Icon-App-20x20@3x.png", 13 | "scale" : "3x" 14 | }, 15 | { 16 | "size" : "29x29", 17 | "idiom" : "iphone", 18 | "filename" : "Icon-App-29x29@1x.png", 19 | "scale" : "1x" 20 | }, 21 | { 22 | "size" : "29x29", 23 | "idiom" : "iphone", 24 | "filename" : "Icon-App-29x29@2x.png", 25 | "scale" : "2x" 26 | }, 27 | { 28 | "size" : "29x29", 29 | "idiom" : "iphone", 30 | "filename" : "Icon-App-29x29@3x.png", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "size" : "40x40", 35 | "idiom" : "iphone", 36 | "filename" : "Icon-App-40x40@2x.png", 37 | "scale" : "2x" 38 | }, 39 | { 40 | "size" : "40x40", 41 | "idiom" : "iphone", 42 | "filename" : "Icon-App-40x40@3x.png", 43 | "scale" : "3x" 44 | }, 45 | { 46 | "size" : "60x60", 47 | "idiom" : "iphone", 48 | "filename" : "Icon-App-60x60@2x.png", 49 | "scale" : "2x" 50 | }, 51 | { 52 | "size" : "60x60", 53 | "idiom" : "iphone", 54 | "filename" : "Icon-App-60x60@3x.png", 55 | "scale" : "3x" 56 | }, 57 | { 58 | "size" : "20x20", 59 | "idiom" : "ipad", 60 | "filename" : "Icon-App-20x20@1x.png", 61 | "scale" : "1x" 62 | }, 63 | { 64 | "size" : "20x20", 65 | "idiom" : "ipad", 66 | "filename" : "Icon-App-20x20@2x.png", 67 | "scale" : "2x" 68 | }, 69 | { 70 | "size" : "29x29", 71 | "idiom" : "ipad", 72 | "filename" : "Icon-App-29x29@1x.png", 73 | "scale" : "1x" 74 | }, 75 | { 76 | "size" : "29x29", 77 | "idiom" : "ipad", 78 | "filename" : "Icon-App-29x29@2x.png", 79 | "scale" : "2x" 80 | }, 81 | { 82 | "size" : "40x40", 83 | "idiom" : "ipad", 84 | "filename" : "Icon-App-40x40@1x.png", 85 | "scale" : "1x" 86 | }, 87 | { 88 | "size" : "40x40", 89 | "idiom" : "ipad", 90 | "filename" : "Icon-App-40x40@2x.png", 91 | "scale" : "2x" 92 | }, 93 | { 94 | "size" : "76x76", 95 | "idiom" : "ipad", 96 | "filename" : "Icon-App-76x76@1x.png", 97 | "scale" : "1x" 98 | }, 99 | { 100 | "size" : "76x76", 101 | "idiom" : "ipad", 102 | "filename" : "Icon-App-76x76@2x.png", 103 | "scale" : "2x" 104 | }, 105 | { 106 | "size" : "83.5x83.5", 107 | "idiom" : "ipad", 108 | "filename" : "Icon-App-83.5x83.5@2x.png", 109 | "scale" : "2x" 110 | }, 111 | { 112 | "size" : "1024x1024", 113 | "idiom" : "ios-marketing", 114 | "filename" : "Icon-App-1024x1024@1x.png", 115 | "scale" : "1x" 116 | } 117 | ], 118 | "info" : { 119 | "version" : 1, 120 | "author" : "xcode" 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /starter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "20x20", 5 | "idiom" : "iphone", 6 | "filename" : "Icon-App-20x20@2x.png", 7 | "scale" : "2x" 8 | }, 9 | { 10 | "size" : "20x20", 11 | "idiom" : "iphone", 12 | "filename" : "Icon-App-20x20@3x.png", 13 | "scale" : "3x" 14 | }, 15 | { 16 | "size" : "29x29", 17 | "idiom" : "iphone", 18 | "filename" : "Icon-App-29x29@1x.png", 19 | "scale" : "1x" 20 | }, 21 | { 22 | "size" : "29x29", 23 | "idiom" : "iphone", 24 | "filename" : "Icon-App-29x29@2x.png", 25 | "scale" : "2x" 26 | }, 27 | { 28 | "size" : "29x29", 29 | "idiom" : "iphone", 30 | "filename" : "Icon-App-29x29@3x.png", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "size" : "40x40", 35 | "idiom" : "iphone", 36 | "filename" : "Icon-App-40x40@2x.png", 37 | "scale" : "2x" 38 | }, 39 | { 40 | "size" : "40x40", 41 | "idiom" : "iphone", 42 | "filename" : "Icon-App-40x40@3x.png", 43 | "scale" : "3x" 44 | }, 45 | { 46 | "size" : "60x60", 47 | "idiom" : "iphone", 48 | "filename" : "Icon-App-60x60@2x.png", 49 | "scale" : "2x" 50 | }, 51 | { 52 | "size" : "60x60", 53 | "idiom" : "iphone", 54 | "filename" : "Icon-App-60x60@3x.png", 55 | "scale" : "3x" 56 | }, 57 | { 58 | "size" : "20x20", 59 | "idiom" : "ipad", 60 | "filename" : "Icon-App-20x20@1x.png", 61 | "scale" : "1x" 62 | }, 63 | { 64 | "size" : "20x20", 65 | "idiom" : "ipad", 66 | "filename" : "Icon-App-20x20@2x.png", 67 | "scale" : "2x" 68 | }, 69 | { 70 | "size" : "29x29", 71 | "idiom" : "ipad", 72 | "filename" : "Icon-App-29x29@1x.png", 73 | "scale" : "1x" 74 | }, 75 | { 76 | "size" : "29x29", 77 | "idiom" : "ipad", 78 | "filename" : "Icon-App-29x29@2x.png", 79 | "scale" : "2x" 80 | }, 81 | { 82 | "size" : "40x40", 83 | "idiom" : "ipad", 84 | "filename" : "Icon-App-40x40@1x.png", 85 | "scale" : "1x" 86 | }, 87 | { 88 | "size" : "40x40", 89 | "idiom" : "ipad", 90 | "filename" : "Icon-App-40x40@2x.png", 91 | "scale" : "2x" 92 | }, 93 | { 94 | "size" : "76x76", 95 | "idiom" : "ipad", 96 | "filename" : "Icon-App-76x76@1x.png", 97 | "scale" : "1x" 98 | }, 99 | { 100 | "size" : "76x76", 101 | "idiom" : "ipad", 102 | "filename" : "Icon-App-76x76@2x.png", 103 | "scale" : "2x" 104 | }, 105 | { 106 | "size" : "83.5x83.5", 107 | "idiom" : "ipad", 108 | "filename" : "Icon-App-83.5x83.5@2x.png", 109 | "scale" : "2x" 110 | }, 111 | { 112 | "size" : "1024x1024", 113 | "idiom" : "ios-marketing", 114 | "filename" : "Icon-App-1024x1024@1x.png", 115 | "scale" : "1x" 116 | } 117 | ], 118 | "info" : { 119 | "version" : 1, 120 | "author" : "xcode" 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /final/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 37 | 38 | 39 | 40 | 41 | 42 | 52 | 54 | 60 | 61 | 62 | 63 | 69 | 71 | 77 | 78 | 79 | 80 | 82 | 83 | 86 | 87 | 88 | -------------------------------------------------------------------------------- /final/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 37 | 38 | 39 | 40 | 41 | 42 | 52 | 54 | 60 | 61 | 62 | 63 | 69 | 71 | 77 | 78 | 79 | 80 | 82 | 83 | 86 | 87 | 88 | -------------------------------------------------------------------------------- /starter/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 37 | 38 | 39 | 40 | 43 | 49 | 50 | 51 | 52 | 53 | 64 | 66 | 72 | 73 | 74 | 75 | 81 | 83 | 89 | 90 | 91 | 92 | 94 | 95 | 98 | 99 | 100 | -------------------------------------------------------------------------------- /starter/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 31 | 32 | 38 | 39 | 40 | 41 | 44 | 50 | 51 | 52 | 53 | 54 | 66 | 68 | 74 | 75 | 76 | 77 | 83 | 85 | 91 | 92 | 93 | 94 | 96 | 97 | 100 | 101 | 102 | -------------------------------------------------------------------------------- /final/lib/page_manager.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/foundation.dart'; 2 | import 'notifiers/play_button_notifier.dart'; 3 | import 'notifiers/progress_notifier.dart'; 4 | import 'notifiers/repeat_button_notifier.dart'; 5 | import 'package:audio_service/audio_service.dart'; 6 | import 'services/playlist_repository.dart'; 7 | import 'services/service_locator.dart'; 8 | 9 | class PageManager { 10 | // Listeners: Updates going to the UI 11 | final currentSongTitleNotifier = ValueNotifier(''); 12 | final playlistNotifier = ValueNotifier>([]); 13 | final progressNotifier = ProgressNotifier(); 14 | final repeatButtonNotifier = RepeatButtonNotifier(); 15 | final isFirstSongNotifier = ValueNotifier(true); 16 | final playButtonNotifier = PlayButtonNotifier(); 17 | final isLastSongNotifier = ValueNotifier(true); 18 | final isShuffleModeEnabledNotifier = ValueNotifier(false); 19 | 20 | final _audioHandler = getIt(); 21 | 22 | // Events: Calls coming from the UI 23 | void init() async { 24 | await _loadPlaylist(); 25 | _listenToChangesInPlaylist(); 26 | _listenToPlaybackState(); 27 | _listenToCurrentPosition(); 28 | _listenToBufferedPosition(); 29 | _listenToTotalDuration(); 30 | _listenToChangesInSong(); 31 | } 32 | 33 | Future _loadPlaylist() async { 34 | final songRepository = getIt(); 35 | final playlist = await songRepository.fetchInitialPlaylist(); 36 | final mediaItems = playlist 37 | .map((song) => MediaItem( 38 | id: song['id'] ?? '', 39 | album: song['album'] ?? '', 40 | title: song['title'] ?? '', 41 | extras: {'url': song['url']}, 42 | )) 43 | .toList(); 44 | _audioHandler.addQueueItems(mediaItems); 45 | } 46 | 47 | void _listenToChangesInPlaylist() { 48 | _audioHandler.queue.listen((playlist) { 49 | if (playlist.isEmpty) { 50 | playlistNotifier.value = []; 51 | currentSongTitleNotifier.value = ''; 52 | } else { 53 | final newList = playlist.map((item) => item.title).toList(); 54 | playlistNotifier.value = newList; 55 | } 56 | _updateSkipButtons(); 57 | }); 58 | } 59 | 60 | void _listenToPlaybackState() { 61 | _audioHandler.playbackState.listen((playbackState) { 62 | final isPlaying = playbackState.playing; 63 | final processingState = playbackState.processingState; 64 | if (processingState == AudioProcessingState.loading || 65 | processingState == AudioProcessingState.buffering) { 66 | playButtonNotifier.value = ButtonState.loading; 67 | } else if (!isPlaying) { 68 | playButtonNotifier.value = ButtonState.paused; 69 | } else if (processingState != AudioProcessingState.completed) { 70 | playButtonNotifier.value = ButtonState.playing; 71 | } else { 72 | _audioHandler.seek(Duration.zero); 73 | _audioHandler.pause(); 74 | } 75 | }); 76 | } 77 | 78 | void _listenToCurrentPosition() { 79 | AudioService.position.listen((position) { 80 | final oldState = progressNotifier.value; 81 | progressNotifier.value = ProgressBarState( 82 | current: position, 83 | buffered: oldState.buffered, 84 | total: oldState.total, 85 | ); 86 | }); 87 | } 88 | 89 | void _listenToBufferedPosition() { 90 | _audioHandler.playbackState.listen((playbackState) { 91 | final oldState = progressNotifier.value; 92 | progressNotifier.value = ProgressBarState( 93 | current: oldState.current, 94 | buffered: playbackState.bufferedPosition, 95 | total: oldState.total, 96 | ); 97 | }); 98 | } 99 | 100 | void _listenToTotalDuration() { 101 | _audioHandler.mediaItem.listen((mediaItem) { 102 | final oldState = progressNotifier.value; 103 | progressNotifier.value = ProgressBarState( 104 | current: oldState.current, 105 | buffered: oldState.buffered, 106 | total: mediaItem?.duration ?? Duration.zero, 107 | ); 108 | }); 109 | } 110 | 111 | void _listenToChangesInSong() { 112 | _audioHandler.mediaItem.listen((mediaItem) { 113 | currentSongTitleNotifier.value = mediaItem?.title ?? ''; 114 | _updateSkipButtons(); 115 | }); 116 | } 117 | 118 | void _updateSkipButtons() { 119 | final mediaItem = _audioHandler.mediaItem.value; 120 | final playlist = _audioHandler.queue.value; 121 | if (playlist.length < 2 || mediaItem == null) { 122 | isFirstSongNotifier.value = true; 123 | isLastSongNotifier.value = true; 124 | } else { 125 | isFirstSongNotifier.value = playlist.first == mediaItem; 126 | isLastSongNotifier.value = playlist.last == mediaItem; 127 | } 128 | } 129 | 130 | void play() => _audioHandler.play(); 131 | void pause() => _audioHandler.pause(); 132 | 133 | void seek(Duration position) => _audioHandler.seek(position); 134 | 135 | void previous() => _audioHandler.skipToPrevious(); 136 | void next() => _audioHandler.skipToNext(); 137 | 138 | void repeat() { 139 | repeatButtonNotifier.nextState(); 140 | final repeatMode = repeatButtonNotifier.value; 141 | switch (repeatMode) { 142 | case RepeatState.off: 143 | _audioHandler.setRepeatMode(AudioServiceRepeatMode.none); 144 | break; 145 | case RepeatState.repeatSong: 146 | _audioHandler.setRepeatMode(AudioServiceRepeatMode.one); 147 | break; 148 | case RepeatState.repeatPlaylist: 149 | _audioHandler.setRepeatMode(AudioServiceRepeatMode.all); 150 | break; 151 | } 152 | } 153 | 154 | void shuffle() { 155 | final enable = !isShuffleModeEnabledNotifier.value; 156 | isShuffleModeEnabledNotifier.value = enable; 157 | if (enable) { 158 | _audioHandler.setShuffleMode(AudioServiceShuffleMode.all); 159 | } else { 160 | _audioHandler.setShuffleMode(AudioServiceShuffleMode.none); 161 | } 162 | } 163 | 164 | Future add() async { 165 | final songRepository = getIt(); 166 | final song = await songRepository.fetchAnotherSong(); 167 | final mediaItem = MediaItem( 168 | id: song['id'] ?? '', 169 | album: song['album'] ?? '', 170 | title: song['title'] ?? '', 171 | extras: {'url': song['url']}, 172 | ); 173 | _audioHandler.addQueueItem(mediaItem); 174 | } 175 | 176 | void remove() { 177 | final lastIndex = _audioHandler.queue.value.length - 1; 178 | if (lastIndex < 0) return; 179 | _audioHandler.removeQueueItemAt(lastIndex); 180 | } 181 | 182 | void dispose() { 183 | _audioHandler.customAction('dispose'); 184 | } 185 | 186 | void stop() { 187 | _audioHandler.stop(); 188 | } 189 | } 190 | -------------------------------------------------------------------------------- /final/lib/services/audio_handler.dart: -------------------------------------------------------------------------------- 1 | import 'package:audio_service/audio_service.dart'; 2 | import 'package:just_audio/just_audio.dart'; 3 | 4 | Future initAudioService() async { 5 | return await AudioService.init( 6 | builder: () => MyAudioHandler(), 7 | config: const AudioServiceConfig( 8 | androidNotificationChannelId: 'com.mycompany.myapp.audio', 9 | androidNotificationChannelName: 'Audio Service Demo', 10 | androidNotificationOngoing: true, 11 | androidStopForegroundOnPause: true, 12 | ), 13 | ); 14 | } 15 | 16 | class MyAudioHandler extends BaseAudioHandler { 17 | final _player = AudioPlayer(); 18 | final _playlist = ConcatenatingAudioSource(children: []); 19 | 20 | MyAudioHandler() { 21 | _loadEmptyPlaylist(); 22 | _notifyAudioHandlerAboutPlaybackEvents(); 23 | _listenForDurationChanges(); 24 | _listenForCurrentSongIndexChanges(); 25 | _listenForSequenceStateChanges(); 26 | } 27 | 28 | Future _loadEmptyPlaylist() async { 29 | try { 30 | await _player.setAudioSource(_playlist); 31 | } catch (e) { 32 | print("Error: $e"); 33 | } 34 | } 35 | 36 | void _notifyAudioHandlerAboutPlaybackEvents() { 37 | _player.playbackEventStream.listen((PlaybackEvent event) { 38 | final playing = _player.playing; 39 | playbackState.add(playbackState.value.copyWith( 40 | controls: [ 41 | MediaControl.skipToPrevious, 42 | if (playing) MediaControl.pause else MediaControl.play, 43 | MediaControl.stop, 44 | MediaControl.skipToNext, 45 | ], 46 | systemActions: const { 47 | MediaAction.seek, 48 | }, 49 | androidCompactActionIndices: const [0, 1, 3], 50 | processingState: const { 51 | ProcessingState.idle: AudioProcessingState.idle, 52 | ProcessingState.loading: AudioProcessingState.loading, 53 | ProcessingState.buffering: AudioProcessingState.buffering, 54 | ProcessingState.ready: AudioProcessingState.ready, 55 | ProcessingState.completed: AudioProcessingState.completed, 56 | }[_player.processingState]!, 57 | repeatMode: const { 58 | LoopMode.off: AudioServiceRepeatMode.none, 59 | LoopMode.one: AudioServiceRepeatMode.one, 60 | LoopMode.all: AudioServiceRepeatMode.all, 61 | }[_player.loopMode]!, 62 | shuffleMode: (_player.shuffleModeEnabled) 63 | ? AudioServiceShuffleMode.all 64 | : AudioServiceShuffleMode.none, 65 | playing: playing, 66 | updatePosition: _player.position, 67 | bufferedPosition: _player.bufferedPosition, 68 | speed: _player.speed, 69 | queueIndex: event.currentIndex, 70 | )); 71 | }); 72 | } 73 | 74 | void _listenForDurationChanges() { 75 | _player.durationStream.listen((duration) { 76 | var index = _player.currentIndex; 77 | final newQueue = queue.value; 78 | if (index == null || newQueue.isEmpty) return; 79 | if (_player.shuffleModeEnabled) { 80 | index = _player.shuffleIndices!.indexOf(index); 81 | } 82 | final oldMediaItem = newQueue[index]; 83 | final newMediaItem = oldMediaItem.copyWith(duration: duration); 84 | newQueue[index] = newMediaItem; 85 | queue.add(newQueue); 86 | mediaItem.add(newMediaItem); 87 | }); 88 | } 89 | 90 | void _listenForCurrentSongIndexChanges() { 91 | _player.currentIndexStream.listen((index) { 92 | final playlist = queue.value; 93 | if (index == null || playlist.isEmpty) return; 94 | if (_player.shuffleModeEnabled) { 95 | index = _player.shuffleIndices!.indexOf(index); 96 | } 97 | mediaItem.add(playlist[index]); 98 | }); 99 | } 100 | 101 | void _listenForSequenceStateChanges() { 102 | _player.sequenceStateStream.listen((SequenceState? sequenceState) { 103 | final sequence = sequenceState?.effectiveSequence; 104 | if (sequence == null || sequence.isEmpty) return; 105 | final items = sequence.map((source) => source.tag as MediaItem); 106 | queue.add(items.toList()); 107 | }); 108 | } 109 | 110 | @override 111 | Future addQueueItems(List mediaItems) async { 112 | // manage Just Audio 113 | final audioSource = mediaItems.map(_createAudioSource); 114 | _playlist.addAll(audioSource.toList()); 115 | 116 | // notify system 117 | final newQueue = queue.value..addAll(mediaItems); 118 | queue.add(newQueue); 119 | } 120 | 121 | @override 122 | Future addQueueItem(MediaItem mediaItem) async { 123 | // manage Just Audio 124 | final audioSource = _createAudioSource(mediaItem); 125 | _playlist.add(audioSource); 126 | 127 | // notify system 128 | final newQueue = queue.value..add(mediaItem); 129 | queue.add(newQueue); 130 | } 131 | 132 | UriAudioSource _createAudioSource(MediaItem mediaItem) { 133 | return AudioSource.uri( 134 | Uri.parse(mediaItem.extras!['url'] as String), 135 | tag: mediaItem, 136 | ); 137 | } 138 | 139 | @override 140 | Future removeQueueItemAt(int index) async { 141 | // manage Just Audio 142 | _playlist.removeAt(index); 143 | 144 | // notify system 145 | final newQueue = queue.value..removeAt(index); 146 | queue.add(newQueue); 147 | } 148 | 149 | @override 150 | Future play() => _player.play(); 151 | 152 | @override 153 | Future pause() => _player.pause(); 154 | 155 | @override 156 | Future seek(Duration position) => _player.seek(position); 157 | 158 | @override 159 | Future skipToQueueItem(int index) async { 160 | if (index < 0 || index >= queue.value.length) return; 161 | if (_player.shuffleModeEnabled) { 162 | index = _player.shuffleIndices![index]; 163 | } 164 | _player.seek(Duration.zero, index: index); 165 | } 166 | 167 | @override 168 | Future skipToNext() => _player.seekToNext(); 169 | 170 | @override 171 | Future skipToPrevious() => _player.seekToPrevious(); 172 | 173 | @override 174 | Future setRepeatMode(AudioServiceRepeatMode repeatMode) async { 175 | switch (repeatMode) { 176 | case AudioServiceRepeatMode.none: 177 | _player.setLoopMode(LoopMode.off); 178 | break; 179 | case AudioServiceRepeatMode.one: 180 | _player.setLoopMode(LoopMode.one); 181 | break; 182 | case AudioServiceRepeatMode.group: 183 | case AudioServiceRepeatMode.all: 184 | _player.setLoopMode(LoopMode.all); 185 | break; 186 | } 187 | } 188 | 189 | @override 190 | Future setShuffleMode(AudioServiceShuffleMode shuffleMode) async { 191 | if (shuffleMode == AudioServiceShuffleMode.none) { 192 | _player.setShuffleModeEnabled(false); 193 | } else { 194 | await _player.shuffle(); 195 | _player.setShuffleModeEnabled(true); 196 | } 197 | } 198 | 199 | @override 200 | Future customAction(String name, [Map? extras]) async { 201 | if (name == 'dispose') { 202 | await _player.dispose(); 203 | super.stop(); 204 | } 205 | } 206 | 207 | @override 208 | Future stop() async { 209 | await _player.stop(); 210 | return super.stop(); 211 | } 212 | } 213 | -------------------------------------------------------------------------------- /starter/pubspec.lock: -------------------------------------------------------------------------------- 1 | # Generated by pub 2 | # See https://dart.dev/tools/pub/glossary#lockfile 3 | packages: 4 | async: 5 | dependency: transitive 6 | description: 7 | name: async 8 | sha256: "758e6d74e971c3e5aceb4110bfd6698efc7f501675bcfe0c775459a8140750eb" 9 | url: "https://pub.dev" 10 | source: hosted 11 | version: "2.13.0" 12 | audio_video_progress_bar: 13 | dependency: "direct main" 14 | description: 15 | name: audio_video_progress_bar 16 | sha256: "552b1f73c56c4c88407999e0a8507176f60c56de3e6d63bc20a0eab48467d4c9" 17 | url: "https://pub.dev" 18 | source: hosted 19 | version: "2.0.3" 20 | boolean_selector: 21 | dependency: transitive 22 | description: 23 | name: boolean_selector 24 | sha256: "8aab1771e1243a5063b8b0ff68042d67334e3feab9e95b9490f9a6ebf73b42ea" 25 | url: "https://pub.dev" 26 | source: hosted 27 | version: "2.1.2" 28 | characters: 29 | dependency: transitive 30 | description: 31 | name: characters 32 | sha256: f71061c654a3380576a52b451dd5532377954cf9dbd272a78fc8479606670803 33 | url: "https://pub.dev" 34 | source: hosted 35 | version: "1.4.0" 36 | clock: 37 | dependency: transitive 38 | description: 39 | name: clock 40 | sha256: fddb70d9b5277016c77a80201021d40a2247104d9f4aa7bab7157b7e3f05b84b 41 | url: "https://pub.dev" 42 | source: hosted 43 | version: "1.1.2" 44 | collection: 45 | dependency: transitive 46 | description: 47 | name: collection 48 | sha256: "2f5709ae4d3d59dd8f7cd309b4e023046b57d8a6c82130785d2b0e5868084e76" 49 | url: "https://pub.dev" 50 | source: hosted 51 | version: "1.19.1" 52 | fake_async: 53 | dependency: transitive 54 | description: 55 | name: fake_async 56 | sha256: "5368f224a74523e8d2e7399ea1638b37aecfca824a3cc4dfdf77bf1fa905ac44" 57 | url: "https://pub.dev" 58 | source: hosted 59 | version: "1.3.3" 60 | flutter: 61 | dependency: "direct main" 62 | description: flutter 63 | source: sdk 64 | version: "0.0.0" 65 | flutter_lints: 66 | dependency: "direct dev" 67 | description: 68 | name: flutter_lints 69 | sha256: aeb0b80a8b3709709c9cc496cdc027c5b3216796bc0af0ce1007eaf24464fd4c 70 | url: "https://pub.dev" 71 | source: hosted 72 | version: "2.0.1" 73 | flutter_test: 74 | dependency: "direct dev" 75 | description: flutter 76 | source: sdk 77 | version: "0.0.0" 78 | get_it: 79 | dependency: "direct main" 80 | description: 81 | name: get_it 82 | sha256: f126a3e286b7f5b578bf436d5592968706c4c1de28a228b870ce375d9f743103 83 | url: "https://pub.dev" 84 | source: hosted 85 | version: "8.0.3" 86 | leak_tracker: 87 | dependency: transitive 88 | description: 89 | name: leak_tracker 90 | sha256: "6bb818ecbdffe216e81182c2f0714a2e62b593f4a4f13098713ff1685dfb6ab0" 91 | url: "https://pub.dev" 92 | source: hosted 93 | version: "10.0.9" 94 | leak_tracker_flutter_testing: 95 | dependency: transitive 96 | description: 97 | name: leak_tracker_flutter_testing 98 | sha256: f8b613e7e6a13ec79cfdc0e97638fddb3ab848452eff057653abd3edba760573 99 | url: "https://pub.dev" 100 | source: hosted 101 | version: "3.0.9" 102 | leak_tracker_testing: 103 | dependency: transitive 104 | description: 105 | name: leak_tracker_testing 106 | sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3" 107 | url: "https://pub.dev" 108 | source: hosted 109 | version: "3.0.1" 110 | lints: 111 | dependency: transitive 112 | description: 113 | name: lints 114 | sha256: "5e4a9cd06d447758280a8ac2405101e0e2094d2a1dbdd3756aec3fe7775ba593" 115 | url: "https://pub.dev" 116 | source: hosted 117 | version: "2.0.1" 118 | matcher: 119 | dependency: transitive 120 | description: 121 | name: matcher 122 | sha256: dc58c723c3c24bf8d3e2d3ad3f2f9d7bd9cf43ec6feaa64181775e60190153f2 123 | url: "https://pub.dev" 124 | source: hosted 125 | version: "0.12.17" 126 | material_color_utilities: 127 | dependency: transitive 128 | description: 129 | name: material_color_utilities 130 | sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec 131 | url: "https://pub.dev" 132 | source: hosted 133 | version: "0.11.1" 134 | meta: 135 | dependency: transitive 136 | description: 137 | name: meta 138 | sha256: e3641ec5d63ebf0d9b41bd43201a66e3fc79a65db5f61fc181f04cd27aab950c 139 | url: "https://pub.dev" 140 | source: hosted 141 | version: "1.16.0" 142 | path: 143 | dependency: transitive 144 | description: 145 | name: path 146 | sha256: "75cca69d1490965be98c73ceaea117e8a04dd21217b37b292c9ddbec0d955bc5" 147 | url: "https://pub.dev" 148 | source: hosted 149 | version: "1.9.1" 150 | sky_engine: 151 | dependency: transitive 152 | description: flutter 153 | source: sdk 154 | version: "0.0.0" 155 | source_span: 156 | dependency: transitive 157 | description: 158 | name: source_span 159 | sha256: "254ee5351d6cb365c859e20ee823c3bb479bf4a293c22d17a9f1bf144ce86f7c" 160 | url: "https://pub.dev" 161 | source: hosted 162 | version: "1.10.1" 163 | stack_trace: 164 | dependency: transitive 165 | description: 166 | name: stack_trace 167 | sha256: "8b27215b45d22309b5cddda1aa2b19bdfec9df0e765f2de506401c071d38d1b1" 168 | url: "https://pub.dev" 169 | source: hosted 170 | version: "1.12.1" 171 | stream_channel: 172 | dependency: transitive 173 | description: 174 | name: stream_channel 175 | sha256: "969e04c80b8bcdf826f8f16579c7b14d780458bd97f56d107d3950fdbeef059d" 176 | url: "https://pub.dev" 177 | source: hosted 178 | version: "2.1.4" 179 | string_scanner: 180 | dependency: transitive 181 | description: 182 | name: string_scanner 183 | sha256: "921cd31725b72fe181906c6a94d987c78e3b98c2e205b397ea399d4054872b43" 184 | url: "https://pub.dev" 185 | source: hosted 186 | version: "1.4.1" 187 | term_glyph: 188 | dependency: transitive 189 | description: 190 | name: term_glyph 191 | sha256: "7f554798625ea768a7518313e58f83891c7f5024f88e46e7182a4558850a4b8e" 192 | url: "https://pub.dev" 193 | source: hosted 194 | version: "1.2.2" 195 | test_api: 196 | dependency: transitive 197 | description: 198 | name: test_api 199 | sha256: fb31f383e2ee25fbbfe06b40fe21e1e458d14080e3c67e7ba0acfde4df4e0bbd 200 | url: "https://pub.dev" 201 | source: hosted 202 | version: "0.7.4" 203 | vector_math: 204 | dependency: transitive 205 | description: 206 | name: vector_math 207 | sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" 208 | url: "https://pub.dev" 209 | source: hosted 210 | version: "2.1.4" 211 | vm_service: 212 | dependency: transitive 213 | description: 214 | name: vm_service 215 | sha256: ddfa8d30d89985b96407efce8acbdd124701f96741f2d981ca860662f1c0dc02 216 | url: "https://pub.dev" 217 | source: hosted 218 | version: "15.0.0" 219 | sdks: 220 | dart: ">=3.8.0 <4.0.0" 221 | flutter: ">=3.18.0-18.0.pre.54" 222 | -------------------------------------------------------------------------------- /starter/lib/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:audio_video_progress_bar/audio_video_progress_bar.dart'; 2 | import 'package:flutter/material.dart'; 3 | import 'notifiers/play_button_notifier.dart'; 4 | import 'notifiers/progress_notifier.dart'; 5 | import 'notifiers/repeat_button_notifier.dart'; 6 | import 'page_manager.dart'; 7 | import 'services/service_locator.dart'; 8 | 9 | void main() async { 10 | await setupServiceLocator(); 11 | runApp(const MyApp()); 12 | } 13 | 14 | class MyApp extends StatefulWidget { 15 | const MyApp({super.key}); 16 | 17 | @override 18 | State createState() => _MyAppState(); 19 | } 20 | 21 | class _MyAppState extends State { 22 | @override 23 | void initState() { 24 | super.initState(); 25 | getIt().init(); 26 | } 27 | 28 | @override 29 | void dispose() { 30 | getIt().dispose(); 31 | super.dispose(); 32 | } 33 | 34 | @override 35 | Widget build(BuildContext context) { 36 | return const MaterialApp( 37 | home: Scaffold( 38 | body: Padding( 39 | padding: EdgeInsets.all(20.0), 40 | child: Column( 41 | children: [ 42 | CurrentSongTitle(), 43 | Playlist(), 44 | AddRemoveSongButtons(), 45 | AudioProgressBar(), 46 | AudioControlButtons(), 47 | ], 48 | ), 49 | ), 50 | ), 51 | ); 52 | } 53 | } 54 | 55 | class CurrentSongTitle extends StatelessWidget { 56 | const CurrentSongTitle({Key? key}) : super(key: key); 57 | @override 58 | Widget build(BuildContext context) { 59 | final pageManager = getIt(); 60 | return ValueListenableBuilder( 61 | valueListenable: pageManager.currentSongTitleNotifier, 62 | builder: (_, title, __) { 63 | return Padding( 64 | padding: const EdgeInsets.only(top: 8.0), 65 | child: Text(title, style: const TextStyle(fontSize: 40)), 66 | ); 67 | }, 68 | ); 69 | } 70 | } 71 | 72 | class Playlist extends StatelessWidget { 73 | const Playlist({Key? key}) : super(key: key); 74 | @override 75 | Widget build(BuildContext context) { 76 | final pageManager = getIt(); 77 | return Expanded( 78 | child: ValueListenableBuilder>( 79 | valueListenable: pageManager.playlistNotifier, 80 | builder: (context, playlistTitles, _) { 81 | return ListView.builder( 82 | itemCount: playlistTitles.length, 83 | itemBuilder: (context, index) { 84 | return ListTile(title: Text(playlistTitles[index])); 85 | }, 86 | ); 87 | }, 88 | ), 89 | ); 90 | } 91 | } 92 | 93 | class AddRemoveSongButtons extends StatelessWidget { 94 | const AddRemoveSongButtons({Key? key}) : super(key: key); 95 | @override 96 | Widget build(BuildContext context) { 97 | final pageManager = getIt(); 98 | return Padding( 99 | padding: const EdgeInsets.only(bottom: 20.0), 100 | child: Row( 101 | mainAxisAlignment: MainAxisAlignment.spaceEvenly, 102 | children: [ 103 | FloatingActionButton( 104 | onPressed: pageManager.add, 105 | child: const Icon(Icons.add), 106 | ), 107 | FloatingActionButton( 108 | onPressed: pageManager.remove, 109 | child: const Icon(Icons.remove), 110 | ), 111 | ], 112 | ), 113 | ); 114 | } 115 | } 116 | 117 | class AudioProgressBar extends StatelessWidget { 118 | const AudioProgressBar({Key? key}) : super(key: key); 119 | @override 120 | Widget build(BuildContext context) { 121 | final pageManager = getIt(); 122 | return ValueListenableBuilder( 123 | valueListenable: pageManager.progressNotifier, 124 | builder: (_, value, __) { 125 | return ProgressBar( 126 | progress: value.current, 127 | buffered: value.buffered, 128 | total: value.total, 129 | onSeek: pageManager.seek, 130 | ); 131 | }, 132 | ); 133 | } 134 | } 135 | 136 | class AudioControlButtons extends StatelessWidget { 137 | const AudioControlButtons({Key? key}) : super(key: key); 138 | @override 139 | Widget build(BuildContext context) { 140 | return const SizedBox( 141 | height: 60, 142 | child: Row( 143 | mainAxisAlignment: MainAxisAlignment.spaceAround, 144 | children: [ 145 | RepeatButton(), 146 | PreviousSongButton(), 147 | PlayButton(), 148 | NextSongButton(), 149 | ShuffleButton(), 150 | ], 151 | ), 152 | ); 153 | } 154 | } 155 | 156 | class RepeatButton extends StatelessWidget { 157 | const RepeatButton({Key? key}) : super(key: key); 158 | @override 159 | Widget build(BuildContext context) { 160 | final pageManager = getIt(); 161 | return ValueListenableBuilder( 162 | valueListenable: pageManager.repeatButtonNotifier, 163 | builder: (context, value, child) { 164 | Icon icon; 165 | switch (value) { 166 | case RepeatState.off: 167 | icon = const Icon(Icons.repeat, color: Colors.grey); 168 | break; 169 | case RepeatState.repeatSong: 170 | icon = const Icon(Icons.repeat_one); 171 | break; 172 | case RepeatState.repeatPlaylist: 173 | icon = const Icon(Icons.repeat); 174 | break; 175 | } 176 | return IconButton(icon: icon, onPressed: pageManager.repeat); 177 | }, 178 | ); 179 | } 180 | } 181 | 182 | class PreviousSongButton extends StatelessWidget { 183 | const PreviousSongButton({Key? key}) : super(key: key); 184 | @override 185 | Widget build(BuildContext context) { 186 | final pageManager = getIt(); 187 | return ValueListenableBuilder( 188 | valueListenable: pageManager.isFirstSongNotifier, 189 | builder: (_, isFirst, __) { 190 | return IconButton( 191 | icon: const Icon(Icons.skip_previous), 192 | onPressed: (isFirst) ? null : pageManager.previous, 193 | ); 194 | }, 195 | ); 196 | } 197 | } 198 | 199 | class PlayButton extends StatelessWidget { 200 | const PlayButton({Key? key}) : super(key: key); 201 | @override 202 | Widget build(BuildContext context) { 203 | final pageManager = getIt(); 204 | return ValueListenableBuilder( 205 | valueListenable: pageManager.playButtonNotifier, 206 | builder: (_, value, __) { 207 | switch (value) { 208 | case ButtonState.loading: 209 | return Container( 210 | margin: const EdgeInsets.all(8.0), 211 | width: 32.0, 212 | height: 32.0, 213 | child: const CircularProgressIndicator(), 214 | ); 215 | case ButtonState.paused: 216 | return IconButton( 217 | icon: const Icon(Icons.play_arrow), 218 | iconSize: 32.0, 219 | onPressed: pageManager.play, 220 | ); 221 | case ButtonState.playing: 222 | return IconButton( 223 | icon: const Icon(Icons.pause), 224 | iconSize: 32.0, 225 | onPressed: pageManager.pause, 226 | ); 227 | } 228 | }, 229 | ); 230 | } 231 | } 232 | 233 | class NextSongButton extends StatelessWidget { 234 | const NextSongButton({Key? key}) : super(key: key); 235 | @override 236 | Widget build(BuildContext context) { 237 | final pageManager = getIt(); 238 | return ValueListenableBuilder( 239 | valueListenable: pageManager.isLastSongNotifier, 240 | builder: (_, isLast, __) { 241 | return IconButton( 242 | icon: const Icon(Icons.skip_next), 243 | onPressed: (isLast) ? null : pageManager.next, 244 | ); 245 | }, 246 | ); 247 | } 248 | } 249 | 250 | class ShuffleButton extends StatelessWidget { 251 | const ShuffleButton({Key? key}) : super(key: key); 252 | @override 253 | Widget build(BuildContext context) { 254 | final pageManager = getIt(); 255 | return ValueListenableBuilder( 256 | valueListenable: pageManager.isShuffleModeEnabledNotifier, 257 | builder: (context, isEnabled, child) { 258 | return IconButton( 259 | icon: (isEnabled) 260 | ? const Icon(Icons.shuffle) 261 | : const Icon(Icons.shuffle, color: Colors.grey), 262 | onPressed: pageManager.shuffle, 263 | ); 264 | }, 265 | ); 266 | } 267 | } 268 | -------------------------------------------------------------------------------- /final/lib/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:audio_video_progress_bar/audio_video_progress_bar.dart'; 2 | import 'package:flutter/material.dart'; 3 | import 'notifiers/play_button_notifier.dart'; 4 | import 'notifiers/progress_notifier.dart'; 5 | import 'notifiers/repeat_button_notifier.dart'; 6 | import 'page_manager.dart'; 7 | import 'services/service_locator.dart'; 8 | 9 | void main() async { 10 | await setupServiceLocator(); 11 | runApp(const MyApp()); 12 | } 13 | 14 | class MyApp extends StatefulWidget { 15 | const MyApp({super.key}); 16 | 17 | @override 18 | State createState() => _MyAppState(); 19 | } 20 | 21 | class _MyAppState extends State { 22 | @override 23 | void initState() { 24 | super.initState(); 25 | getIt().init(); 26 | } 27 | 28 | @override 29 | void dispose() { 30 | getIt().dispose(); 31 | super.dispose(); 32 | } 33 | 34 | @override 35 | Widget build(BuildContext context) { 36 | return MaterialApp( 37 | home: Scaffold( 38 | body: Padding( 39 | padding: const EdgeInsets.all(20.0), 40 | child: Column( 41 | children: const [ 42 | CurrentSongTitle(), 43 | Playlist(), 44 | AddRemoveSongButtons(), 45 | AudioProgressBar(), 46 | AudioControlButtons(), 47 | ], 48 | ), 49 | ), 50 | ), 51 | ); 52 | } 53 | } 54 | 55 | class CurrentSongTitle extends StatelessWidget { 56 | const CurrentSongTitle({Key? key}) : super(key: key); 57 | @override 58 | Widget build(BuildContext context) { 59 | final pageManager = getIt(); 60 | return ValueListenableBuilder( 61 | valueListenable: pageManager.currentSongTitleNotifier, 62 | builder: (_, title, __) { 63 | return Padding( 64 | padding: const EdgeInsets.only(top: 8.0), 65 | child: Text(title, style: const TextStyle(fontSize: 40)), 66 | ); 67 | }, 68 | ); 69 | } 70 | } 71 | 72 | class Playlist extends StatelessWidget { 73 | const Playlist({Key? key}) : super(key: key); 74 | @override 75 | Widget build(BuildContext context) { 76 | final pageManager = getIt(); 77 | return Expanded( 78 | child: ValueListenableBuilder>( 79 | valueListenable: pageManager.playlistNotifier, 80 | builder: (context, playlistTitles, _) { 81 | return ListView.builder( 82 | itemCount: playlistTitles.length, 83 | itemBuilder: (context, index) { 84 | return ListTile( 85 | title: Text(playlistTitles[index]), 86 | ); 87 | }, 88 | ); 89 | }, 90 | ), 91 | ); 92 | } 93 | } 94 | 95 | class AddRemoveSongButtons extends StatelessWidget { 96 | const AddRemoveSongButtons({Key? key}) : super(key: key); 97 | @override 98 | Widget build(BuildContext context) { 99 | final pageManager = getIt(); 100 | return Padding( 101 | padding: const EdgeInsets.only(bottom: 20.0), 102 | child: Row( 103 | mainAxisAlignment: MainAxisAlignment.spaceEvenly, 104 | children: [ 105 | FloatingActionButton( 106 | onPressed: pageManager.add, 107 | child: const Icon(Icons.add), 108 | ), 109 | FloatingActionButton( 110 | onPressed: pageManager.remove, 111 | child: const Icon(Icons.remove), 112 | ), 113 | ], 114 | ), 115 | ); 116 | } 117 | } 118 | 119 | class AudioProgressBar extends StatelessWidget { 120 | const AudioProgressBar({Key? key}) : super(key: key); 121 | @override 122 | Widget build(BuildContext context) { 123 | final pageManager = getIt(); 124 | return ValueListenableBuilder( 125 | valueListenable: pageManager.progressNotifier, 126 | builder: (_, value, __) { 127 | return ProgressBar( 128 | progress: value.current, 129 | buffered: value.buffered, 130 | total: value.total, 131 | onSeek: pageManager.seek, 132 | ); 133 | }, 134 | ); 135 | } 136 | } 137 | 138 | class AudioControlButtons extends StatelessWidget { 139 | const AudioControlButtons({Key? key}) : super(key: key); 140 | @override 141 | Widget build(BuildContext context) { 142 | return SizedBox( 143 | height: 60, 144 | child: Row( 145 | mainAxisAlignment: MainAxisAlignment.spaceAround, 146 | children: const [ 147 | RepeatButton(), 148 | PreviousSongButton(), 149 | PlayButton(), 150 | NextSongButton(), 151 | ShuffleButton(), 152 | ], 153 | ), 154 | ); 155 | } 156 | } 157 | 158 | class RepeatButton extends StatelessWidget { 159 | const RepeatButton({Key? key}) : super(key: key); 160 | @override 161 | Widget build(BuildContext context) { 162 | final pageManager = getIt(); 163 | return ValueListenableBuilder( 164 | valueListenable: pageManager.repeatButtonNotifier, 165 | builder: (context, value, child) { 166 | Icon icon; 167 | switch (value) { 168 | case RepeatState.off: 169 | icon = const Icon(Icons.repeat, color: Colors.grey); 170 | break; 171 | case RepeatState.repeatSong: 172 | icon = const Icon(Icons.repeat_one); 173 | break; 174 | case RepeatState.repeatPlaylist: 175 | icon = const Icon(Icons.repeat); 176 | break; 177 | } 178 | return IconButton( 179 | icon: icon, 180 | onPressed: pageManager.repeat, 181 | ); 182 | }, 183 | ); 184 | } 185 | } 186 | 187 | class PreviousSongButton extends StatelessWidget { 188 | const PreviousSongButton({Key? key}) : super(key: key); 189 | @override 190 | Widget build(BuildContext context) { 191 | final pageManager = getIt(); 192 | return ValueListenableBuilder( 193 | valueListenable: pageManager.isFirstSongNotifier, 194 | builder: (_, isFirst, __) { 195 | return IconButton( 196 | icon: const Icon(Icons.skip_previous), 197 | onPressed: (isFirst) ? null : pageManager.previous, 198 | ); 199 | }, 200 | ); 201 | } 202 | } 203 | 204 | class PlayButton extends StatelessWidget { 205 | const PlayButton({Key? key}) : super(key: key); 206 | @override 207 | Widget build(BuildContext context) { 208 | final pageManager = getIt(); 209 | return ValueListenableBuilder( 210 | valueListenable: pageManager.playButtonNotifier, 211 | builder: (_, value, __) { 212 | switch (value) { 213 | case ButtonState.loading: 214 | return Container( 215 | margin: const EdgeInsets.all(8.0), 216 | width: 32.0, 217 | height: 32.0, 218 | child: const CircularProgressIndicator(), 219 | ); 220 | case ButtonState.paused: 221 | return IconButton( 222 | icon: const Icon(Icons.play_arrow), 223 | iconSize: 32.0, 224 | onPressed: pageManager.play, 225 | ); 226 | case ButtonState.playing: 227 | return IconButton( 228 | icon: const Icon(Icons.pause), 229 | iconSize: 32.0, 230 | onPressed: pageManager.pause, 231 | ); 232 | } 233 | }, 234 | ); 235 | } 236 | } 237 | 238 | class NextSongButton extends StatelessWidget { 239 | const NextSongButton({Key? key}) : super(key: key); 240 | @override 241 | Widget build(BuildContext context) { 242 | final pageManager = getIt(); 243 | return ValueListenableBuilder( 244 | valueListenable: pageManager.isLastSongNotifier, 245 | builder: (_, isLast, __) { 246 | return IconButton( 247 | icon: const Icon(Icons.skip_next), 248 | onPressed: (isLast) ? null : pageManager.next, 249 | ); 250 | }, 251 | ); 252 | } 253 | } 254 | 255 | class ShuffleButton extends StatelessWidget { 256 | const ShuffleButton({Key? key}) : super(key: key); 257 | @override 258 | Widget build(BuildContext context) { 259 | final pageManager = getIt(); 260 | return ValueListenableBuilder( 261 | valueListenable: pageManager.isShuffleModeEnabledNotifier, 262 | builder: (context, isEnabled, child) { 263 | return IconButton( 264 | icon: (isEnabled) 265 | ? const Icon(Icons.shuffle) 266 | : const Icon(Icons.shuffle, color: Colors.grey), 267 | onPressed: pageManager.shuffle, 268 | ); 269 | }, 270 | ); 271 | } 272 | } 273 | -------------------------------------------------------------------------------- /final/pubspec.lock: -------------------------------------------------------------------------------- 1 | # Generated by pub 2 | # See https://dart.dev/tools/pub/glossary#lockfile 3 | packages: 4 | async: 5 | dependency: transitive 6 | description: 7 | name: async 8 | sha256: "758e6d74e971c3e5aceb4110bfd6698efc7f501675bcfe0c775459a8140750eb" 9 | url: "https://pub.dev" 10 | source: hosted 11 | version: "2.13.0" 12 | audio_service: 13 | dependency: "direct main" 14 | description: 15 | name: audio_service 16 | sha256: "7e86d7ce23caad605199f7b25e548fe7b618fb0c150fa0585f47a910fe7e7a67" 17 | url: "https://pub.dev" 18 | source: hosted 19 | version: "0.18.9" 20 | audio_service_platform_interface: 21 | dependency: transitive 22 | description: 23 | name: audio_service_platform_interface 24 | sha256: "2c3a1d52803931e836b9693547a71c0c3585ad54219d2214219ed5cfcc3c1af4" 25 | url: "https://pub.dev" 26 | source: hosted 27 | version: "0.1.0" 28 | audio_service_web: 29 | dependency: transitive 30 | description: 31 | name: audio_service_web 32 | sha256: "523e64ddc914c714d53eec2da85bba1074f08cf26c786d4efb322de510815ea7" 33 | url: "https://pub.dev" 34 | source: hosted 35 | version: "0.1.1" 36 | audio_session: 37 | dependency: transitive 38 | description: 39 | name: audio_session 40 | sha256: e4acc4e9eaa32436dfc5d7aed7f0a370f2d7bb27ee27de30d6c4f220c2a05c73 41 | url: "https://pub.dev" 42 | source: hosted 43 | version: "0.1.13" 44 | audio_video_progress_bar: 45 | dependency: "direct main" 46 | description: 47 | name: audio_video_progress_bar 48 | sha256: "38d8efe20cd0ff2bfad648396ae3d4ba6f8058b7d8b6ee6cb26e3245eda58ddd" 49 | url: "https://pub.dev" 50 | source: hosted 51 | version: "1.0.0" 52 | boolean_selector: 53 | dependency: transitive 54 | description: 55 | name: boolean_selector 56 | sha256: "8aab1771e1243a5063b8b0ff68042d67334e3feab9e95b9490f9a6ebf73b42ea" 57 | url: "https://pub.dev" 58 | source: hosted 59 | version: "2.1.2" 60 | characters: 61 | dependency: transitive 62 | description: 63 | name: characters 64 | sha256: f71061c654a3380576a52b451dd5532377954cf9dbd272a78fc8479606670803 65 | url: "https://pub.dev" 66 | source: hosted 67 | version: "1.4.0" 68 | clock: 69 | dependency: transitive 70 | description: 71 | name: clock 72 | sha256: fddb70d9b5277016c77a80201021d40a2247104d9f4aa7bab7157b7e3f05b84b 73 | url: "https://pub.dev" 74 | source: hosted 75 | version: "1.1.2" 76 | collection: 77 | dependency: transitive 78 | description: 79 | name: collection 80 | sha256: "2f5709ae4d3d59dd8f7cd309b4e023046b57d8a6c82130785d2b0e5868084e76" 81 | url: "https://pub.dev" 82 | source: hosted 83 | version: "1.19.1" 84 | crypto: 85 | dependency: transitive 86 | description: 87 | name: crypto 88 | sha256: aa274aa7774f8964e4f4f38cc994db7b6158dd36e9187aaceaddc994b35c6c67 89 | url: "https://pub.dev" 90 | source: hosted 91 | version: "3.0.2" 92 | fake_async: 93 | dependency: transitive 94 | description: 95 | name: fake_async 96 | sha256: "5368f224a74523e8d2e7399ea1638b37aecfca824a3cc4dfdf77bf1fa905ac44" 97 | url: "https://pub.dev" 98 | source: hosted 99 | version: "1.3.3" 100 | ffi: 101 | dependency: transitive 102 | description: 103 | name: ffi 104 | sha256: a38574032c5f1dd06c4aee541789906c12ccaab8ba01446e800d9c5b79c4a978 105 | url: "https://pub.dev" 106 | source: hosted 107 | version: "2.0.1" 108 | file: 109 | dependency: transitive 110 | description: 111 | name: file 112 | sha256: "1b92bec4fc2a72f59a8e15af5f52cd441e4a7860b49499d69dfa817af20e925d" 113 | url: "https://pub.dev" 114 | source: hosted 115 | version: "6.1.4" 116 | flutter: 117 | dependency: "direct main" 118 | description: flutter 119 | source: sdk 120 | version: "0.0.0" 121 | flutter_cache_manager: 122 | dependency: transitive 123 | description: 124 | name: flutter_cache_manager 125 | sha256: "32cd900555219333326a2d0653aaaf8671264c29befa65bbd9856d204a4c9fb3" 126 | url: "https://pub.dev" 127 | source: hosted 128 | version: "3.3.0" 129 | flutter_lints: 130 | dependency: "direct dev" 131 | description: 132 | name: flutter_lints 133 | sha256: aeb0b80a8b3709709c9cc496cdc027c5b3216796bc0af0ce1007eaf24464fd4c 134 | url: "https://pub.dev" 135 | source: hosted 136 | version: "2.0.1" 137 | flutter_test: 138 | dependency: "direct dev" 139 | description: flutter 140 | source: sdk 141 | version: "0.0.0" 142 | flutter_web_plugins: 143 | dependency: transitive 144 | description: flutter 145 | source: sdk 146 | version: "0.0.0" 147 | get_it: 148 | dependency: "direct main" 149 | description: 150 | name: get_it 151 | sha256: "290fde3a86072e4b37dbb03c07bec6126f0ecc28dad403c12ffe2e5a2d751ab7" 152 | url: "https://pub.dev" 153 | source: hosted 154 | version: "7.2.0" 155 | http: 156 | dependency: transitive 157 | description: 158 | name: http 159 | sha256: "6aa2946395183537c8b880962d935877325d6a09a2867c3970c05c0fed6ac482" 160 | url: "https://pub.dev" 161 | source: hosted 162 | version: "0.13.5" 163 | http_parser: 164 | dependency: transitive 165 | description: 166 | name: http_parser 167 | sha256: "2aa08ce0341cc9b354a498388e30986515406668dbcc4f7c950c3e715496693b" 168 | url: "https://pub.dev" 169 | source: hosted 170 | version: "4.0.2" 171 | js: 172 | dependency: transitive 173 | description: 174 | name: js 175 | sha256: "5528c2f391ededb7775ec1daa69e65a2d61276f7552de2b5f7b8d34ee9fd4ab7" 176 | url: "https://pub.dev" 177 | source: hosted 178 | version: "0.6.5" 179 | just_audio: 180 | dependency: "direct main" 181 | description: 182 | name: just_audio 183 | sha256: "7a5057a4d05c8f88ee968cec6fdfe1015577d5184e591d5ac15ab16d8f5ecb17" 184 | url: "https://pub.dev" 185 | source: hosted 186 | version: "0.9.31" 187 | just_audio_platform_interface: 188 | dependency: transitive 189 | description: 190 | name: just_audio_platform_interface 191 | sha256: eff112d5138bea3ba544b6338b1e0537a32b5e1425e4d0dc38f732771cda7c84 192 | url: "https://pub.dev" 193 | source: hosted 194 | version: "4.2.0" 195 | just_audio_web: 196 | dependency: transitive 197 | description: 198 | name: just_audio_web 199 | sha256: "89d8db6f19f3821bb6bf908c4bfb846079afb2ab575b783d781a6bf119e3abaf" 200 | url: "https://pub.dev" 201 | source: hosted 202 | version: "0.4.7" 203 | leak_tracker: 204 | dependency: transitive 205 | description: 206 | name: leak_tracker 207 | sha256: "6bb818ecbdffe216e81182c2f0714a2e62b593f4a4f13098713ff1685dfb6ab0" 208 | url: "https://pub.dev" 209 | source: hosted 210 | version: "10.0.9" 211 | leak_tracker_flutter_testing: 212 | dependency: transitive 213 | description: 214 | name: leak_tracker_flutter_testing 215 | sha256: f8b613e7e6a13ec79cfdc0e97638fddb3ab848452eff057653abd3edba760573 216 | url: "https://pub.dev" 217 | source: hosted 218 | version: "3.0.9" 219 | leak_tracker_testing: 220 | dependency: transitive 221 | description: 222 | name: leak_tracker_testing 223 | sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3" 224 | url: "https://pub.dev" 225 | source: hosted 226 | version: "3.0.1" 227 | lints: 228 | dependency: transitive 229 | description: 230 | name: lints 231 | sha256: "5e4a9cd06d447758280a8ac2405101e0e2094d2a1dbdd3756aec3fe7775ba593" 232 | url: "https://pub.dev" 233 | source: hosted 234 | version: "2.0.1" 235 | matcher: 236 | dependency: transitive 237 | description: 238 | name: matcher 239 | sha256: dc58c723c3c24bf8d3e2d3ad3f2f9d7bd9cf43ec6feaa64181775e60190153f2 240 | url: "https://pub.dev" 241 | source: hosted 242 | version: "0.12.17" 243 | material_color_utilities: 244 | dependency: transitive 245 | description: 246 | name: material_color_utilities 247 | sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec 248 | url: "https://pub.dev" 249 | source: hosted 250 | version: "0.11.1" 251 | meta: 252 | dependency: transitive 253 | description: 254 | name: meta 255 | sha256: e3641ec5d63ebf0d9b41bd43201a66e3fc79a65db5f61fc181f04cd27aab950c 256 | url: "https://pub.dev" 257 | source: hosted 258 | version: "1.16.0" 259 | path: 260 | dependency: transitive 261 | description: 262 | name: path 263 | sha256: "75cca69d1490965be98c73ceaea117e8a04dd21217b37b292c9ddbec0d955bc5" 264 | url: "https://pub.dev" 265 | source: hosted 266 | version: "1.9.1" 267 | path_provider: 268 | dependency: transitive 269 | description: 270 | name: path_provider 271 | sha256: dcea5feb97d8abf90cab9e9030b497fb7c3cbf26b7a1fe9e3ef7dcb0a1ddec95 272 | url: "https://pub.dev" 273 | source: hosted 274 | version: "2.0.12" 275 | path_provider_android: 276 | dependency: transitive 277 | description: 278 | name: path_provider_android 279 | sha256: a776c088d671b27f6e3aa8881d64b87b3e80201c64e8869b811325de7a76c15e 280 | url: "https://pub.dev" 281 | source: hosted 282 | version: "2.0.22" 283 | path_provider_foundation: 284 | dependency: transitive 285 | description: 286 | name: path_provider_foundation 287 | sha256: "62a68e7e1c6c459f9289859e2fae58290c981ce21d1697faf54910fe1faa4c74" 288 | url: "https://pub.dev" 289 | source: hosted 290 | version: "2.1.1" 291 | path_provider_linux: 292 | dependency: transitive 293 | description: 294 | name: path_provider_linux 295 | sha256: "2e32f1640f07caef0d3cb993680f181c79e54a3827b997d5ee221490d131fbd9" 296 | url: "https://pub.dev" 297 | source: hosted 298 | version: "2.1.8" 299 | path_provider_platform_interface: 300 | dependency: transitive 301 | description: 302 | name: path_provider_platform_interface 303 | sha256: f0abc8ebd7253741f05488b4813d936b4d07c6bae3e86148a09e342ee4b08e76 304 | url: "https://pub.dev" 305 | source: hosted 306 | version: "2.0.5" 307 | path_provider_windows: 308 | dependency: transitive 309 | description: 310 | name: path_provider_windows 311 | sha256: bcabbe399d4042b8ee687e17548d5d3f527255253b4a639f5f8d2094a9c2b45c 312 | url: "https://pub.dev" 313 | source: hosted 314 | version: "2.1.3" 315 | pedantic: 316 | dependency: transitive 317 | description: 318 | name: pedantic 319 | sha256: "67fc27ed9639506c856c840ccce7594d0bdcd91bc8d53d6e52359449a1d50602" 320 | url: "https://pub.dev" 321 | source: hosted 322 | version: "1.11.1" 323 | platform: 324 | dependency: transitive 325 | description: 326 | name: platform 327 | sha256: "4a451831508d7d6ca779f7ac6e212b4023dd5a7d08a27a63da33756410e32b76" 328 | url: "https://pub.dev" 329 | source: hosted 330 | version: "3.1.0" 331 | plugin_platform_interface: 332 | dependency: transitive 333 | description: 334 | name: plugin_platform_interface 335 | sha256: dbf0f707c78beedc9200146ad3cb0ab4d5da13c246336987be6940f026500d3a 336 | url: "https://pub.dev" 337 | source: hosted 338 | version: "2.1.3" 339 | process: 340 | dependency: transitive 341 | description: 342 | name: process 343 | sha256: "53fd8db9cec1d37b0574e12f07520d582019cb6c44abf5479a01505099a34a09" 344 | url: "https://pub.dev" 345 | source: hosted 346 | version: "4.2.4" 347 | rxdart: 348 | dependency: transitive 349 | description: 350 | name: rxdart 351 | sha256: "0c7c0cedd93788d996e33041ffecda924cc54389199cde4e6a34b440f50044cb" 352 | url: "https://pub.dev" 353 | source: hosted 354 | version: "0.27.7" 355 | sky_engine: 356 | dependency: transitive 357 | description: flutter 358 | source: sdk 359 | version: "0.0.0" 360 | source_span: 361 | dependency: transitive 362 | description: 363 | name: source_span 364 | sha256: "254ee5351d6cb365c859e20ee823c3bb479bf4a293c22d17a9f1bf144ce86f7c" 365 | url: "https://pub.dev" 366 | source: hosted 367 | version: "1.10.1" 368 | sqflite: 369 | dependency: transitive 370 | description: 371 | name: sqflite 372 | sha256: "78324387dc81df14f78df06019175a86a2ee0437624166c382e145d0a7fd9a4f" 373 | url: "https://pub.dev" 374 | source: hosted 375 | version: "2.2.4+1" 376 | sqflite_common: 377 | dependency: transitive 378 | description: 379 | name: sqflite_common 380 | sha256: bfd6973aaeeb93475bc0d875ac9aefddf7965ef22ce09790eb963992ffc5183f 381 | url: "https://pub.dev" 382 | source: hosted 383 | version: "2.4.2+2" 384 | stack_trace: 385 | dependency: transitive 386 | description: 387 | name: stack_trace 388 | sha256: "8b27215b45d22309b5cddda1aa2b19bdfec9df0e765f2de506401c071d38d1b1" 389 | url: "https://pub.dev" 390 | source: hosted 391 | version: "1.12.1" 392 | stream_channel: 393 | dependency: transitive 394 | description: 395 | name: stream_channel 396 | sha256: "969e04c80b8bcdf826f8f16579c7b14d780458bd97f56d107d3950fdbeef059d" 397 | url: "https://pub.dev" 398 | source: hosted 399 | version: "2.1.4" 400 | string_scanner: 401 | dependency: transitive 402 | description: 403 | name: string_scanner 404 | sha256: "921cd31725b72fe181906c6a94d987c78e3b98c2e205b397ea399d4054872b43" 405 | url: "https://pub.dev" 406 | source: hosted 407 | version: "1.4.1" 408 | synchronized: 409 | dependency: transitive 410 | description: 411 | name: synchronized 412 | sha256: "33b31b6beb98100bf9add464a36a8dd03eb10c7a8cf15aeec535e9b054aaf04b" 413 | url: "https://pub.dev" 414 | source: hosted 415 | version: "3.0.1" 416 | term_glyph: 417 | dependency: transitive 418 | description: 419 | name: term_glyph 420 | sha256: "7f554798625ea768a7518313e58f83891c7f5024f88e46e7182a4558850a4b8e" 421 | url: "https://pub.dev" 422 | source: hosted 423 | version: "1.2.2" 424 | test_api: 425 | dependency: transitive 426 | description: 427 | name: test_api 428 | sha256: fb31f383e2ee25fbbfe06b40fe21e1e458d14080e3c67e7ba0acfde4df4e0bbd 429 | url: "https://pub.dev" 430 | source: hosted 431 | version: "0.7.4" 432 | typed_data: 433 | dependency: transitive 434 | description: 435 | name: typed_data 436 | sha256: "26f87ade979c47a150c9eaab93ccd2bebe70a27dc0b4b29517f2904f04eb11a5" 437 | url: "https://pub.dev" 438 | source: hosted 439 | version: "1.3.1" 440 | uuid: 441 | dependency: transitive 442 | description: 443 | name: uuid 444 | sha256: "648e103079f7c64a36dc7d39369cabb358d377078a051d6ae2ad3aa539519313" 445 | url: "https://pub.dev" 446 | source: hosted 447 | version: "3.0.7" 448 | vector_math: 449 | dependency: transitive 450 | description: 451 | name: vector_math 452 | sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" 453 | url: "https://pub.dev" 454 | source: hosted 455 | version: "2.1.4" 456 | vm_service: 457 | dependency: transitive 458 | description: 459 | name: vm_service 460 | sha256: ddfa8d30d89985b96407efce8acbdd124701f96741f2d981ca860662f1c0dc02 461 | url: "https://pub.dev" 462 | source: hosted 463 | version: "15.0.0" 464 | win32: 465 | dependency: transitive 466 | description: 467 | name: win32 468 | sha256: c9ebe7ee4ab0c2194e65d3a07d8c54c5d00bb001b76081c4a04cdb8448b59e46 469 | url: "https://pub.dev" 470 | source: hosted 471 | version: "3.1.3" 472 | xdg_directories: 473 | dependency: transitive 474 | description: 475 | name: xdg_directories 476 | sha256: ee1505df1426458f7f60aac270645098d318a8b4766d85fde75f76f2e21807d1 477 | url: "https://pub.dev" 478 | source: hosted 479 | version: "1.0.0" 480 | sdks: 481 | dart: ">=3.7.0-0 <4.0.0" 482 | flutter: ">=3.18.0-18.0.pre.54" 483 | --------------------------------------------------------------------------------