안드로이드 개발 정보
(글 수 1,067)
안녕하세요.
앞의 글에서 MediaScanner 서비스를 실행하는 것이구요.
이글은 조금 더 복잡하지만 수동으로 Media Scanning을 하는 것입니다.
http://developer.android.com/reference/android/media/MediaScannerConnection.html
위 링크에 설명이 있는데요.
생성자를 보면,
이렇게 되어 있습니다.
생성자가 MediaScannerConnection.MediaScannerConnectionClient 를 필요로 하므로,
이것을 먼저 만들어 줍니다.
private MediaScannerConnectionClient mScanClient = new MediaScannerConnectionClient(){
public void onMediaScannerConnected() {
}
public void onScanCompleted(String path, Uri uri) {
}
};
이 클립스가 이렇게 코드를 생성해 줄텐데요.
위 두 함수를 채워 주면 됩니다.
onMediaScannerConnected() 이 함수는 MediaScanner 서비스가 연결이 된 경우 호출이 되고,
onScanCompleted() 이 함수는 스캔이 성공한 파일에 대한 정보를 전달해 줍니다.
우선 내용을 채우는 것은 아래 설명을 본 후에 채워 넣겠습니다.
이제
private MediaScannerConnection msc = new MediaScannerConnection(this, mScanClient);
이렇게 MediaScannerConnection 변수를 만들어 줍니다.
MediaScannerConnection 의 함수들을 보면 아래와 같이 있습니다.
버튼이나 어느곳이나 Media Scan을 시작하고 싶은 곳에서
msc.connect();
을 호출합니다.
그럼, MediaScanner 서비스와 연결이 되면, MediaScannerConnectionClient 의 onMediaScannerConnected() 가 호출이 된답니다.
그러므로, 실제 scanFile을 할 수 있는 곳이 onMediaScannerConnected() 함수 안 이랍니다.
그리고, scanFile의 설명을 보면, 'a file' 이라고 명시하고 있습니다.
scanFile의 path 값에는 /sdcard/* 이런 값은 들어가지 않는답니다.
넣어도 되지만 스캐닝이 안되지요.
이말은 스캐닝할 파일들을 알아서 찾아서 정확한 파일명으로 넣어주어야 된다는 것입니다.
이제 onMediaScannerConnected() 함수를 채워 보겠습니다.
private MediaScannerConnectionClient mScanClient = new MediaScannerConnectionClient(){
public void onMediaScannerConnected() {
Log.i(TAG, "onMediaScannerConnected");
File file = Environment.getExternalStorageDirectory(); // 외장 디렉토리 가져옴
File[] fileNames = file.listFiles(new FilenameFilter(){ // 특정 확장자만 가진 파일들을 필터링함
public boolean accept(File dir, String name){
return name.endsWith(".mp4")
|| name.endsWith(".avi")
|| name.endsWith(".wmv")
;
}
});
if (fileNames != null)
{
for (int i = 0; i < fileNames.length ; i++) // 파일 갯수 만큼 scanFile을 호출함
{
msc.scanFile(fileNames[i].getAbsolutePath(), null);
}
}
}
public void onScanCompleted(String path, Uri uri) {
Log.i(TAG, "onScanCompleted(" + path + ", " + uri.toString() + ")"); // 스캐닝한 정보를 출력해봄
}
};
위 코드에서는 하위 디렉토리에 대한 처리는 없습니다. (예제이기 때문이죠 ^^)
이렇게 해서 LogCat에 찍히는 정보를 보면,
01-05 13:57:16.918: INFO/TextTest(520): onMediaScannerConnected
01-05 13:57:17.039: DEBUG/MediaScannerService(163): IMediaScannerService.scanFile: /sdcard/SolB.mp4 mimeType: null
01-05 13:57:17.088: DEBUG/MediaScannerService(163): IMediaScannerService.scanFile: /sdcard/2008SA-Lp(̱Ʈ).mp4 mimeType: null
01-05 13:57:17.117: DEBUG/MediaScannerService(163): IMediaScannerService.scanFile: /sdcard/ڰö .mp4 mimeType: null
01-05 13:57:17.168: DEBUG/MediaScannerService(163): IMediaScannerService.scanFile: /sdcard/2007_1215 GPF Yu-Na Kim SP.mp4 mimeType: null
01-05 13:57:17.209: DEBUG/MediaScannerService(163): IMediaScannerService.scanFile: /sdcard/2009 Skate America - Ladies' Short Program - Yu-na Kim.mp4 mimeType: null
01-05 13:57:17.239: DEBUG/MediaScannerService(163): IMediaScannerService.scanFile: /sdcard/2009.1017.TEB.Yu-Na Kim SP.[6Audio.4Sub].720p.60fps.x264.6000K-Kimini.mp4 mimeType: null
01-05 13:57:17.278: DEBUG/MediaScannerService(163): IMediaScannerService.scanFile: /sdcard/2009.ISU.Skate.America.Interview.Yu-Na.Kim.810p.TVAsahi.X264-.mp4 mimeType: null
01-05 13:57:17.319: DEBUG/MediaScannerService(163): IMediaScannerService.scanFile: /sdcard/ǹþƹ.mp4 mimeType: null
01-05 13:57:17.358: DEBUG/MediaScannerService(163): IMediaScannerService.scanFile: /sdcard/͹̳2-1991.EE.XviD.AC3.CD2.avi mimeType: null
01-05 13:57:17.537: INFO/TextTest(520): onScanCompleted(/sdcard/SolB.mp4, content://media/external/video/media/3)
01-05 13:57:17.729: INFO/TextTest(520): onScanCompleted(/sdcard/2008SA-Lp(̱Ʈ).mp4, content://media/external/video/media/4)
01-05 13:57:17.928: INFO/TextTest(520): onScanCompleted(/sdcard/ڰö .mp4, content://media/external/video/media/5)
01-05 13:57:18.118: INFO/TextTest(520): onScanCompleted(/sdcard/2007_1215 GPF Yu-Na Kim SP.mp4, content://media/external/video/media/6)
01-05 13:57:18.327: INFO/TextTest(520): onScanCompleted(/sdcard/2009 Skate America - Ladies' Short Program - Yu-na Kim.mp4, content://media/external/video/media/7)
01-05 13:57:18.538: INFO/TextTest(520): onScanCompleted(/sdcard/2009.1017.TEB.Yu-Na Kim SP.[6Audio.4Sub].720p.60fps.x264.6000K-Kimini.mp4, content://media/external/video/media/8)
01-05 13:57:18.739: INFO/TextTest(520): onScanCompleted(/sdcard/2009.ISU.Skate.America.Interview.Yu-Na.Kim.810p.TVAsahi.X264-.mp4, content://media/external/video/media/9)
01-05 13:57:18.928: INFO/TextTest(520): onScanCompleted(/sdcard/ǹþƹ.mp4, content://media/external/video/media/10)
이런식으로 스캔이 되는 상황을 볼 수가 있습니다.
그런데, 여기서 알수 없는 정보가 있더군요.
스캔이 완료 되었는지 확인할 방법이 없더군요 ㅡ.ㅡ
제가 SDCARD에서 8개의 진짜 동영상 파일과 1개의 가짜 동영상 파일을 넣었답니다.
가짜 파일은 text 파일인데 , 확장자만 avi로 바꾸어 놓았지요.
위에서 빨간색으로 표시한 부분이랍니다.
그런데, 이 파일은 onScanCompleted() 함수에서 불려지지가 않더군요.
실제 디렉토리를 전부 읽어서 파일명을 다 알고 scanFile을 다 호출해도
마지막 까지 진행이 되고 아니면 아직도 스캔중인지 알 수가 없겠더라구요.
스캐닝 중이면을 대화상자로 표시하였다고 하면, 언제 닫아야 하는지 알수 가 없다는 것입니다.
아무튼 사용법은 위와 같구요.
public void onClick(View v) {
if (msc != null)
{
if (msc.isConnected())
msc.disconnect();
else
msc.connect();
}
}
스캐닝을 시작하는 버튼을 위와 같이 만들어 주었답니다.
스캐닝 중간이라도 msc.disconnect(); 호출하면 중간에 스캐닝을 멈추기는 하더군요.
혹시 스캐닝이 완료된 시점을 알 수 있는 방법을 아시는 분 좀 알려주십시오. ^^
감사합니다.
앞의 글에서 MediaScanner 서비스를 실행하는 것이구요.
이글은 조금 더 복잡하지만 수동으로 Media Scanning을 하는 것입니다.
http://developer.android.com/reference/android/media/MediaScannerConnection.html
위 링크에 설명이 있는데요.
생성자를 보면,
Constructs a new MediaScannerConnection object. |
이렇게 되어 있습니다.
생성자가 MediaScannerConnection.MediaScannerConnectionClient 를 필요로 하므로,
이것을 먼저 만들어 줍니다.
private MediaScannerConnectionClient mScanClient = new MediaScannerConnectionClient(){
public void onMediaScannerConnected() {
}
public void onScanCompleted(String path, Uri uri) {
}
};
이 클립스가 이렇게 코드를 생성해 줄텐데요.
위 두 함수를 채워 주면 됩니다.
onMediaScannerConnected() 이 함수는 MediaScanner 서비스가 연결이 된 경우 호출이 되고,
onScanCompleted() 이 함수는 스캔이 성공한 파일에 대한 정보를 전달해 줍니다.
우선 내용을 채우는 것은 아래 설명을 본 후에 채워 넣겠습니다.
이제
private MediaScannerConnection msc = new MediaScannerConnection(this, mScanClient);
이렇게 MediaScannerConnection 변수를 만들어 줍니다.
MediaScannerConnection 의 함수들을 보면 아래와 같이 있습니다.
Public Methods | |||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|
Initiates a connection to the media scanner service.
| |||||||||||
Releases the connection to the media scanner service.
| |||||||||||
Returns whether we are connected to the media scanner service
| |||||||||||
Part of the ServiceConnection interface.
| |||||||||||
Part of the ServiceConnection interface.
| |||||||||||
Requests the media scanner to scan a file. |
버튼이나 어느곳이나 Media Scan을 시작하고 싶은 곳에서
msc.connect();
을 호출합니다.
그럼, MediaScanner 서비스와 연결이 되면, MediaScannerConnectionClient 의 onMediaScannerConnected() 가 호출이 된답니다.
그러므로, 실제 scanFile을 할 수 있는 곳이 onMediaScannerConnected() 함수 안 이랍니다.
그리고, scanFile의 설명을 보면, 'a file' 이라고 명시하고 있습니다.
scanFile의 path 값에는 /sdcard/* 이런 값은 들어가지 않는답니다.
넣어도 되지만 스캐닝이 안되지요.
이말은 스캐닝할 파일들을 알아서 찾아서 정확한 파일명으로 넣어주어야 된다는 것입니다.
이제 onMediaScannerConnected() 함수를 채워 보겠습니다.
private MediaScannerConnectionClient mScanClient = new MediaScannerConnectionClient(){
public void onMediaScannerConnected() {
Log.i(TAG, "onMediaScannerConnected");
File file = Environment.getExternalStorageDirectory(); // 외장 디렉토리 가져옴
File[] fileNames = file.listFiles(new FilenameFilter(){ // 특정 확장자만 가진 파일들을 필터링함
public boolean accept(File dir, String name){
return name.endsWith(".mp4")
|| name.endsWith(".avi")
|| name.endsWith(".wmv")
;
}
});
if (fileNames != null)
{
for (int i = 0; i < fileNames.length ; i++) // 파일 갯수 만큼 scanFile을 호출함
{
msc.scanFile(fileNames[i].getAbsolutePath(), null);
}
}
}
public void onScanCompleted(String path, Uri uri) {
Log.i(TAG, "onScanCompleted(" + path + ", " + uri.toString() + ")"); // 스캐닝한 정보를 출력해봄
}
};
위 코드에서는 하위 디렉토리에 대한 처리는 없습니다. (예제이기 때문이죠 ^^)
이렇게 해서 LogCat에 찍히는 정보를 보면,
01-05 13:57:16.918: INFO/TextTest(520): onMediaScannerConnected
01-05 13:57:17.039: DEBUG/MediaScannerService(163): IMediaScannerService.scanFile: /sdcard/SolB.mp4 mimeType: null
01-05 13:57:17.088: DEBUG/MediaScannerService(163): IMediaScannerService.scanFile: /sdcard/2008SA-Lp(̱Ʈ).mp4 mimeType: null
01-05 13:57:17.117: DEBUG/MediaScannerService(163): IMediaScannerService.scanFile: /sdcard/ڰö .mp4 mimeType: null
01-05 13:57:17.168: DEBUG/MediaScannerService(163): IMediaScannerService.scanFile: /sdcard/2007_1215 GPF Yu-Na Kim SP.mp4 mimeType: null
01-05 13:57:17.209: DEBUG/MediaScannerService(163): IMediaScannerService.scanFile: /sdcard/2009 Skate America - Ladies' Short Program - Yu-na Kim.mp4 mimeType: null
01-05 13:57:17.239: DEBUG/MediaScannerService(163): IMediaScannerService.scanFile: /sdcard/2009.1017.TEB.Yu-Na Kim SP.[6Audio.4Sub].720p.60fps.x264.6000K-Kimini.mp4 mimeType: null
01-05 13:57:17.278: DEBUG/MediaScannerService(163): IMediaScannerService.scanFile: /sdcard/2009.ISU.Skate.America.Interview.Yu-Na.Kim.810p.TVAsahi.X264-.mp4 mimeType: null
01-05 13:57:17.319: DEBUG/MediaScannerService(163): IMediaScannerService.scanFile: /sdcard/ǹþƹ.mp4 mimeType: null
01-05 13:57:17.358: DEBUG/MediaScannerService(163): IMediaScannerService.scanFile: /sdcard/͹̳2-1991.EE.XviD.AC3.CD2.avi mimeType: null
01-05 13:57:17.537: INFO/TextTest(520): onScanCompleted(/sdcard/SolB.mp4, content://media/external/video/media/3)
01-05 13:57:17.729: INFO/TextTest(520): onScanCompleted(/sdcard/2008SA-Lp(̱Ʈ).mp4, content://media/external/video/media/4)
01-05 13:57:17.928: INFO/TextTest(520): onScanCompleted(/sdcard/ڰö .mp4, content://media/external/video/media/5)
01-05 13:57:18.118: INFO/TextTest(520): onScanCompleted(/sdcard/2007_1215 GPF Yu-Na Kim SP.mp4, content://media/external/video/media/6)
01-05 13:57:18.327: INFO/TextTest(520): onScanCompleted(/sdcard/2009 Skate America - Ladies' Short Program - Yu-na Kim.mp4, content://media/external/video/media/7)
01-05 13:57:18.538: INFO/TextTest(520): onScanCompleted(/sdcard/2009.1017.TEB.Yu-Na Kim SP.[6Audio.4Sub].720p.60fps.x264.6000K-Kimini.mp4, content://media/external/video/media/8)
01-05 13:57:18.739: INFO/TextTest(520): onScanCompleted(/sdcard/2009.ISU.Skate.America.Interview.Yu-Na.Kim.810p.TVAsahi.X264-.mp4, content://media/external/video/media/9)
01-05 13:57:18.928: INFO/TextTest(520): onScanCompleted(/sdcard/ǹþƹ.mp4, content://media/external/video/media/10)
이런식으로 스캔이 되는 상황을 볼 수가 있습니다.
그런데, 여기서 알수 없는 정보가 있더군요.
스캔이 완료 되었는지 확인할 방법이 없더군요 ㅡ.ㅡ
제가 SDCARD에서 8개의 진짜 동영상 파일과 1개의 가짜 동영상 파일을 넣었답니다.
가짜 파일은 text 파일인데 , 확장자만 avi로 바꾸어 놓았지요.
위에서 빨간색으로 표시한 부분이랍니다.
그런데, 이 파일은 onScanCompleted() 함수에서 불려지지가 않더군요.
실제 디렉토리를 전부 읽어서 파일명을 다 알고 scanFile을 다 호출해도
마지막 까지 진행이 되고 아니면 아직도 스캔중인지 알 수가 없겠더라구요.
스캐닝 중이면을 대화상자로 표시하였다고 하면, 언제 닫아야 하는지 알수 가 없다는 것입니다.
아무튼 사용법은 위와 같구요.
public void onClick(View v) {
if (msc != null)
{
if (msc.isConnected())
msc.disconnect();
else
msc.connect();
}
}
스캐닝을 시작하는 버튼을 위와 같이 만들어 주었답니다.
스캐닝 중간이라도 msc.disconnect(); 호출하면 중간에 스캐닝을 멈추기는 하더군요.
혹시 스캐닝이 완료된 시점을 알 수 있는 방법을 아시는 분 좀 알려주십시오. ^^
감사합니다.
2010.01.05 23:19:58
onScanCompleted는 1개 파일이 스캔이 완료되었을 때 호출이 되는 함수 랍니다.
scanFile을 10번 호출할 때, onScanCompleted 10번 호출되면 다 되었구만 하면 되겠지만,
위에서 썼듯이, onScanCompleted 자체가 호출이 안되는 경우도 있습니다.
즉, 갯수를 세어서도 숫자가 모자란 상황이 나올 수 있어서 완료여부를 확인할 수 없고,
그렇다고, 전체 다 스캔이 되었다고 하는 것도 없다는 것입니다.
어쩌면, onScanCompleted 이 호출안되는 것이 버그일 수도 있지만,
현재로서는 방법을 못 찾겠네요 ^^
scanFile을 10번 호출할 때, onScanCompleted 10번 호출되면 다 되었구만 하면 되겠지만,
위에서 썼듯이, onScanCompleted 자체가 호출이 안되는 경우도 있습니다.
즉, 갯수를 세어서도 숫자가 모자란 상황이 나올 수 있어서 완료여부를 확인할 수 없고,
그렇다고, 전체 다 스캔이 되었다고 하는 것도 없다는 것입니다.
어쩌면, onScanCompleted 이 호출안되는 것이 버그일 수도 있지만,
현재로서는 방법을 못 찾겠네요 ^^
2010.01.12 14:56:36
Eclair pull Source에서 확인하시면 MediaScannerService class 내에..
private void scan(String[] directories, String volumeName) {
// don't sleep while scanning
mWakeLock.acquire();
ContentValues values = new ContentValues();
values.put(MediaStore.MEDIA_SCANNER_VOLUME, volumeName);
Uri scanUri = getContentResolver().insert(MediaStore.getMediaScannerUri(), values);
Uri uri = Uri.parse("file://" + directories[0]);
sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_STARTED, uri));
try {
if (volumeName.equals(MediaProvider.EXTERNAL_VOLUME)) {
openDatabase(volumeName);
}
MediaScanner scanner = createMediaScanner();
scanner.scanDirectories(directories, volumeName);
} catch (Exception e) {
Log.e(TAG, "exception in MediaScanner.scan()", e);
}
getContentResolver().delete(scanUri, null, null);
sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_FINISHED, uri));
mWakeLock.release();
}
-----------------------------------------------------------------------------------------------------------------------
sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_FINISHED, uri)); 의해 전달하는 내용을 리씨브 하시면 정확한 시점을
아실 수 있을거 같긴한데 소스에서 확인 했듯이..start 했으면 반듯이 finish 됩니다. 다시 말해 예외처리 메세지는 log로 되어 있어서 리씨브가 불가능 하게 되어 있더군요..
public abstract void onScanCompleted (String path, Uri uri)
Called to notify the client when the media scanner has finished scanning a file.
Parameters