From 1cf39d14f66e9477ef730f7a8d032531c6959d8e Mon Sep 17 00:00:00 2001 From: Jesus Acosta Date: Thu, 21 Mar 2024 19:07:12 -0400 Subject: [PATCH] Update permissions & switch to another audio query library --- android/app/src/main/AndroidManifest.xml | 5 ++ lib/internal/global.dart | 4 + lib/internal/media_utils.dart | 81 ++++++++----------- lib/providers/media_provider.dart | 15 +--- lib/screens/intro/pages/permissions_page.dart | 5 +- lib/ui/components/song_thumbnail.dart | 4 +- pubspec.yaml | 5 +- 7 files changed, 53 insertions(+), 66 deletions(-) diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index ef5ba112..177bbdf5 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -4,7 +4,12 @@ + + + + + diff --git a/lib/internal/global.dart b/lib/internal/global.dart index 3c39f00a..6f51b8d6 100644 --- a/lib/internal/global.dart +++ b/lib/internal/global.dart @@ -23,6 +23,7 @@ Future initGlobals() async { } songThumbnailPath = (await getApplicationDocumentsDirectory()); deviceInfo = await DeviceInfoPlugin().androidInfo; + androidSdk = deviceInfo.version.sdkInt!; audioHandler = await AudioService.init( builder: () => StAudioHandler(), config: const AudioServiceConfig( @@ -44,6 +45,9 @@ Color accentColor = const Color.fromARGB(255, 229, 12, 73); // Platform Details late AndroidDeviceInfo deviceInfo; +// Device SDK +late int androidSdk; + // Shared Preferences for user settings and app caching and stuff late SharedPreferences sharedPreferences; diff --git a/lib/internal/media_utils.dart b/lib/internal/media_utils.dart index d438aa06..7b349ab7 100644 --- a/lib/internal/media_utils.dart +++ b/lib/internal/media_utils.dart @@ -7,9 +7,9 @@ import 'package:audio_tagger/audio_tagger.dart' as tagger; import 'package:audio_tagger/audio_tags.dart' as tags; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; -import 'package:flutter_audio_query/flutter_audio_query.dart'; import 'package:http/http.dart'; import 'package:newpipeextractor_dart/newpipeextractor_dart.dart'; +import 'package:on_audio_query/on_audio_query.dart'; import 'package:palette_generator/palette_generator.dart'; import 'package:path_provider/path_provider.dart'; import 'package:songtube/internal/artwork_manager.dart'; @@ -72,28 +72,18 @@ class MediaUtils { return null; } - static Future fetchDeviceSongs(Function(SongItem) onUpdateTrigger) async { - // New songs found on device - List userSongs = await FlutterAudioQuery() - .getSongs(sortType: SongSortType.DISPLAY_NAME); - // Cached Songs - List cachedSongs = fetchCachedSongsAsMediaItems(); - // Filter out non needed songs from this process - // ignore: avoid_function_literals_in_foreach_calls - cachedSongs.forEach((item) { - if (userSongs.any((element) => element.filePath == item.id)) { - userSongs.removeWhere((element) => element.filePath == item.id); - } - }); - final List songs = []; - for (final element in userSongs) { - final song = MediaUtils.convertToSongItem(element); - if (song != null) { - songs.add(song); - onUpdateTrigger(song); - } - } - CacheUtils.cacheSongs = fetchCachedSongsAsSongItems()..addAll(songs); + static Future> fetchDeviceSongs() async { + // Scan media stores + await OnAudioQuery().scanMedia('/storage/emulated/0/Music'); + await OnAudioQuery().scanMedia('/storage/emulated/0/Download'); + // Get all songs from device storage + List userSongs = await OnAudioQuery().querySongs( + sortType: SongSortType.DISPLAY_NAME, + ignoreCase: true, + ); + final songs = MediaUtils.convertToSongItem(userSongs); + CacheUtils.cacheSongs = songs; + return songs; } static MediaItem fromMap(Map map) { @@ -144,31 +134,28 @@ class MediaUtils { } // Convert any List to a List - static SongItem? convertToSongItem(SongInfo element) { - Duration duration = Duration( - milliseconds: element.duration != null - ? int.parse(element.duration!) - : 0, - ); - FileStat? stats; - try { - stats = FileStat.statSync(element.filePath!); - } catch (e) { - if (kDebugMode) { - print(e.toString()); - } + static List convertToSongItem(List songList) { + List list = []; + for (var element in songList) { + try { + Duration duration = Duration(milliseconds: element.duration!); + FileStat stats = FileStat.statSync(element.data); + list.add( + SongItem( + id: element.data, + modelId: element.displayName, + title: element.title, + album: element.album, + artist: element.artist, + duration: duration, + lastModified: stats.changed, + artworkPath: artworkFile(element.data), + thumbnailPath: thumbnailFile(element.data), + ) + ); + } catch (_) {} } - return SongItem( - id: element.filePath!, - modelId: element.id, - title: element.title!, - album: element.album, - artist: element.artist, - artworkPath: artworkFile(element.filePath!), - thumbnailPath: thumbnailFile(element.filePath!), - duration: duration, - lastModified: stats?.changed ?? DateTime.now(), - ); + return list; } static Future downloadToSongItem(DownloadInfo info, String path) async { diff --git a/lib/providers/media_provider.dart b/lib/providers/media_provider.dart index 96224822..1656c43d 100644 --- a/lib/providers/media_provider.dart +++ b/lib/providers/media_provider.dart @@ -78,21 +78,14 @@ class MediaProvider extends ChangeNotifier { // Fetch Songs for this Provider Future fetchMedia() async { - permissionStatus = await Permission.storage.status; + permissionStatus = await (androidSdk >= 33 ? Permission.audio.status : Permission.storage.status); if (permissionStatus == PermissionStatus.granted) { - if (kDebugMode) { - print('Fetching device Media...'); - } + print('Fetching device Media...'); fetchMediaRunning = true; notifyListeners(); - Timer timer = Timer.periodic(const Duration(seconds: 5), (_) { - notifyListeners(); - }); - await MediaUtils.fetchDeviceSongs((newSong) { - songs.add(newSong); - }); + final items = await MediaUtils.fetchDeviceSongs(); + songs = items; fetchMediaRunning = false; - timer.cancel(); notifyListeners(); } } diff --git a/lib/screens/intro/pages/permissions_page.dart b/lib/screens/intro/pages/permissions_page.dart index 563aa244..f3065c84 100644 --- a/lib/screens/intro/pages/permissions_page.dart +++ b/lib/screens/intro/pages/permissions_page.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; import 'package:google_fonts/google_fonts.dart'; import 'package:permission_handler/permission_handler.dart'; +import 'package:songtube/internal/global.dart'; import 'package:songtube/languages/languages.dart'; import 'package:songtube/ui/animations/show_up.dart'; @@ -27,7 +28,7 @@ class _PermissionIntroPageState extends State { @override void initState() { - Permission.storage.status.then((status) { + (androidSdk >= 33 ? Permission.audio.status : Permission.storage.status).then((status) { if (status != PermissionStatus.granted) { if (mounted) { setState(() { @@ -47,7 +48,7 @@ class _PermissionIntroPageState extends State { } void requestPermissions() async { - final status = await Permission.storage.request(); + final status = await (androidSdk >= 33 ? Permission.audio.request() : Permission.storage.request()); if (status == PermissionStatus.granted) { if (mounted) { setState(() { diff --git a/lib/ui/components/song_thumbnail.dart b/lib/ui/components/song_thumbnail.dart index 9ef14071..792d42aa 100644 --- a/lib/ui/components/song_thumbnail.dart +++ b/lib/ui/components/song_thumbnail.dart @@ -50,8 +50,8 @@ class _SongThumbnailState extends State { borderRadius: widget.borderRadius ?? BorderRadius.circular(15), child: ImageFade( fadeDuration: const Duration(milliseconds: 300), - image: widget.artwork != null ? Image.file(widget.artwork!, cacheHeight: 150, cacheWidth: 150).image - : artwork != null ? Image.file(artwork!, cacheHeight: 150, cacheWidth: 150).image : Image.memory(kTransparentImage).image, + image: widget.artwork != null ? Image.file(widget.artwork!).image + : artwork != null ? Image.file(artwork!).image : Image.memory(kTransparentImage).image, placeholder: Image.memory(kTransparentImage), fit: BoxFit.cover, errorBuilder: (context, child, exception) { diff --git a/pubspec.yaml b/pubspec.yaml index 206fc3ac..ced9e8d5 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -78,10 +78,7 @@ dependencies: ref: master # Audio Query, Extract Music from device - flutter_audio_query: - git: - url: https://github.com/harshmandan/flutter_audio_query - ref: master + on_audio_query: ^2.9.0 # Shared Preferences, Save user settings and cache things shared_preferences: ^2.0.11