Alle Sound-Dateien / -Informationen aus sdcard und external-sdcard erhalten

  • Antworten:8
  • Bentwortet
Aaron B.
  • Forum-Beiträge: 206

28.07.2013, 13:22:17 via App

hallo community.

Ich arbeite gerade an einem Music-Player und möchte für diesen alle Sound-Dateien aus der Sd-Card und externen Sd-Card heraussuchen und für diese folgende Informationen erhalten:
-Titel
-Interpret
-Album
-Länge
-Bild

Dazu nutze ich momentan den MediaMetadataRetreiver. Dieser funktioniert jedoch nur bei mp3-Dateien und findet nur bei sehr wenigen Titeln Informationen.

Mein Problem ist, dass das Finden der Dateien und das Heraussuchen derer Unformationen ca. 40 Sekunden dauert, was viel zu lang ist.
Außerdem möchte ich auch andere Formate neben mp3 nutzen können.

Die Daten sollen wenn möglich in eine ArrayList <SoundItem> geladen werden. SoundItem ist eine Custom-Klasse, die Bild (Cover), Titel, Artist, Album, Länge und Pfad beinhaltet.

Mit dieser Klasse lade ich momentan die Informationen:
1package de.mymusic.classes;
2
3import android.content.*;
4import android.graphics.*;
5import android.media.*;
6import android.os.*;
7import android.widget.*;
8import de.mymusic.adapters.*;
9import java.io.*;
10import java.util.*;
11
12public class MusicManager
13{
14
15 public static ArrayList<String> getAllSoundsInExternalStorage() {
16 ArrayList<String> result = getAllSoundsInFolder(new File(Environment.getExternalStorageDirectory() + File.separator).getParent());
17
18 return result;
19 }
20
21 public static ArrayList<String> getAllSoundsInFolder(String path) {
22 ArrayList<String> result = new ArrayList<String>();
23
24 for(File f : new File(path).listFiles()) {
25 try {
26 if(f.isDirectory()) {
27 for(String f2 : getAllSoundsInFolder(f.getPath())) {
28 result.add(f2);
29 }
30 } else if(f.getName().endsWith(".mp3")) {
31 result.add(f.getPath());
32 }/* else if(f.getName().endsWith(".m4a")) {
33 result.add(f.getPath());
34 }*/
35 } catch(Exception e) {
36
37 }
38 }
39
40 return result;
41 }
42
43 public static ArrayList<SoundItem> buildTitleList(Context c, ArrayList<String> soundFiles) {
44 ArrayList<SoundItem> result = new ArrayList<SoundItem>();
45
46 for(String f : soundFiles) {
47 try {
48 MediaMetadataRetriever rec = new MediaMetadataRetriever();
49 rec.setDataSource(f);
50
51 Float time = Float.valueOf(rec.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION));
52 time = time / 1000 / 60;
53
54 SoundItem adding = new SoundItem((rec.extractMetadata(MediaMetadataRetriever.METADATA_KEY_TITLE) == null ? new File(f).getName().replace(".mp3", "").replace(".m4a", "") : rec.extractMetadata(MediaMetadataRetriever.METADATA_KEY_TITLE)), rec.extractMetadata(MediaMetadataRetriever.METADATA_KEY_ARTIST), rec.extractMetadata(MediaMetadataRetriever.METADATA_KEY_ALBUM), time, f);
55 try {
56 adding.setCover(BitmapFactory.decodeByteArray(rec.getEmbeddedPicture(), 0, rec.getEmbeddedPicture().length));
57 } catch(Exception e) {
58
59 }
60 result.add(adding);
61 } catch(Exception e) {
62
63 }
64 }
65
66 return result;
67 }
68
69}

Gibt es einen schnelleren und zuverlässigeren Weg, Musik-Daten zu laden?

Danke im Voraus für Antworten.

Antworten
JekApps
  • Forum-Beiträge: 19

29.07.2013, 20:28:38 via Website

Schau dir mal das Prinzip der ContentResolver an.
Du musst nicht den Speicher nach Dateien durchsuchen, Android bietet dafür eine SQL ähnliche Schnittstelle:

Hole dir ein Cursor Objekt in dem du über den contentResolver nach AudioDateien suchst:

1Cursor musicCursor = context.getContentResolver().query(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, new String[] {
2
3 BaseColumns._ID,
4 AudioColumns.TITLE,
5 AudioColumns.ARTIST,
6 AudioColumns.ALBUM,
7 AudioColumns.DURATION,
8 AudioColumns.DATA,
9 AudioColumns.ALBUM_ID
10
11 }, AudioColumns.IS_MUSIC + "=1" , null, MediaStore.Audio.Media.DEFAULT_SORT_ORDER);

Der Cursor enthält jetzt Zeile für Zeile Einträge, die deiner Suche entsprechen. Jeder Eintrag besitzt die 7 Felder des String Arrays.
Deine ArrayList kannst du dann folgendermaßen mit dem Inhalt des Cursors füllen:

