programing

Intent.ACTION_GET_CONTENT에서 반환 된 URI에서 파일 이름을 추출하는 방법은 무엇입니까?

nasanasas 2020. 10. 20. 07:43
반응형

Intent.ACTION_GET_CONTENT에서 반환 된 URI에서 파일 이름을 추출하는 방법은 무엇입니까?


타사 파일 관리자를 사용하여 파일 시스템에서 파일 (제 경우에는 PDF)을 선택합니다.

이것이 내가 활동을 시작하는 방법입니다.

Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.setType(getString(R.string.app_pdf_mime_type));
intent.addCategory(Intent.CATEGORY_OPENABLE);

String chooserName = getString(R.string.Browse);
Intent chooser = Intent.createChooser(intent, chooserName);

startActivityForResult(chooser, ActivityRequests.BROWSE);

이것이 내가 가진 것입니다 onActivityResult.

Uri uri = data.getData();
if (uri != null) {
    if (uri.toString().startsWith("file:")) {
        fileName = uri.getPath();
    } else { // uri.startsWith("content:")

        Cursor c = getContentResolver().query(uri, null, null, null, null);

        if (c != null && c.moveToFirst()) {

            int id = c.getColumnIndex(Images.Media.DATA);
            if (id != -1) {
                fileName = c.getString(id);
            }
        }
    }
}

코드 조각은 http://www.openintents.org/en/node/829에 있는 Open Intents 파일 관리자 지침 에서 차용되었습니다
.

의 목적 if-else은 이전 버전과의 호환성입니다. 다른 파일 관리자가 모든 종류의 것을 반환한다는 것을 알았 기 때문에 이것이 파일 이름을 얻는 가장 좋은 방법인지 궁금합니다.

예를 들어 Documents ToGo 는 다음과 같은 내용을 반환합니다.

content://com.dataviz.dxtg.documentprovider/document/file%3A%2F%2F%2Fsdcard%2Fdropbox%2FTransfer%2Fconsent.pdf

어떤에 getContentResolver().query()반환 null.

더 흥미롭게 만들기 위해 이름이 지정되지 않은 파일 관리자 (클라이언트 로그에서이 URI를 얻었습니다)는 다음과 같은 결과를 반환했습니다.

/./sdcard/downloads/.bin


URI에서 파일 이름을 추출하는 선호하는 방법이 있습니까? 아니면 문자열 구문 분석에 의존해야합니까?


developer.android.com에는 이에 대한 멋진 예제 코드가 있습니다 : https://developer.android.com/guide/topics/providers/document-provider.html

파일 이름을 추출하기위한 압축 버전 ( "this"가 활동이라고 가정) :

public String getFileName(Uri uri) {
  String result = null;
  if (uri.getScheme().equals("content")) {
    Cursor cursor = getContentResolver().query(uri, null, null, null, null);
    try {
      if (cursor != null && cursor.moveToFirst()) {
        result = cursor.getString(cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME));
      }
    } finally {
      cursor.close();
    }
  }
  if (result == null) {
    result = uri.getPath();
    int cut = result.lastIndexOf('/');
    if (cut != -1) {
      result = result.substring(cut + 1);
    }
  }
  return result;
}

나는 다음과 같은 것을 사용하고 있습니다.

String scheme = uri.getScheme();
if (scheme.equals("file")) {
    fileName = uri.getLastPathSegment();
}
else if (scheme.equals("content")) {
    String[] proj = { MediaStore.Images.Media.TITLE };
    Cursor cursor = context.getContentResolver().query(contentUri, proj, null, null, null);
    if (cursor != null && cursor.getCount() != 0) {
        int columnIndex = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.TITLE);
        cursor.moveToFirst();
        fileName = cursor.getString(columnIndex);
    }
    if (cursor != null) {
        cursor.close();
    }
}

파일 정보 검색 에서 가져옴 | Android 개발자

파일 이름 검색.

private String queryName(ContentResolver resolver, Uri uri) {
    Cursor returnCursor =
            resolver.query(uri, null, null, null, null);
    assert returnCursor != null;
    int nameIndex = returnCursor.getColumnIndex(OpenableColumns.DISPLAY_NAME);
    returnCursor.moveToFirst();
    String name = returnCursor.getString(nameIndex);
    returnCursor.close();
    return name;
}

