--------------------------
안녕하세요.
안드로이드 기본 Music player의 구조 공부하다가 알게 된것 몇가지 올립니다.
강좌라고 하기는 뭐하지만, 그냥 간단한 정보정도로 보세요 ^^
안드로이드의 Music Player는 음악의 정보를 DB에서 가져 옵니다.
애플것이나 MS 것도 이런 방식을 취하고 있습니다.
안드로이드에서는 Dev Tools 아래의 Media Scanner 를 실행하면,
저장장치 (sdcard등)의 Media 파일 (음악, 이미지, 동영상) 의 정보를
DB에 기록하여 줍니다.
Music Player를 이렇게 생성된 DB의 정보를 가지고 재생하게 됩니다.
생성된 DB의 구조는
http://www.androidside.com/bbs/board.php?bo_table=03_4&wr_id=303
이 글을 참고 하세요.
* 음악 정보 가져오기
Music 소스를 보면 Title, Artist 등의 정보를 가져오는 것은 아래처럼 가져오더군요.
private Cursor mCursor; // 커서 선언
// 가져올 필드 정의
String[] mCursorCols = new String[] {
"audio._id AS _id", // index must match IDCOLIDX below
MediaStore.Audio.Media.ARTIST,
MediaStore.Audio.Media.ALBUM,
MediaStore.Audio.Media.TITLE,
MediaStore.Audio.Media.DATA,
MediaStore.Audio.Media.MIME_TYPE,
MediaStore.Audio.Media.ALBUM_ID,
MediaStore.Audio.Media.ARTIST_ID,
};
// 컨텐츠 리졸브로 데이타 가져옴.
Cursor cur = getContentResolver().query(
MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
mCursorCols, null , null, null);
저도 아직 초보라서 URI 하고 실제 DB 테이블 하고 어떻게 맵핑이 되는지는 모르는데요.
MediaStore.Audio.Media.EXTERNAL_CONTENT_URI
이것으로 가져오면 audio view를 이용하여 데이타를 가져오더군요.
SQL 문장으로 바꾸면,
select audio._id AS _id, artist, album, title .... from audio;
뭐 이정도 되더라구요.
가져오 Cursor 를 이용하여 출력하면 되는데요.
제가 아직 Apadter를 잘 쓰지 못해서 Cursor의 각 값을 array에 넣었다가
ArrayAdapter 로 다시 List에 넣어서 출력해 보았답니다.
위에서 구한 Cursor 를 이용해서
if (cur.moveToFirst()) {
String title;
String artist;
String id;
String albumArt;
int idNum;
int titleColumn = cur.getColumnIndex(MediaStore.Audio.Media.TITLE);
int artistColumn = cur.getColumnIndex(MediaStore.Audio.Media.ARTIST);
//int albumArtColumn = cur.getColumnIndex(MediaStore.Audio.Media.ALBUM_ART);
String imagePath;
do {
// Get the field values
idNum = cur.getInt(0); // 레코드의 _id를 가져옵니다.
id = String.valueOf(idNum);
title = cur.getString(titleColumn); // title 필드의 값을 가져옴
artist = cur.getString(artistColumn); // artist 필드의 값을 가져옴
//albumArt = cur.getString(8);
songs.add(title + "-" + artist); // 두개 합쳐서 array list 에 넣어줌.
apService.addSongPlaylist(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI + "/" + id); // 이것을 MediaPlayer에서 재생하기 위한 URI를 만들어주는 것입니다.
} while (cur.moveToNext());
ArrayAdapter<String> songList = new ArrayAdapter<String>(this,
R.layout.song_item, songs);
setListAdapter(songList);
}
이렇게 하면 노래정보는 출력이 됩니다.
* Album Art를 출력하려면 ??????
이 정보 찾으려고 한참 헤맷는데요. 아직도 출력을 못하였답니다 ^^
다만 대충 어떻게 들어가 있는지 확인은 하였습니다.
우선 안드로이드의 테이블을 좀 보겠습니다.
CREATE TABLE album_art (album_id INTEGER PRIMARY KEY,_data TEXT);
이런 테이블이 있구요.
CREATE VIEW album_info AS SELECT audio.album_id AS _id, album, album_key, MIN(year) AS minyear, MAX(year) AS maxyear,
artist, artist_id, artist_key, count(*) AS numsongs,album_art._data AS album_art
FROM audio LEFT OUTER JOIN album_art ON audio.album_id=album_art.album_id
WHERE is_music=1 GROUP BY audio.album_id;
album_info 뷰에서 album_art 데이타를 가져옵니다.
위에서 MediaStore.Audio.Media.EXTERNAL_CONTENT_URI 는 audio 뷰라고 말씀 드렸듯이 이것을 이용해서는 저 컬럼(필드)를 가져 올 수가 없습니다.
String[] cols = new String[] {
MediaStore.Audio.Albums._ID,
MediaStore.Audio.Albums.ARTIST,
MediaStore.Audio.Albums.ALBUM,
MediaStore.Audio.Albums.ALBUM_ART
};
Cursor cur = getContentResolver().query(
MediaStore.Audio.Albums.EXTERNAL_CONTENT_URI,
cols , null , null, null);
이렇게 바꾸어서 가져오는거 같더군요.
위 예제는 where 절이 없기 때문에 앨범테이블 다 가져옵니다.
특정한 값만 가져오는 것을 직접 해 보세요^^
안드로이드 사이트의 설명을 보면,
public static final String ALBUM_ART
A URI to the album art, if any
Type: TEXT
album_art 필드에 들어가 있는 값도 URI 라고 되어 있습니다.
아 URI 헷갈립니다 ㅡ.ㅡ
그래서 직접 DB 테이블의 내용을 보았습니다.
sqlite> select * from album_art;
select * from album_art;
2|/sdcard/albumthumbs/1254213657784
3|/sdcard/albumthumbs/1254213658032
이렇게 나오더군요.
_id 와 저런 문자열이 들어 있더군요.
/sdcard/albumthumbs/1254213657784
이것을 보고 이곳을 가서 ls을 해 보았습니다.
ls -l
----rwxr-x system sdcard_rw 3477 2009-09-30 07:01 1254213658032
----rwxr-x system sdcard_rw 50823 2009-09-30 07:01 1254213657784
#
sdcard에 해당 디렉토리에 저렇게 파일로 존재 하더군요.
URI를 이용해서 출력하는 것은 직접해 보세요 ^^
읽어주셔서,
감사합니다.
앨범 아트는 이렇게 가져오면 됩니다.
수고하세요 ~~
private static final BitmapFactory.Options sBitmapOptionsCache = new BitmapFactory.Options();
private static final Uri sArtworkUri = Uri.parse("content://media/external/audio/albumart");
public Bitmap getBitmapImage(int id, int w, int h) {
ContentResolver res = mContext.getContentResolver();
Uri uri = ContentUris.withAppendedId(sArtworkUri, id);
if (uri != null) {
ParcelFileDescriptor fd = null;
try {
fd = res.openFileDescriptor(uri, "r");
int sampleSize = 1;
sBitmapOptionsCache.inJustDecodeBounds = true;
BitmapFactory.decodeFileDescriptor(fd.getFileDescriptor(), null, sBitmapOptionsCache);
int nextWidth = sBitmapOptionsCache.outWidth >> 1;
int nextHeight = sBitmapOptionsCache.outHeight >> 1;
while (nextWidth>w && nextHeight>h) {
sampleSize <<= 1;
nextWidth >>= 1;
nextHeight >>= 1;
}
sBitmapOptionsCache.inSampleSize = sampleSize;
sBitmapOptionsCache.inJustDecodeBounds = false;
Bitmap b = BitmapFactory.decodeFileDescriptor(
fd.getFileDescriptor(), null, sBitmapOptionsCache);
if (b != null) {
if (sBitmapOptionsCache.outWidth != w || sBitmapOptionsCache.outHeight != h) {
Bitmap tmp = Bitmap.createScaledBitmap(b, w, h, true);
b.recycle();
b = tmp;
}
}
return b;
} catch (FileNotFoundException e) { return null;
} catch (Exception e) { return null;
} finally {
try {
if (fd != null)
fd.close();
} catch (IOException e) {
}
}
}
return null;
}
많이 어렵네요...