Picasa // Google + 동기화 폴더의 갤러리에서 이미지를 가져올 수 없습니다.
Google+ 동기화 사진의 폴더 중 하나에서 갤러리 앱에서 이미지를 가져 오려고합니다. 이미지를 선택한 후 Uri가 올바르게 다시 전달됩니다. 그러나 저장 장치에서 해당 이미지의 실제 경로를 가져 와서 사용할 수 있도록하면 충돌이 발생합니다. 문제는 구체적으로 picasa 콘텐츠 제공 업체에 있는 것 같습니다 .
Nexus S, Nexus 7 및 기타 기기에서도 테스트되었습니다.
E / AndroidRuntime (14572) : java.lang.RuntimeException : 결과 전달 실패 ResultInfo {who = null, request = 1, result = -1, data = Intent {dat = content : //com.google.android.gallery3d.provider / picasa / item / 5427003652908228690}}
여기서 dat 필드는 Uri를 올바르게 전달하는 것처럼 보이지만 이미지의 위치를 가져 오려고하면 다음 오류와 함께 충돌합니다.
W / GalleryProvider (14381) : 지원되지 않는 열 : _data
Picasa 앨범의 콘텐츠 제공 업체에 _data 필드가없는 것 같습니다.
위치를 가져 오는 코드는 다음과 같습니다.
// imageUri는 위에서 본 Uri입니다. String [] proj = {MediaStore.Images.Media.DATA}; 커서 커서 = context.getContentResolver (). query (imageUri, proj, null, null, null); int column_index = cursor.getColumnIndexOrThrow (MediaStore.Images.Media.DATA); cursor.moveToFirst (); 문자열 filePath = cursor.getString (column_index); cursor.close ();
이 이미지에 대해 지원되는 유일한 열은 다음과 같습니다. [user_account, picasa_id, _display_name, _size, mime_type, datetaken, latitude, longitude, orientation]
이 이미지의 실제 위치를 어떻게 얻습니까? 그리고 우리가이 이미지로 작업하지 않는다면, 이러한 이미지는 처음에 사용자에게 보여서는 안됩니다.
갤러리 앱을 시작하려는 의도는 다음과 같습니다.
의도 의도 = new Intent (); intent.setType ( "이미지 / *"); intent.setAction (Intent.ACTION_GET_CONTENT);
나는 지금 많은 시간을 낭비했고 이제는 특별한 스레드 또는 무언가에서 마술 다운로드없이 모든 경우에서 작동하는 솔루션을 찾았습니다. 다음 메소드는 사용자가 선택한 콘텐츠에서 스트림을 반환하며 이는 야생의 모든 것과 함께 작동합니다.
FileInputStream getSourceStream(Uri u) throws FileNotFoundException {
FileInputStream out = null;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
ParcelFileDescriptor parcelFileDescriptor =
mContext.getContentResolver().openFileDescriptor(u, "r");
FileDescriptor fileDescriptor = parcelFileDescriptor.getFileDescriptor();
out = new FileInputStream(fileDescriptor);
} else {
out = (FileInputStream) mContext.getContentResolver().openInputStream(u);
}
return out;
}
많은 연구 끝에 저는 아주 간단한 일을하기에는 너무 많은 해결 방법이 있다고 느꼈습니다. 그래서 저는 다른 모든 복잡한 것을 처리하고 제가 생각할 수있는 모든 가능한 시나리오에서 작동하는 작은 라이브러리를 작성했습니다. 시도해보고 이것이 도움이되는지 확인하십시오.
http://techdroid.kbeanie.com/2013/03/easy-image-chooser-library-for-android.html
이것은 초기 구현입니다. 거의 모든 상황을 처리하지만 몇 가지 버그가있을 수 있습니다. 이 라이브러리를 사용하는 경우 피드백을 알려 주시고 추가 개선이 필요한 경우 알려주십시오.
나는 약 1 년 전에 같은 문제에 직면했다. 나는 내 해결책을 보여 주었다. (코드는 꽤 지저분하다. 따라서 갤러리에서 반환 된 이미지 URI가 있습니다.
ImageInfo getImage(URI imageUri) {
ImageInfo result = null;
final String[] cursorColumns = {MediaStore.Images.Media.DATA, MediaStore.Images.Media.ORIENTATION};
// some devices (OS versions return an URI of com.android instead of com.google.android
if (imageUri.toString().startsWith("content://com.android.gallery3d.provider")) {
// use the com.google provider, not the com.android provider.
imageUri = Uri.parse(imageUri.toString().replace("com.android.gallery3d","com.google.android.gallery3d"));
}
Cursor cursor = App.getContext().getContentResolver().query(imageUri, cursorColumns, null, null, null);
if (cursor != null) {
int dataColumnIndex = cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA);
int orientationColumnIndex = cursor.getColumnIndex(MediaStore.Images.ImageColumns.ORIENTATION);
cursor.moveToFirst();
// if it is a picasa image on newer devices with OS 3.0 and up
if (imageUri.toString().startsWith("content://com.google.android.gallery3d")) {
result = new ImageInfo(downloadImage(imageUri), "0");
} else { // it is a regular local image file
result = new ImageInfo(cursor.getString(dataColumnIndex), cursor.getString(orientationColumnIndex));
}
cursor.close();
} else {
result = new ImageInfo(downloadImage(imageUri), "0");
}
return result;
}
이제 이미지를 다운로드하는 기능이 필요합니다.
private String downloadImage(URI imageUri) {
File cacheDir;
// if the device has an SD card
if (android.os.Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED)) {
cacheDir = new File(android.os.Environment.getExternalStorageDirectory(),".OCFL311");
} else {
// it does not have an SD card
cacheDir = App.getContext().getCacheDir();
}
if(!cacheDir.exists()) cacheDir.mkdirs();
File f = new File(cacheDir, PUT_HERE_FILE_NAME_TO_STORE_IMAGE);
try {
InputStream is = null;
if (imageUri.toString().startsWith("content://com.google.android.gallery3d")) {
is = App.getContext().getContentResolver().openInputStream(imageUri);
} else {
is = new URL(imageUri.toString()).openStream();
}
OutputStream os = new FileOutputStream(f);
Utils.InputToOutputStream(is, os);
return f.getAbsolutePath();
} catch (Exception ex) {
Log.d(this.getClass().getName(), "Exception: " + ex.getMessage());
// something went wrong
ex.printStackTrace();
return null;
}
}
ImageInfo는 이미지 경로와 방향을 저장하는 클래스입니다.
public static class ImageInfo {
public final String filePath;
public final String imageOrientation;
public ImageInfo(String filePath, String imageOrientation) {
this.filePath = filePath;
if (imageOrientation == null) imageOrientation = "0";
this.imageOrientation = imageOrientation;
}
}
@drindt 답변에 따라 아래 코드 File
는 Google 포토 클라우드 동기화되었지만 장치에없는 파일에서 다운로드 한 임시 경로를 제공 합니다.
@SuppressLint("NewApi")
public static String getFilePath(final Context context, final Uri uri) {
// Google photo uri example
// content://com.google.android.apps.photos.contentprovider/0/1/mediakey%3A%2FAF1QipMObgoK_wDY66gu0QkMAi/ORIGINAL/NONE/114919
if ("content".equalsIgnoreCase(uri.getScheme())) {
String result = getDataColumn(context, uri, null, null); //
if (TextUtils.isEmpty(result))
if (uri.getAuthority().contains("com.google.android")) {
try {
File localFile = createImageFile(context, null);
FileInputStream remoteFile = getSourceStream(context, uri);
if(copyToFile(remoteFile, localFile))
result = localFile.getAbsolutePath();
remoteFile.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return result;
}
// 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.
*/
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;
}
/**
* Copy data from a source stream to destFile.
* Return true if succeed, return false if failed.
*/
private static boolean copyToFile(InputStream inputStream, File destFile) {
if (inputStream == null || destFile == null) return false;
try {
OutputStream out = new FileOutputStream(destFile);
try {
byte[] buffer = new byte[4096];
int bytesRead;
while ((bytesRead = inputStream.read(buffer)) >= 0) {
out.write(buffer, 0, bytesRead);
}
} finally {
out.close();
}
return true;
} catch (IOException e) {
return false;
}
}
public static String getTimestamp() {
try {
return new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.ROOT).format(new Date());
} catch (RuntimeException e) {
return new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.getDefault()).format(new Date());
}
}
public static File createImageFile(Context context, String imageFileName) throws IOException {
if (TextUtils.isEmpty(imageFileName))
imageFileName = getTimestamp(); // make random filename if you want.
final File root;
imageFileName = imageFileName;
root = context.getExternalCacheDir();
if (root != null && !root.exists())
root.mkdirs();
return new File(root, imageFileName);
}
public static FileInputStream getSourceStream(Context context, Uri u) throws FileNotFoundException {
FileInputStream out = null;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
ParcelFileDescriptor parcelFileDescriptor =
context.getContentResolver().openFileDescriptor(u, "r");
FileDescriptor fileDescriptor = null;
if (parcelFileDescriptor != null) {
fileDescriptor = parcelFileDescriptor.getFileDescriptor();
out = new FileInputStream(fileDescriptor);
}
} else {
out = (FileInputStream) context.getContentResolver().openInputStream(u);
}
return out;
}
아래 트릭이 나를 위해 일했습니다. 여기서 제가하는 일은 URI에 권한 URL이 있으면 아래 코드를 사용하여 임시 이미지를 만들고 동일한 콘텐츠 URI를 반환하는 것입니다.
public static String getImageUrlWithAuthority(Context context, Uri uri) {
InputStream is = null;
if (uri.getAuthority() != null) {
try {
is = context.getContentResolver().openInputStream(uri);
Bitmap bmp = BitmapFactory.decodeStream(is);
return writeToTempImageAndGetPathUri(context, bmp).toString();
} catch (FileNotFoundException e) {
e.printStackTrace();
}finally {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return null;
}
public static Uri writeToTempImageAndGetPathUri(Context inContext, Bitmap inImage) {
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
inImage.compress(Bitmap.CompressFormat.JPEG, 100, bytes);
String path = MediaStore.Images.Media.insertImage(inContext.getContentResolver(), inImage, "Title", null);
return Uri.parse(path);
}
나는이 접근 방식을 사용했고, 나를 위해 잘 작동하며, 이것이 당신을 도울 수 있기를 바랍니다 ....
ACTIVITYRESULT_CHOOSEPICTURE는 startActivity (intent, requestCode)를 호출 할 때 사용하는 int입니다.
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if(requestCode == ACTIVITYRESULT_CHOOSEPICTURE) {
BitmapFactory.Options options = new BitmapFactory.Options();
final InputStream ist = ontext.getContentResolver().openInputStream(intent.getData());
final Bitmap bitmap = BitmapFactory.decodeStream(ist, null, options);
ist.close();
}
}
위의 코드가이 링크를 참조하는 것보다 작동하지 않는다면 ...
마지막으로 고전적인 솔루션으로 끝났습니다 ... 모든 권한을 다루는 Document.util을 사용하여 : -1-onActivityResult () 내부 :-
case GALLERY_CAPTURE_IMAGE_REQUEST_CODE:
String filePath = DocumentUtils.getPath(MainContainerActivity.this,data.getData();
break;
2- 클래스 DocumentUtils 만들기 :-
public class DocumentUtils {
@TargetApi(Build.VERSION_CODES.KITKAT)
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 the remote address
String url;
if (isGooglePhotosUri(uri)) {
url = getDataColumnWithAuthority(context, uri, null, null);
return getDataColumn(context, Uri.parse(url), null, null);
}
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;
}
/**
* Function for fixing synced folder image picking bug
*
* **/
public static String getDataColumnWithAuthority(Context context, Uri uri, String selection, String[] selectionArgs) {
Bitmap bitmap = null;
InputStream is = null;
if (uri.getAuthority()!=null){
try {
is = context.getContentResolver().openInputStream(uri);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
Bitmap bmp = BitmapFactory.decodeStream(is);
return ImageLoader.getImageUri(context,bmp).toString();
}
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());
}
/**
* @param uri The Uri to check.
* @return Whether the Uri authority is Google Photos.
*/
public static boolean isGooglePhotosUri(Uri uri) {
if(uri.getAuthority()!=null)
return true;
return false;
}
}
3- 또한 ImageLoader.java에 다음 기능이 필요합니다.
public static Uri getImageUri(Context inContext, Bitmap inImage) {
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
inImage.compress(Bitmap.CompressFormat.JPEG, 100, bytes);
String path = MediaStore.Images.Media.insertImage(inContext.getContentResolver(), inImage, "Title", null);
return Uri.parse(path);
}
'programing' 카테고리의 다른 글
큰 카디널리티 계산을위한 LogLog 및 HyperLogLog 알고리즘 (0) | 2020.12.13 |
---|---|
std :: multiset에는 요소가 발견되면 하나의 샘플 (단일화 또는 복제) 만 지우는 함수 또는 알고리즘이 있습니다. (0) | 2020.12.13 |
상태 저장 서비스를 사용할시기와 Azure Service Fabric의 외부 지속성에 의존하는시기 이해 (0) | 2020.12.13 |
Android 페이지 말림 애니메이션 (0) | 2020.12.13 |
Xcode 8 iOS 10 논스톱 기기 로그 (0) | 2020.12.13 |