짧게 원하면 작동합니다.

Uri uri= data.getData();
File file= new File(uri.getPath());
file.getName();

파일 이름을 얻는 가장 쉬운 방법 :

val fileName = File(uri.path).name
// or
val fileName = uri.pathSegments.last()

올바른 이름을 제공하지 않으면 다음을 사용해야합니다.

fun Uri.getName(context: Context): String {
    val returnCursor = context.contentResolver.query(this, null, null, null, null)
    val nameIndex = returnCursor.getColumnIndex(OpenableColumns.DISPLAY_NAME)
    returnCursor.moveToFirst()
    val fileName = returnCursor.getString(nameIndex)
    returnCursor.close()
    return fileName
}

아래 코드를 사용하여 프로젝트의 Uri에서 파일 이름 및 파일 크기를 가져옵니다.

/**
 * Used to get file detail from uri.
 * <p>
 * 1. Used to get file detail (name & size) from uri.
 * 2. Getting file details from uri is different for different uri scheme,
 * 2.a. For "File Uri Scheme" - We will get file from uri & then get its details.
 * 2.b. For "Content Uri Scheme" - We will get the file details by querying content resolver.
 *
 * @param uri Uri.
 * @return file detail.
 */
public static FileDetail getFileDetailFromUri(final Context context, final Uri uri) {
    FileDetail fileDetail = null;
    if (uri != null) {
        fileDetail = new FileDetail();
        // File Scheme.
        if (ContentResolver.SCHEME_FILE.equals(uri.getScheme())) {
            File file = new File(uri.getPath());
            fileDetail.fileName = file.getName();
            fileDetail.fileSize = file.length();
        }
        // Content Scheme.
        else if (ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) {
            Cursor returnCursor =
                    context.getContentResolver().query(uri, null, null, null, null);
            if (returnCursor != null && returnCursor.moveToFirst()) {
                int nameIndex = returnCursor.getColumnIndex(OpenableColumns.DISPLAY_NAME);
                int sizeIndex = returnCursor.getColumnIndex(OpenableColumns.SIZE);
                fileDetail.fileName = returnCursor.getString(nameIndex);
                fileDetail.fileSize = returnCursor.getLong(sizeIndex);
                returnCursor.close();
            }
        }
    }
    return fileDetail;
}

/**
 * File Detail.
 * <p>
 * 1. Model used to hold file details.
 */
public static class FileDetail {

    // fileSize.
    public String fileName;

    // fileSize in bytes.
    public long fileSize;

    /**
     * Constructor.
     */
    public FileDetail() {

    }
}

public String getFilename() 
{
/*  Intent intent = getIntent();
    String name = intent.getData().getLastPathSegment();
    return name;*/
    Uri uri=getIntent().getData();
    String fileName = null;
    Context context=getApplicationContext();
    String scheme = uri.getScheme();
    if (scheme.equals("file")) {
        fileName = uri.getLastPathSegment();
    }
    else if (scheme.equals("content")) {
        String[] proj = { MediaStore.Video.Media.TITLE };
        Uri contentUri = null;
        Cursor cursor = context.getContentResolver().query(uri, proj, null, null, null);
        if (cursor != null && cursor.getCount() != 0) {
            int columnIndex = cursor.getColumnIndexOrThrow(MediaStore.Video.Media.TITLE);
            cursor.moveToFirst();
            fileName = cursor.getString(columnIndex);
        }
    }
    return fileName;
}

String Fpath = getPath(this, uri) ;
File file = new File(Fpath);
String filename = file.getName();

내 버전의 답변은 실제로 @Stefan Haustein과 매우 유사합니다. Android 개발자 페이지 파일 정보 검색 에서 답변을 찾았습니다 . 여기에있는 정보는 스토리지 액세스 프레임 워크 가이드 사이트 보다이 특정 주제에 대해 더 요약되어 있습니다. 쿼리 결과에서 파일 이름을 포함하는 열 인덱스는 OpenableColumns.DISPLAY_NAME입니다. 열 인덱스에 대한 다른 답변 / 솔루션은 나를 위해 일하지 않았습니다. 다음은 샘플 함수입니다.

 /**
 * @param uri uri of file.
 * @param contentResolver access to server app.
 * @return the name of the file.
 */
