source

Android:컨텐츠 URI에서 파일 URI를 가져오시겠습니까?

ittop 2023. 8. 30. 22:05
반응형

Android:컨텐츠 URI에서 파일 URI를 가져오시겠습니까?

내 앱에서 사용자는 앱이 처리하는 오디오 파일을 선택해야 합니다.문제는 앱이 오디오 파일로 원하는 작업을 수행하기 위해서는 URI가 파일 형식이어야 한다는 것입니다.Android의 기본 음악 플레이어를 사용하여 앱에서 오디오 파일을 검색하면 URI는 다음과 같은 내용의 URI가 됩니다.

content://media/external/audio/media/710

그러나 인기 있는 파일 관리자 애플리케이션 Astro를 사용하면 다음과 같은 이점을 얻을 수 있습니다.

file:///sdcard/media/audio/ringtones/GetupGetOut.mp3

후자는 제가 작업하기에 훨씬 더 접근하기 쉽지만, 물론 사용자가 컬렉션을 탐색하는 데 사용하는 프로그램에 상관없이 사용자가 선택한 오디오 파일로 앱이 기능하기를 원합니다.그래서 제 질문은, 그것을 변환할 수 있는 방법이 있습니까?content://URI를 a로 스타일 지정file://URI? 아니면 이 문제를 해결하기 위해 무엇을 추천하시겠습니까?다음은 선택기를 불러오는 코드입니다. 참고로 사용할 수 있습니다.

Intent ringIntent = new Intent();
ringIntent.setType("audio/mp3");
ringIntent.setAction(Intent.ACTION_GET_CONTENT);
ringIntent.addCategory(Intent.CATEGORY_OPENABLE);
startActivityForResult(Intent.createChooser(ringIntent, "Select Ringtone"), SELECT_RINGTONE);

URI 컨텐츠를 사용하여 다음 작업을 수행합니다.

m_ringerPath = m_ringtoneUri.getPath();
File file = new File(m_ringerPath);

그런 다음 해당 파일로 FileInputStream 작업을 수행합니다.

그냥 사용하기getContentResolver().openInputStream(uri)점수를 따다InputStreamURI로부터.

http://developer.android.com/reference/android/content/ContentResolver.html#openInputStream(android.net.Uri)

이것은 일부 특정 콘텐츠 해결자의 문제점을 극복하기 위해 사용되지 않는 진부한 방법을 가진 오래된 답변입니다.큰 소금과 함께 섭취하고 가능하면 적절한 OpenInputStream API를 사용합니다.

내용 확인기를 사용하여 다음 정보를 얻을 수 있습니다.file://로부터의 경로content://URI:

String filePath = null;
Uri _uri = data.getData();
Log.d("","URI = "+ _uri);                                       
if (_uri != null && "content".equals(_uri.getScheme())) {
    Cursor cursor = this.getContentResolver().query(_uri, new String[] { android.provider.MediaStore.Images.ImageColumns.DATA }, null, null, null);
    cursor.moveToFirst();   
    filePath = cursor.getString(0);
    cursor.close();
} else {
    filePath = _uri.getPath();
}
Log.d("","Chosen path = "+ filePath);

이것을 시도해보세요.

컨텐츠 URI에서 파일 가져오기

fun fileFromContentUri(context: Context, contentUri: Uri): File {
    // Preparing Temp file name
    val fileExtension = getFileExtension(context, contentUri)
    val fileName = "temp_file" + if (fileExtension != null) ".$fileExtension" else ""

    // Creating Temp file
    val tempFile = File(context.cacheDir, fileName)
    tempFile.createNewFile()

    try {
        val oStream = FileOutputStream(tempFile)
        val inputStream = context.contentResolver.openInputStream(contentUri)

        inputStream?.let {
            copy(inputStream, oStream)
        }

        oStream.flush()
    } catch (e: Exception) {
        e.printStackTrace()
    }

    return tempFile
}

private fun getFileExtension(context: Context, uri: Uri): String? {
    val fileType: String? = context.contentResolver.getType(uri)
    return MimeTypeMap.getSingleton().getExtensionFromMimeType(fileType)
}

