2016-10-27 21 views
0

私のアプリは、曲のタイトル、アーティスト、アルバム、ジャンルなどを含む、デバイスのすべての音楽をリストする必要があります。Androidは入れ子になっていないすべての音楽やジャンルを取得します。 (MediaStore.Audio ...)

私は曲のジャンルを取得するの知っている方法は、このような歌のIDを持つ別のCursorを作成することです:

Uri uri = MediaStore.Audio.Genres.getContentUriForAudioId("external", (int) id); 
Cursor genresCursor = mContentResolver.query(uri, genresProjection, null, null, null); 

しかし、私はすべての曲が一覧表示されますCursor以内にこれを行う場合は、ロード時間が大幅に増加します。 (私の電話の曲の量は、0.5秒から約3秒まで)。

これは私のコードです:

// If you change this to `false`, it will load a lot quicker. 
private static final boolean LOAD_GENRE = true; 

private static String[] mediaProjection = { 
     MediaStore.Audio.AudioColumns._ID, 
     MediaStore.Audio.AudioColumns.DATA, 
     MediaStore.Audio.AudioColumns.TITLE, 
     MediaStore.Audio.AudioColumns.ARTIST, 
     MediaStore.Audio.AudioColumns.ALBUM, 
     MediaStore.Audio.AudioColumns.ALBUM_ID, 
     MediaStore.Audio.AudioColumns.DURATION 
}; 
private static String[] genresProjection = { 
     MediaStore.Audio.GenresColumns.NAME 
}; 

private ArrayList<MediaMetadataCompat> getAllMusic() { 
    Uri uriAudio = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI; 
    Cursor cursor = mContentResolver.query(uriAudio, mediaProjection, null, null, null); 

    if (cursor != null) { 
     int count = cursor.getCount(); 

     if (count > 0) { 
      ArrayList<MediaMetadataCompat> audioFiles = new ArrayList<>(); 

      while (cursor.moveToNext()) { 
       MediaMetadataCompat song = buildFromCursor(cursor); 
       if (song != null) { 
        audioFiles.add(song); 
       } 
      } 
      cursor.close(); 

      return audioFiles; 
     } 
    } 
    return new ArrayList<>(); 
} 

private MediaMetadataCompat buildFromCursor(Cursor cursor, boolean loadGenre) { 
    long id = cursor.getLong(cursor.getColumnIndex(MediaStore.Audio.AudioColumns._ID)); 
    String data = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.AudioColumns.DATA)); 
    String title = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.AudioColumns.TITLE)); 
    String artist = ...; 
    String album = ...; 
    long albumId = ...; 
    long duration = ...; 

    //File file = new File(data); 
    //if (!file.exists()) { 
    // Log.e(TAG, "Skipping song because it does not exist: " + title); 
    // return null; 
    //} 


    Uri uri = MediaStore.Audio.Genres.getContentUriForAudioId("external", (int) id); 

    if (LOAD_GENRE) { 
     String genre = null; 
     Cursor genresCursor = mContentResolver.query(uri, genresProjection, null, null, null); 
     if (genresCursor != null && genresCursor.moveToFirst()) { 
      int genreColumnIndex = genresCursor.getColumnIndex(MediaStore.Audio.GenresColumns.NAME); 
      do { 
       String genreColumn = genresCursor.getString(genreColumnIndex); 
       if (genre == null) { 
        genre = genreColumn; 
       } else { 
        genre += " " + genre; 
       } 
      } while (genresCursor.moveToNext()); 
      genresCursor.close(); 
     } 
    } 

    // Workaround to avoid ANOTHER cursor to load album art. 
    Uri albumArtUri = ContentUris.withAppendedId(Uri.parse("content://media/external/audio/albumart"), albumId); 

    MediaMetadataCompat.Builder builder = new MediaMetadataCompat.Builder() 
      .putString(MediaMetadataCompat.METADATA_KEY_MEDIA_ID, String.valueOf(id)) 
      .put... 
      .put...; 


    return builder.build(); 
} 

は、私は、ネストされたCursorを避けるために、このコードを向上させることができます方法はありますか?私はすでにアルバムアートの回避策を見つけました。それらを何らかの方法で組み合わせることは可能ですか?これにはCursorJoinerが使えますか?問題は、ジャンルを取得するには、メディアIDが必要です。ありがとう。

答えて

0

SOユーザーSuhaib Roomeyさんが最近投稿した (get genre_id and audio_id from audio_genres_map from mediastore)です。おそらくそれはあなたが達成しようとしているものに役立ちます

String[] genresProjection = { 
     Audio.Genres.Members.AUDIO_ID, 
     Audio.Genres.Members.GENRE_ID 
}; 
     context.getContentResolver().query(Uri.parse("content://media/external/audio/genres/all/members"), genresProjection, null, null, null); 
関連する問題