def extractFileName(uri: Uri, contentResolver: ContentResolver): Option[String] = {

    var fileName: Option[String] = None
    if (uri.getScheme.equals("file")) {

        fileName = Option(uri.getLastPathSegment)
    } else if (uri.getScheme.equals("content")) {

        var cursor: Cursor = null
        try {

            // Query the server app to get the file's display name and size.
            cursor = contentResolver.query(uri, null, null, null, null)

            // Get the column indexes of the data in the Cursor,
            // move to the first row in the Cursor, get the data.
            if (cursor != null && cursor.moveToFirst()) {

                val nameIndex = cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME)
                fileName = Option(cursor.getString(nameIndex))
            }

        } finally {

            if (cursor != null) {
                cursor.close()
            }

        }

    }

    fileName
}

먼저 URI개체를 URL개체 로 변환 한 다음 File개체를 사용 하여 파일 이름을 검색해야합니다.

try
    {
        URL videoUrl = uri.toURL();
        File tempFile = new File(videoUrl.getFile());
        String fileName = tempFile.getName();
    }
    catch (Exception e)
    {

    }

그게 아주 쉽습니다.


xamarin / c #에 대한 Stefan Haustein 함수 :

public string GetFilenameFromURI(Android.Net.Uri uri)
        {
            string result = null;
            if (uri.Scheme == "content")
            {
                using (var cursor = Application.Context.ContentResolver.Query(uri, null, null, null, null))
                {
                    try
                    {
                        if (cursor != null && cursor.MoveToFirst())
                        {
                            result = cursor.GetString(cursor.GetColumnIndex(OpenableColumns.DisplayName));
                        }
                    }
                    finally
                    {
                        cursor.Close();
                    }
                }
            }
            if (result == null)
            {
                result = uri.Path;
                int cut = result.LastIndexOf('/');
                if (cut != -1)
                {
                    result = result.Substring(cut + 1);
                }
            }
            return result;
        }

If you want to have the filename with extension I use this function to get it. It also works with google drive file picks

public static String getFileName(Uri uri) {
    String result;

    //if uri is content
    if (uri.getScheme() != null && uri.getScheme().equals("content")) {
        Cursor cursor = global.getInstance().context.getContentResolver().query(uri, null, null, null, null);
        try {
            if (cursor != null && cursor.moveToFirst()) {
                //local filesystem
                int index = cursor.getColumnIndex("_data");
                if(index == -1)
                    //google drive
                    index = cursor.getColumnIndex("_display_name");
                result = cursor.getString(index);
                if(result != null)
                    uri = Uri.parse(result);
                else
                    return null;
            }
        } finally {
            cursor.close();
        }
    }

    result = uri.getPath();

    //get filename + ext of path
    int cut = result.lastIndexOf('/');
    if (cut != -1)
        result = result.substring(cut + 1);
    return result;
}

For Kotlin, You can use something like this :

object FileUtils {

fun getFileName(context: Context, uri : Uri) : String {
    var fileName = "Unknown"
    when (uri.scheme) {
        ContentResolver.SCHEME_FILE -> {
            fileName = File(uri.path).name
        }
        ContentResolver.SCHEME_CONTENT -> {
            try {
                context.contentResolver.query(
                    uri,
                    null,
                    null,
                    null,
                    null
                )?.apply {
                    if (moveToFirst()) {
                        fileName = getString(getColumnIndex(OpenableColumns.DISPLAY_NAME))
                    }
                    close()
                }
            } catch (e : Exception) {
                return fileName
            }
        }
    }
    return fileName
}
}

This actually worked for me:

private String uri2filename() {

    String ret;
    String scheme = uri.getScheme();

    if (scheme.equals("file")) {
        ret = uri.getLastPathSegment();
    }
    else if (scheme.equals("content")) {
        Cursor cursor = getContentResolver().query(uri, null, null, null, null);
        if (cursor != null && cursor.moveToFirst()) {
            ret = cursor.getString(cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME));
        }
   }
   return ret;
}

참고URL : https://stackoverflow.com/questions/5568874/how-to-extract-the-file-name-from-uri-returned-from-intent-action-get-content

반응형