@Throws(IOException::class)
private fun copy(source: InputStream, target: OutputStream) {
    val buf = ByteArray(8192)
    var length: Int
    while (source.read(buf).also { length = it } > 0) {
        target.write(buf, 0, length)
    }
}

영감을 받은 답변은 제이슨 라브룬과 다스 레이븐입니다.이미 답변한 접근 방식을 시도한 결과 대부분 커서 Null 사례 및 내용://에서 파일://로의 변환을 포함할 수 있는 아래의 솔루션으로 전환되었습니다.

파일을 변환하려면 gain uri에서 파일 읽기 및 쓰기

public static Uri getFilePathFromUri(Uri uri) throws IOException {
    String fileName = getFileName(uri);
    File file = new File(myContext.getExternalCacheDir(), fileName);
    file.createNewFile();
    try (OutputStream outputStream = new FileOutputStream(file);
         InputStream inputStream = myContext.getContentResolver().openInputStream(uri)) {
        FileUtil.copyStream(inputStream, outputStream); //Simply reads input to output stream
        outputStream.flush();
    }
    return Uri.fromFile(file);
}

파일 이름 사용을 위해 커서 Null 대소문자를 포함합니다.

public static String getFileName(Uri uri) {
    String fileName = getFileNameFromCursor(uri);
    if (fileName == null) {
        String fileExtension = getFileExtension(uri);
        fileName = "temp_file" + (fileExtension != null ? "." + fileExtension : "");
    } else if (!fileName.contains(".")) {
        String fileExtension = getFileExtension(uri);
        fileName = fileName + "." + fileExtension;
    }
    return fileName;
}

MIME 유형에서 파일 확장명으로 변환하는 좋은 옵션이 있습니다.

 public static String getFileExtension(Uri uri) {
    String fileType = myContext.getContentResolver().getType(uri);
    return MimeTypeMap.getSingleton().getExtensionFromMimeType(fileType);
}

파일 이름을 가져오는 커서

public static String getFileNameFromCursor(Uri uri) {
    Cursor fileCursor = myContext.getContentResolver().query(uri, new String[]{OpenableColumns.DISPLAY_NAME}, null, null, null);
    String fileName = null;
    if (fileCursor != null && fileCursor.moveToFirst()) {
        int cIndex = fileCursor.getColumnIndex(OpenableColumns.DISPLAY_NAME);
        if (cIndex != -1) {
            fileName = fileCursor.getString(cIndex);
        }
    }
    return fileName;
}

URI 콘텐츠가 있는 경우content://com.externalstorage...Android 19 이상에서 이 방법을 사용하여 폴더 또는 파일의 절대 경로를 얻을 수 있습니다.

public static String getPath(final Context context, final Uri uri) {
    final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;

    // DocumentProvider
    if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) {
        System.out.println("getPath() uri: " + uri.toString());
        System.out.println("getPath() uri authority: " + uri.getAuthority());
        System.out.println("getPath() uri path: " + uri.getPath());

        // ExternalStorageProvider
        if ("com.android.externalstorage.documents".equals(uri.getAuthority())) {
            final String docId = DocumentsContract.getDocumentId(uri);
            final String[] split = docId.split(":");
            final String type = split[0];
            System.out.println("getPath() docId: " + docId + ", split: " + split.length + ", type: " + type);

            // This is for checking Main Memory
            if ("primary".equalsIgnoreCase(type)) {
                if (split.length > 1) {
                    return Environment.getExternalStorageDirectory() + "/" + split[1] + "/";
                } else {
                    return Environment.getExternalStorageDirectory() + "/";
                }
                // This is for checking SD Card
            } else {
                return "storage" + "/" + docId.replace(":", "/");
            }

        }
    }
    return null;
}

다음을 사용하여 URI의 각 부분을 확인할 수 있습니다.printlnSD 카드 및 장치 메인 메모리에 대해 반환된 값은 아래와 같습니다.파일이 메모리에 있는 경우 액세스 및 삭제가 가능하지만, 이 절대 경로를 사용하여 이미지를 읽거나 연 경우에만 SD 카드에서 파일을 삭제할 수 없습니다.이 방법으로 삭제할 수 있는 해결책을 찾으시면 공유 부탁드립니다.

