2015년 8월 25일 화요일

Android File Chooser and URI to File Path.

파일을 Intent.ACTION_GET_CONTENT을 이용하여 선택하고 URIFile Path로 변환하기

Image 나 Video 같은 파일을 얻어오는 예제는 많지만 일반 파일을 선택하는 예제가 없어서 며칠 찾아 보다가 직접 external.db에서 값을 얻어와야 한다는 결론을 얻었습니다.

/data/data/com.android.providers.media/databases 경로에 가면 모든 파일을 DB로 관리합니다.

root@odroidc:/data/data/com.android.providers.media/databases # ls -l
-rw-rw---- u0_a4    u0_a4      163840 2015-08-25 03:23 external.db
-rw-rw---- u0_a4    u0_a4       32768 2015-08-25 03:21 external.db-shm
-rw-rw---- u0_a4    u0_a4       28872 2015-08-25 03:21 external.db-wal
-rw-rw---- u0_a4    u0_a4      212992 2015-08-20 06:22 internal.db
-rw------- u0_a4    u0_a4       32768 2015-08-25 03:21 internal.db-shm
-rw------- u0_a4    u0_a4      453232 2015-08-25 03:21 internal.db-wal
root@odroidc:/data/data/com.android.providers.media/databases #

external.db를 sqliteman 프로그램을 이용하여 열어 보시면 아래와 같이 되어 있습니다.
files 테이블에 '_data'란 column에 실제 file path가 들어 있습니다.



private static final int FILE_SELECT_CODE = 0;

private void showFileChooser() {
    Intent intent = new Intent();
    intent.setAction(Intent.ACTION_GET_CONTENT);

아래와 같이 할 경우 mime-type에 해당하는 파일만 선택 가능해 집니다.
    intent.setType("application/zip");
    intent.addCategory(Intent.CATEGORY_OPENABLE);

    try {
        startActivityForResult(
                Intent.createChooser(intent, "Select a File"),
                FILE_SELECT_CODE);
    } catch (android.content.ActivityNotFoundException ex) {
        // Potentially direct the user to the Market with a Dialog
        Toast.makeText(this, "Please install a File Manager.",
                Toast.LENGTH_SHORT).show();
    }
}

showFileChooser()를 실행하면 아래와 같은 file dialog가 실행 됩니다.


@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    switch (requestCode) {
        case FILE_SELECT_CODE:
            if (resultCode == RESULT_OK) {
                // Get the Uri of the selected file
                Uri uri = data.getData();
URI -> real file path
                String file_path = getRealPathFromURI(uri);
            }
            break;
    }
    super.onActivityResult(requestCode, resultCode, data);
}


private String getRealPathFromURI(Uri uri) {
    String filePath = "";
    filePath = uri.getPath();
경로에 /storage가 들어가면 real file path로 판단
    if (filePath.startsWith("/storage"))
        return filePath;

    String wholeID = DocumentsContract.getDocumentId(uri);

wholeID는 파일명이 abc.zip이라면 /document/B5D7-1CE9:abc.zip와 같습니다.

    // Split at colon, use second item in the array
    String id = wholeID.split(":")[1];

    Log.e(TAG, "id = " + id);

    String[] column = { MediaStore.Files.FileColumns.DATA };

파일의 이름을 통해 where 조건식을 만듭니다.

    String sel = MediaStore.Files.FileColumns.DATA + " LIKE '%" + id + "%'";

External storage에 있는 파일의 DB를 접근하는 방법 입니다.
    Cursor cursor = getContentResolver().query(MediaStore.Files.getContentUri("external"),
            column, sel, null, null);

SQL문으로 표현하면 아래와 같이 되겠죠????
SELECT _dtat FROM files WHERE _data LIKE '%selected file name%'

    int columnIndex = cursor.getColumnIndex(column[0]);

    if (cursor.moveToFirst()) {
        filePath = cursor.getString(columnIndex);
    }
    cursor.close();
    return filePath;
}