Android 4.4에서 content : // URI를 실제 경로로 변환
Android 4.4에서 startActivityForResult()
"최근", "이미지", "다운로드"및 선택할 수있는 여러 앱이있는 "열기 위치"라는 제목의 활동 을 불러오는 호출을 제외하고는 잘 작동하는 솔루션 (아래 참조)을 시도했습니다. . "이미지"를 선택하고 반환 된 콘텐츠 URI (아래 코드 사용)를 확인하려고하면 호출이 cursor.getString()
null 을 반환합니다. 갤러리 앱을 사용하여 똑같은 파일을 선택하면 cursor.getString()
파일 경로를 반환합니다. 저는 API 레벨 16과 19에서만 이것을 테스트했습니다. 모든 것이 16에서 예상대로 작동합니다. 19가되면 갤러리 나 다른 앱을 선택해야합니다. 그렇지 않으면 작동하지 않습니다.
private String getRealPathFromURI(Context context, Uri contentUri) {
Cursor cursor = null;
try {
String[] proj = { MediaStore.Images.Media.DATA };
cursor = context.getContentResolver().query(contentUri, proj, null, null, null);
int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
cursor.moveToFirst();
String path = cursor.getString(column_index);
return path;
} finally {
if (cursor != null) {
cursor.close();
}
}
}
이렇게하면 MediaProvider, DownloadsProvider 및 ExternalStorageProvider에서 파일 경로를 가져 오면서 언급 한 비공식 ContentProvider 메서드로 돌아갑니다.
/**
* Get a file path from a Uri. This will get the the path for Storage Access
* Framework Documents, as well as the _data field for the MediaStore and
* other file-based ContentProviders.
*
* @param context The context.
* @param uri The Uri to query.
* @author paulburke
*/
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)) {
// ExternalStorageProvider
if (isExternalStorageDocument(uri)) {
final String docId = DocumentsContract.getDocumentId(uri);
final String[] split = docId.split(":");
final String type = split[0];
if ("primary".equalsIgnoreCase(type)) {
return Environment.getExternalStorageDirectory() + "/" + split[1];
}
// TODO handle non-primary volumes
}
// DownloadsProvider
else if (isDownloadsDocument(uri)) {
final String id = DocumentsContract.getDocumentId(uri);
final Uri contentUri = ContentUris.withAppendedId(
Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));
return getDataColumn(context, contentUri, null, null);
}
// MediaProvider
else if (isMediaDocument(uri)) {
final String docId = DocumentsContract.getDocumentId(uri);
final String[] split = docId.split(":");
final String type = split[0];
Uri contentUri = null;
if ("image".equals(type)) {
contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
} else if ("video".equals(type)) {
contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
} else if ("audio".equals(type)) {
contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
}
final String selection = "_id=?";
final String[] selectionArgs = new String[] {
split[1]
};
return getDataColumn(context, contentUri, selection, selectionArgs);
}
}
// MediaStore (and general)
else if ("content".equalsIgnoreCase(uri.getScheme())) {
return getDataColumn(context, uri, null, null);
}
// File
else if ("file".equalsIgnoreCase(uri.getScheme())) {
return uri.getPath();
}
return null;
}
/**
* Get the value of the data column for this Uri. This is useful for
* MediaStore Uris, and other file-based ContentProviders.
*
* @param context The context.
* @param uri The Uri to query.
* @param selection (Optional) Filter used in the query.
* @param selectionArgs (Optional) Selection arguments used in the query.
* @return The value of the _data column, which is typically a file path.
*/
public static String getDataColumn(Context context, Uri uri, String selection,
String[] selectionArgs) {
Cursor cursor = null;
final String column = "_data";
final String[] projection = {
column
};
try {
cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs,
null);
if (cursor != null && cursor.moveToFirst()) {
final int column_index = cursor.getColumnIndexOrThrow(column);
return cursor.getString(column_index);
}
} finally {
if (cursor != null)
cursor.close();
}
return null;
}
/**
* @param uri The Uri to check.
* @return Whether the Uri authority is ExternalStorageProvider.
*/
public static boolean isExternalStorageDocument(Uri uri) {
return "com.android.externalstorage.documents".equals(uri.getAuthority());
}
/**
* @param uri The Uri to check.
* @return Whether the Uri authority is DownloadsProvider.
*/
public static boolean isDownloadsDocument(Uri uri) {
return "com.android.providers.downloads.documents".equals(uri.getAuthority());
}
/**
* @param uri The Uri to check.
* @return Whether the Uri authority is MediaProvider.
*/
public static boolean isMediaDocument(Uri uri) {
return "com.android.providers.media.documents".equals(uri.getAuthority());
}
Android 4.4에서 content : // URI를 실제 경로로 변환
Android 버전에서이 작업을 수행하는 신뢰할 수있는 방법은 없습니다. A content://
Uri
는 액세스 할 수있는 파일은 물론 파일 시스템의 파일을 나타낼 필요가 없습니다.
저장소 프레임 워크를 제공하기위한 Android 4.4의 변경 사항은 단순히 content://
Uri
값 을 접하는 빈도를 증가시킵니다 .
를 받으면 content://
Uri
및와 ContentResolver
같은 openInputStream()
및 방법을 사용하여 소비하십시오 openOutputStream()
.
저도이 문제에 직면했지만 제 경우에는 갤러리에 구체적인 Uri를 지정하여 나중에 자르기를 사용할 수 있도록하는 것이 었습니다. KitKat의 새로운 문서 브라우저에서는 탐색 창에서 갤러리를 선택하고 말했듯이 거기에서 직접 이미지 나 파일을 열지 않는 한 더 이상 할 수 없습니다.
Uri의 경우 문서 브라우저에서 열 때 경로를 검색 할 수 있습니다.
Intent dataIntent= new Intent(Intent.ACTION_GET_CONTENT);
dataIntent.setType("image/*"); //Or whatever type you need
그리고 onActivityResult에서 :
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == ACTIVITY_SELECT_IMAGE && resultCode == RESULT_OK) {
myUri = data.getData();
String path = myUri.getPath();
openPath(myUri);
}
}
해당 경로로 파일을 열어야하는 경우 Content Resolver를 사용하면됩니다.
public void openPath(Uri uri){
InputStream is = null;
try {
is = getContentResolver().openInputStream(uri);
//Convert your stream to data here
is.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
Google API에 도입되었습니다 . 이것을 시도 할 수 있습니다.
private Bitmap getBitmapFromUri(Uri uri) throws IOException {
ParcelFileDescriptor parcelFileDescriptor =
getContentResolver().openFileDescriptor(uri, "r");
FileDescriptor fileDescriptor = parcelFileDescriptor.getFileDescriptor();
Bitmap image = BitmapFactory.decodeFileDescriptor(fileDescriptor);
parcelFileDescriptor.close();
return image;
}
정말로 파일 경로가 필요한 경우. 먼저 ContentResolver를 사용하여 데이터를 가져옵니다. 그런 다음 데이터를 임시 파일에 저장하고 해당 경로를 사용할 수 있습니다.
(함수 매개 변수에 File 객체가있는 라이브러리를 사용해야했습니다.)
@FireBear 덕분에 이제 대답을 수정하여 미디어 파일 경로를 얻습니다.
문자열 filePath = saveBitmap (activity, getBitmapFromUri (imageUri), "tmpFile"). getPath ();
private Bitmap getBitmapFromUri(Context context, Uri uri) throws IOException {
ParcelFileDescriptor parcelFileDescriptor =
context.getContentResolver().openFileDescriptor(uri, "r");
FileDescriptor fileDescriptor = parcelFileDescriptor.getFileDescriptor();
Bitmap image = BitmapFactory.decodeFileDescriptor(fileDescriptor);
parcelFileDescriptor.close();
return image;
}
private File saveBitmap(Context context, Bitmap bitmap, String name) {
File filesDir = context.getFilesDir();
File imageFile = new File(filesDir, name + ".jpg");
OutputStream os;
try {
os = new FileOutputStream(imageFile);
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, os);
os.flush();
os.close();
} catch (Exception e) {
//Log.e(getClass().getSimpleName(), "Error writing bitmap", e);
}
return imageFile;
}
Uri에서 파일 경로 가져 오기 : -Storage Access Framework Documents 경로 와 MediaStore 및 기타 파일 기반 ContentProviders에 대한 _data 필드를 가져올 Util 클래스를 만들었습니다 .
ConvertUriToFilePath :-
import android.content.ContentUris;
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
import android.provider.DocumentsContract;
import android.provider.MediaStore;
import android.support.annotation.RequiresApi;
public class ConvertUriToFilePath {
/**
* Get a file path from a Uri. This will get the the path for Storage Access
* Framework Documents, as well as the _data field for the MediaStore and
* other file-based ContentProviders.
*
* @param context The context.
* @param uri The Uri to query.
*/
@RequiresApi(api = Build.VERSION_CODES.KITKAT)
public static String getPathFromURI(final Context context, final Uri uri) {
final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;
// DocumentProvider
if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) {
// ExternalStorageProvider
if (isExternalStorageDocument(uri)) {
final String docId = DocumentsContract.getDocumentId(uri);
final String[] split = docId.split(":");
final String type = split[0];
if ("primary".equalsIgnoreCase(type)) {
return Environment.getExternalStorageDirectory() + "/" + split[1];
}
// TODO handle non-primary volumes
}
// DownloadsProvider
else if (isDownloadsDocument(uri)) {
final String id = DocumentsContract.getDocumentId(uri);
final Uri contentUri = ContentUris.withAppendedId(
Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));
return getDataColumn(context, contentUri, null, null);
}
// MediaProvider
else if (isMediaDocument(uri)) {
final String docId = DocumentsContract.getDocumentId(uri);
final String[] split = docId.split(":");
final String type = split[0];
Uri contentUri = null;
if ("image".equals(type)) {
contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
} else if ("video".equals(type)) {
contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
} else if ("audio".equals(type)) {
contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
}
final String selection = "_id=?";
final String[] selectionArgs = new String[]{
split[1]
};
return getDataColumn(context, contentUri, selection, selectionArgs);
}
}
// MediaStore (and general)
else if ("content".equalsIgnoreCase(uri.getScheme())) {
final String docId = DocumentsContract.getDocumentId(uri);
final String[] split = docId.split(":");
final String type = split[0];
Uri contentUri = null;
if ("image".equals(type)) {
contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
} else if ("video".equals(type)) {
contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
} else if ("audio".equals(type)) {
contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
}
final String selection = "_id=?";
final String[] selectionArgs = new String[]{
split[1]
};
return getDataColumn(context, contentUri, selection, selectionArgs);
// return getDataColumn(context, uri, null, null);
}
// File
else if ("file".equalsIgnoreCase(uri.getScheme())) {
return uri.getPath();
}
return null;
}
/**
* Get the value of the data column for this Uri. This is useful for
* MediaStore Uris, and other file-based ContentProviders.
*
* @param context The context.
* @param uri The Uri to query.
* @param selection (Optional) Filter used in the query.
* @param selectionArgs (Optional) Selection arguments used in the query.
* @return The value of the _data column, which is typically a file path.
*/
public static String getDataColumn(Context context, Uri uri, String selection,
String[] selectionArgs) {
Cursor cursor = null;
final String column = "_data";
final String[] projection = {
column
};
try {
cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs,
null);
if (cursor != null && cursor.moveToFirst()) {
final int column_index = cursor.getColumnIndexOrThrow(column);
return cursor.getString(column_index);
}
} finally {
if (cursor != null)
cursor.close();
}
return null;
}
/**
* @param uri The Uri to check.
* @return Whether the Uri authority is ExternalStorageProvider.
*/
public static boolean isExternalStorageDocument(Uri uri) {
return "com.android.externalstorage.documents".equals(uri.getAuthority());
}
/**
* @param uri The Uri to check.
* @return Whether the Uri authority is DownloadsProvider.
*/
public static boolean isDownloadsDocument(Uri uri) {
return "com.android.providers.downloads.documents".equals(uri.getAuthority());
}
/**
* @param uri The Uri to check.
* @return Whether the Uri authority is MediaProvider.
*/
public static boolean isMediaDocument(Uri uri) {
return "com.android.providers.media.documents".equals(uri.getAuthority());
}
}
예제 코드 :
// Just call this function of ConvertUriToFilePath class and it will return full path of file URI.
String actualFilepath= ConvertUriToFilePath.getPathFromURI(activity,tempUri);
참고 URL : https://stackoverflow.com/questions/19985286/convert-content-uri-to-actual-path-in-android-4-4
'code' 카테고리의 다른 글
심볼릭 링크를 먼저 삭제하지 않고 편집하는 방법이 있습니까? (0) | 2020.12.04 |
---|---|
부트 스트랩에서 '필수'필드 정의 (0) | 2020.12.03 |
Flask는 템플릿 파일이 존재하더라도 TemplateNotFound 오류를 발생시킵니다. (0) | 2020.12.03 |
Objective-C를 사용하여 프로그래밍 방식으로 텍스트 파일 읽기 (0) | 2020.12.03 |
Git 사전 커밋 후크 : 변경 / 추가 된 파일 (0) | 2020.12.03 |