1public static List<SoundItem> loadSongList(Cursor mCursor) {
2 final ArrayList<SoundItem> mSongList = new ArrayList<SoundItem>();
3 // Gather the data
4 if (mCursor != null && mCursor.moveToFirst()) {
5 do {
6 // Copy the song Id
7 final Long id = mCursor.getLong(0);
8 if (id == null) {
9 continue;
10 }
11 // Copy the song name
12 final String songName = mCursor.getString(1);
13
14 // Copy the artist name
15 final String artist = mCursor.getString(2);
16
17 // Copy the album name
18 final String album = mCursor.getString(3);
19
20 // Copy the song duration millis
21 final Long duration = mCursor.getLong(4);
22
23 // Copy the song path
24 final String path = mCursor.getString(5);
25
26 // Copy the album id
27 final Long albumID = mCursor.getLong(6);
28
29 // Create your SoundItem object
30 final SoundItem song = new SoundItem(id, albumID, songName, artist, album, duration, path);
31
32 // Add everything up
33 mSongList.add(song);
34 } while (mCursor.moveToNext());
35 }
36 // Close the cursor
37 if (mCursor != null) {
38 mCursor.close();
39 mCursor = null;
40 }
41 return mSongList;
42 }

Sollte klappen... :unsure:

— geändert am 29.07.2013, 23:04:31

Antworten
Aaron B.
  • Forum-Beiträge: 206

29.07.2013, 21:59:08 via App

ok danke :)

Kann man mithilfe dieses Prozesses auch das Bild des Titels (Cover) laden?

LG

Antworten
JekApps
  • Forum-Beiträge: 19

29.07.2013, 22:15:01 via Website

Aus Performance und Speicher gründen solltest du die Bilder nicht sofort auslesen, wenn du nur schaust, welche Lieder überhaupt da sind.

Am besten lädst du ein Cover erst in den Speicher, wenn du es auch wirklich darstellen willst.
Dazu kann ich dir diese Seite empfehlen. Je nachdem wie fit du in Java bist, kann du da vielleicht ein Menge lernen.
developer.android.com/training/displaying-bitmaps/index.html

Wenn es dir wirklich nur darum geht das Album Cover zu laden, nimmst du die AlbumID aus dem obigen Beispiel und lädst dafür das Cover:
1Uri uri = ContentUris.withAppendedId(Uri.parse("content://media/external/audio/albumart"), soundItem.albumId);
2 ParcelFileDescriptor pfd = getContentResolver().openFileDescriptor(uri, "r");
3 if (pfd != null) {
4 FileDescriptor fd = pfd.getFileDescriptor();
5 Bitmap cover = BitmapFactory.decodeFileDescriptor(fd);
6 }

Antworten
Aaron B.
  • Forum-Beiträge: 206

29.07.2013, 22:18:36 via App

Ok danke. Das hat mir sehr geholfen.

LG

Antworten
JekApps
  • Forum-Beiträge: 19

29.07.2013, 22:27:20 via Website

Gerne und viel Erfolg... :D

Antworten
Aaron B.
  • Forum-Beiträge: 206

30.07.2013, 07:16:37 via App

Eine Frage noch:

Wie erhält man das Genre eines Titels? Wenn ich einfach Genres.NAME hinzufüge, kommen einfach nur die möglichen Genres, sie sind aber nicht zu den Songs zugeordnet.

Wie kann man die einfach laden?
LG

Antworten
JekApps
  • Forum-Beiträge: 19

30.07.2013, 10:02:25 via Website

Aaron B.
Eine Frage noch:

Wie erhält man das Genre eines Titels? Wenn ich einfach Genres.NAME hinzufüge, kommen einfach nur die möglichen Genres, sie sind aber nicht zu den Songs zugeordnet.

Wie kann man die einfach laden?
LG

AudioColumns kennt kein Genre, daher geht es leider nicht so einfach.
Du müsstest dann entweder den Umweg über deinen MediaMetadataRetriever gehen (den Pfad der Dateien hast du ja jetzt), oder wenn es dir eher darum geht alle Lieder eines Genres zu suchen, holst du dir einen Genre-Cursor, daraus baust du eine Liste aller Genres und holst dir dann nochmal die Lieder der einzelnen Genres:

1context.getContentResolver().query(MediaStore.Audio.Genres.EXTERNAL_CONTENT_URI,
2 new String[] {
3 /* 0 */
4 BaseColumns._ID,
5 /* 1 */
6 GenresColumns.NAME
7 }, null , null, MediaStore.Audio.Genres.DEFAULT_SORT_ORDER)

1context.getContentResolver().query(
2 MediaStore.Audio.Genres.Members.getContentUri("external", genreId), new String[] {
3 /* 0 */
4 MediaStore.Audio.Genres.Members._ID,
5 /* 1 */
6 MediaStore.Audio.Genres.Members.TITLE,
7 /* 2 */
8 MediaStore.Audio.Genres.Members.ARTIST,
9 /* 3 */
10 MediaStore.Audio.Genres.Members.ALBUM,
11 /* 4 */
12 AudioColumns.DURATION,
13 /* 5 */
14 AudioColumns.DATA
15 }, null , null, MediaStore.Audio.Genres.Members.DEFAULT_SORT_ORDER)

Antworten
Aaron B.
  • Forum-Beiträge: 206

30.07.2013, 21:22:13 via App

Ok alles klar :)

Antworten