SD 카드

getPath() uri: content://com.android.externalstorage.documents/tree/612E-B7BF%3A/document/612E-B7BF%3A
getPath() uri authority: com.android.externalstorage.documents
getPath() uri path: /tree/612E-B7BF:/document/612E-B7BF:
getPath() docId: 612E-B7BF:, split: 1, type: 612E-B7BF

주 메모리

getPath() uri: content://com.android.externalstorage.documents/tree/primary%3A/document/primary%3A
getPath() uri authority: com.android.externalstorage.documents
getPath() uri path: /tree/primary:/document/primary:
getPath() docId: primary:, split: 1, type: primary

를 URI와 함께 다음과 같이 .file:///를 후에

DocumentFile documentFile = DocumentFile.fromFile(new File(path));
documentFile.getUri() // will return a Uri with file Uri

. 를리URI 니스합 다고려. // 킴ContentResolver.query()그것은 좋은 해결책이 아닙니다. 수 .4.2.2는 HTC Desire에서 NULL을 얻을 수 있습니다.

대신 Content Resolver를 사용하는 것이 어떻습니까?https://stackoverflow.com/a/29141800/3205334

대답이 좀 늦었지만 코드가 테스트되었습니다.

URI에서 체계 확인:

 byte[] videoBytes;

if (uri.getScheme().equals("content")){
        InputStream iStream =   context.getContentResolver().openInputStream(uri);
            videoBytes = getBytes(iStream);
        }else{
            File file = new File(uri.getPath());
            FileInputStream fileInputStream = new FileInputStream(file);     
            videoBytes = getBytes(fileInputStream);
        }

에서 저는 . 위답를나비서는변배만이다바, 그은질관없니습이련과문의 을 보여주기 위해 전체 입니다. 나는 단지 사용법을 보여주기 위해 내 전체 코드를 복사했습니다.FileInputStream그리고.InputStream둘 다 내 코드에서 동일하게 작동하기 때문입니다.

fragment에서는 getActivity()라는 변수 컨텍스트를 사용했고 Activity에서는 단순히 ActivityName입니다.이것.

context=getActivity();//조각포함에

context=ActivityName.this; 중에

당신은 당신에게 조금 더 쉬운 다음 안드로이드 패키지를 사용할 수 있습니다.

https://github.com/Blankj/AndroidUtilCode

위 패키지를 사용하면 코드가 다음과 같을 수 있습니다.

라인 아래에서 사용하기

수입 comblankj.syscode.syscode.sys.Uri Utils;

코드는 다음과 같을 수 있습니다.

File f = UriUtils.uri2File(result);

감사해요.

만약 당신이 절대적으로 확신한다면, 당신의content:URI가 실제 파일을 가리키면 다음과 같은 트릭을 수행할 수 있습니다.

context.contentResolver.openFileDescriptor(uri, "r").use { fileDescriptor ->
    if (fileDescriptor == null) {
        throw NullPointerException("ParcelFileDescriptor from $uri was null")
    }
    val path = "/proc/${android.os.Process.myPid()}/fd/${fileDescriptor.fd}"
    val fileUri = Uri.fromFile(File(path).canonicalFile)
}

서는 다을사용파엽니다일을을 사용하여 .ContentResolver기본 Linux 파일 설명자에 대한 경로를 구성하고 다음을 통해 실제 파일 경로를 확인합니다.canonicalFile.

당신은 간단한 방법으로 uri로 파일 이름을 얻을 수 있습니다.

파일 정보 검색 중

fun get_filename_by_uri(uri : Uri) : String{
    contentResolver.query(uri, null, null, null, null).use { cursor ->
        cursor?.let {
            val nameIndex = it.getColumnIndex(OpenableColumns.DISPLAY_NAME)
            it.moveToFirst()
            return it.getString(nameIndex)
        }
    }
    return ""
}

사용하여 쉽게 읽을 수 있습니다.

contentResolver.openInputStream(uri)

언급URL : https://stackoverflow.com/questions/5657411/android-getting-a-file-uri-from-a-content-uri

반응형