Skip to content

Commit

Permalink
Update permissions & switch to another audio query library
Browse files Browse the repository at this point in the history
  • Loading branch information
Artx-II committed Mar 21, 2024
1 parent bf2cd00 commit 1cf39d1
Show file tree
Hide file tree
Showing 7 changed files with 53 additions and 66 deletions.
5 changes: 5 additions & 0 deletions android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,12 @@
<uses-permission
android:name="android.permission.WRITE_EXTERNAL_STORAGE"
android:maxSdkVersion="30" />
<!-- Android 12 or below -->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<!-- Android 13 or greater -->
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES"/>
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO"/>
<uses-permission android:name="android.permission.READ_MEDIA_AUDIO"/>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.WAKE_LOCK"/>
Expand Down
4 changes: 4 additions & 0 deletions lib/internal/global.dart
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ Future<void> initGlobals() async {
}
songThumbnailPath = (await getApplicationDocumentsDirectory());
deviceInfo = await DeviceInfoPlugin().androidInfo;
androidSdk = deviceInfo.version.sdkInt!;
audioHandler = await AudioService.init(
builder: () => StAudioHandler(),
config: const AudioServiceConfig(
Expand All @@ -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;

Expand Down
81 changes: 34 additions & 47 deletions lib/internal/media_utils.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -72,28 +72,18 @@ class MediaUtils {
return null;
}

static Future<void> fetchDeviceSongs(Function(SongItem) onUpdateTrigger) async {
// New songs found on device
List<SongInfo> userSongs = await FlutterAudioQuery()
.getSongs(sortType: SongSortType.DISPLAY_NAME);
// Cached Songs
List<MediaItem> 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<SongItem> 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<List<SongItem>> 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<SongModel> userSongs = await OnAudioQuery().querySongs(
sortType: SongSortType.DISPLAY_NAME,
ignoreCase: true,
);
final songs = MediaUtils.convertToSongItem(userSongs);
CacheUtils.cacheSongs = songs;
return songs;
}

static MediaItem fromMap(Map<String, dynamic> map) {
Expand Down Expand Up @@ -144,31 +134,28 @@ class MediaUtils {
}

// Convert any List<SongFile> to a List<MediaItem>
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<SongItem> convertToSongItem(List<SongModel> songList) {
List<SongItem> 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<SongItem> downloadToSongItem(DownloadInfo info, String path) async {
Expand Down
15 changes: 4 additions & 11 deletions lib/providers/media_provider.dart
Original file line number Diff line number Diff line change
Expand Up @@ -78,21 +78,14 @@ class MediaProvider extends ChangeNotifier {

// Fetch Songs for this Provider
Future<void> 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();
}
}
Expand Down
5 changes: 3 additions & 2 deletions lib/screens/intro/pages/permissions_page.dart
Original file line number Diff line number Diff line change
@@ -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';

Expand All @@ -27,7 +28,7 @@ class _PermissionIntroPageState extends State<PermissionIntroPage> {

@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(() {
Expand All @@ -47,7 +48,7 @@ class _PermissionIntroPageState extends State<PermissionIntroPage> {
}

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(() {
Expand Down
4 changes: 2 additions & 2 deletions lib/ui/components/song_thumbnail.dart
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,8 @@ class _SongThumbnailState extends State<SongThumbnail> {
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) {
Expand Down
5 changes: 1 addition & 4 deletions pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit 1cf39d1

Please sign in to comment.