从图库中选择图像或 Google 张照片失败
Pick Image From Gallery Or Google Photos Failing
编辑: 我想更新真正的问题所在。在三星 phone 上,您有 "Gallery",在 "Gallery" 中,您还可以看到 google 照片备份。这是我要拍摄的照片 selection。现在在其他应用程序 (Close5) 上,他们只是显示一条消息,说明
"That photo is not supported"。但为什么?为什么我们不能让这个 url (https://lh3.googleusercontent) 工作?
E/BitmapFactory: Unable to decode stream:
java.io.FileNotFoundException:
/https:/lh3.googleusercontent.com/-Llgk8Mqk-rI/U8LK0SMnpWI/AAAAAAAAFk4/0cktb59DnL8GgblJ-IJIUBDuP9MQXCBPACHM/I/IMG_20140711_085012.jpg:
open failed: ENOENT (No such file or directory)
大家可以清楚的看到这是一张真实的照片url:
https:/lh3.googleusercontent.com/-Llgk8Mqk-rI/U8LK0SMnpWI/AAAAAAAAFk4/0cktb59DnL8GgblJ-IJIUBDuP9MQXCBPACHM/I/IMG_20140711_085012.jpg
一切正常,直到我从照片或 google 照片图像而不是从图库转到 select,我尝试处理异常 (Sorry, that image isn't supported. Try another gallery!
),但这似乎不完整.我尝试查看此处的其他解决方案,但其中 none 对 google 照片有效。谢谢!
错误是空指针:
app E/BitmapFactory: Unable to decode stream:
java.io.FileNotFoundException: /https:/lh3.googleusercontent
@Override
public void onActivityResult(int requestCode, int resultCode,
Intent data) {
if (resultCode != Activity.RESULT_CANCELED) {
if (requestCode == 1) {
try{
String selectedImagePath = getAbsolutePath(data.getData()); ((PostAdParentTabHost)getActivity()).getMap_of_picture_paths().put(1, selectedImagePath);
post_ad_camera_img_1.setImageBitmap(decodeSampledBitmapFromFileToCustomSize(selectedImagePath, 150, 150));
animation_master.fade(post_ad_camera_img_1);
}catch(Exception e){
e.printStackTrace();
((PostAdParentTabHost)getActivity()).getMap_of_picture_paths().remove(requestCode);
Toast.makeText(getActivity(), "Sorry, that image isn't supported. Try another gallery! ", Toast.LENGTH_SHORT).show();
}
//------------------------------------------------------Methods:
public String getAbsolutePath(Uri uri) {
Uri final_uri = uri;
if (uri.getLastPathSegment().contains("googleusercontent.com")){
final_uri = getImageUrlWithAuthority(getActivity(), uri);
String[] projection = { MediaStore.MediaColumns.DATA };
Cursor cursor = getActivity().getContentResolver().query(final_uri, projection, null, null, null);
if (cursor != null) {
int column_index = cursor
.getColumnIndexOrThrow(MediaStore.MediaColumns.DATA);
cursor.moveToFirst();
return cursor.getString(column_index);
}else{
return null;
}
}else{
String[] projection = { MediaStore.MediaColumns.DATA };
Cursor cursor = getActivity().getContentResolver().query(final_uri, projection, null, null, null);
if (cursor != null) {
int column_index = cursor
.getColumnIndexOrThrow(MediaStore.MediaColumns.DATA);
cursor.moveToFirst();
return cursor.getString(column_index);
}else{
return null;
}
}
public static Uri 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);
} 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);
}
public Uri setImageUri() {
// Store image in dcim
File file = new File(Environment.getExternalStorageDirectory()
+ "/DCIM/", "image" + new Date().getTime() + ".png");
Uri imgUri = Uri.fromFile(file);
this.image_as_uri_for_parcel = imgUri;
this.imgPath = file.getAbsolutePath();
return imgUri;
}
我没有看到正在创建 Cursor 对象以从 Gallery 中选取图像,试试这个代码
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
callbackManager.onActivityResult(requestCode, resultCode, data);
super.onActivityResult(requestCode, resultCode, data);
//FROM CAMERA
if (requestCode == 1) {
if (resultCode == getActivity().RESULT_OK) {
Bitmap bp = (Bitmap) data.getExtras().get("data");
File fileDirectory = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/Documents/Images/");
}
//FROM GALLERY
else
if (resultCode == getActivity().RESULT_OK && RESULT_LOAD_IMG == 2) {
{
File fileDirectory = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/Documents/TWINE/");
Uri selectedImage = data.getData();
String[] filePathColumn = {MediaStore.Images.Media.DATA};
// Get the cursor
Cursor cursor = AppController.getInstance().getContentResolver().query(selectedImage,
filePathColumn, null, null, null);
// Move to first row
cursor.moveToFirst();
int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
String imgDecodableString = cursor.getString(columnIndex);
File fileGallery = new File(imgDecodableString);
Bitmap bitmap = BitmapFactory.decodeFile(fileGallery.getAbsolutePath());
cursor.close();
// Set the Image in ImageView after decoding the String
Log.d("Bitmap", "Bit");
imageName = UUID.randomUUID().toString() + ".JPG";
imagePath = fileDirectory + "/" + imageName;
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 50, baos);
byte[] b = baos.toByteArray();
File file = new File(fileDirectory, imageName);
try {
FileOutputStream out = new FileOutputStream(file);
out.write(b);
out.flush();
out.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
让用户选择选项的对话框:
private void selectImage() {
final CharSequence[] items = { "Take Photo", "Choose from Gallery", "Cancel" };
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setTitle("Add Photo!");
builder.setItems(items, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int item) {
if (items[item].equals("Take Photo")) {
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(intent, 1);
} else if (items[item].equals("Choose from Gallery")) {
Intent galleryIntent = new Intent(Intent.ACTION_PICK,
android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
// Start the Intent
startActivityForResult(galleryIntent, RESULT_LOAD_IMG);
} else if (items[item].equals("Cancel")) {
dialog.dismiss();
}
}
});
builder.show();
}
Uri 可能是这样的content://com.google.android.apps.photos.content/0/https%3A%2F%2Flh3.googleusercontent.com%2FL-3Jm0TaSqnuKkitli5mK0-d
& 它不是您的本地设备。本地设备的 Uri 会像这样
内容://media/external/images/media/49518
由于这种差异,您的 uriToPath(Uri uri) 返回 null。
所以首先检查 Uri 并相应地从本地设备或服务器获取图像。
您可以使用 DocumentsProvider 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;
}
但是如果您在“照片”应用中有一些本地照片,那么在选择这些照片时您将获得本地 Uri,这将为您提供正确的文件路径。
您还可以在“照片”应用本身中下载照片(在 Google 服务器上)并稍后使用。
来源:
- Android: Error upload image in different android versions
我在使用 google 照片应用选择和裁剪图像时遇到问题。
我这样解决了这个问题
private void pickUserImage() {
if (doHavePermission()) {
Intent photoPickerIntent = new Intent(Intent.ACTION_PICK,
android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
photoPickerIntent.setType("image/*");
photoPickerIntent.putExtra("crop", "true");
photoPickerIntent.putExtra("scale", true);
photoPickerIntent.putExtra("outputX", 256);
photoPickerIntent.putExtra("outputY", 256);
photoPickerIntent.putExtra("aspectX", 1);
photoPickerIntent.putExtra("aspectY", 1);
photoPickerIntent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString());
photoPickerIntent.putExtra(MediaStore.EXTRA_OUTPUT, getTempUri());
startActivityForResult(photoPickerIntent, PICK_FROM_GALLERY);
}
}
在 Whosebug post
中找到我的完整解决方案 here
Try getPathFromInputStreamUri()
, this will fix the content uri problem from google photo app
Kotlin (UPDATED)
fun getPathFromInputStreamUri(context: Context, uri: Uri): String? {
var filePath: String? = null
uri.authority?.let {
try {
context.contentResolver.openInputStream(uri).use {
val photoFile: File? = createTemporalFileFrom(it)
filePath = photoFile?.path
}
} catch (e: FileNotFoundException) {
e.printStackTrace()
} catch (e: IOException) {
e.printStackTrace()
}
}
return filePath
}
@Throws(IOException::class)
private fun createTemporalFileFrom(inputStream: InputStream?): File? {
var targetFile: File? = null
return if (inputStream == null) targetFile
else {
var read: Int
val buffer = ByteArray(8 * 1024)
targetFile = createTemporalFile()
FileOutputStream(targetFile).use { out ->
while (inputStream.read(buffer).also { read = it } != -1) {
out.write(buffer, 0, read)
}
out.flush()
}
targetFile
}
}
private fun createTemporalFile(): File = File(getDefaultDirectory(), "tempPicture.jpg")
Java
public static String getPathFromInputStreamUri(Context context, Uri uri) {
InputStream inputStream = null;
String filePath = null;
if (uri.getAuthority() != null) {
try {
inputStream = context.getContentResolver().openInputStream(uri);
File photoFile = createTemporalFileFrom(inputStream);
filePath = photoFile.getPath();
} catch (FileNotFoundException e) {
Logger.printStackTrace(e);
} catch (IOException e) {
Logger.printStackTrace(e);
} finally {
try {
if (inputStream != null) {
inputStream.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
return filePath;
}
private static File createTemporalFileFrom(InputStream inputStream) throws IOException {
File targetFile = null;
if (inputStream != null) {
int read;
byte[] buffer = new byte[8 * 1024];
targetFile = createTemporalFile();
OutputStream outputStream = new FileOutputStream(targetFile);
while ((read = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, read);
}
outputStream.flush();
try {
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return targetFile;
}
private static File createTemporalFile() {
return new File(Utils.getDefaultDirectory(), "tempPicture.jpg");
}
编辑: 我想更新真正的问题所在。在三星 phone 上,您有 "Gallery",在 "Gallery" 中,您还可以看到 google 照片备份。这是我要拍摄的照片 selection。现在在其他应用程序 (Close5) 上,他们只是显示一条消息,说明 "That photo is not supported"。但为什么?为什么我们不能让这个 url (https://lh3.googleusercontent) 工作?
E/BitmapFactory: Unable to decode stream: java.io.FileNotFoundException: /https:/lh3.googleusercontent.com/-Llgk8Mqk-rI/U8LK0SMnpWI/AAAAAAAAFk4/0cktb59DnL8GgblJ-IJIUBDuP9MQXCBPACHM/I/IMG_20140711_085012.jpg: open failed: ENOENT (No such file or directory)
大家可以清楚的看到这是一张真实的照片url:
https:/lh3.googleusercontent.com/-Llgk8Mqk-rI/U8LK0SMnpWI/AAAAAAAAFk4/0cktb59DnL8GgblJ-IJIUBDuP9MQXCBPACHM/I/IMG_20140711_085012.jpg
一切正常,直到我从照片或 google 照片图像而不是从图库转到 select,我尝试处理异常 (Sorry, that image isn't supported. Try another gallery!
),但这似乎不完整.我尝试查看此处的其他解决方案,但其中 none 对 google 照片有效。谢谢!
错误是空指针:
app E/BitmapFactory: Unable to decode stream: java.io.FileNotFoundException: /https:/lh3.googleusercontent
@Override
public void onActivityResult(int requestCode, int resultCode,
Intent data) {
if (resultCode != Activity.RESULT_CANCELED) {
if (requestCode == 1) {
try{
String selectedImagePath = getAbsolutePath(data.getData()); ((PostAdParentTabHost)getActivity()).getMap_of_picture_paths().put(1, selectedImagePath);
post_ad_camera_img_1.setImageBitmap(decodeSampledBitmapFromFileToCustomSize(selectedImagePath, 150, 150));
animation_master.fade(post_ad_camera_img_1);
}catch(Exception e){
e.printStackTrace();
((PostAdParentTabHost)getActivity()).getMap_of_picture_paths().remove(requestCode);
Toast.makeText(getActivity(), "Sorry, that image isn't supported. Try another gallery! ", Toast.LENGTH_SHORT).show();
}
//------------------------------------------------------Methods:
public String getAbsolutePath(Uri uri) {
Uri final_uri = uri;
if (uri.getLastPathSegment().contains("googleusercontent.com")){
final_uri = getImageUrlWithAuthority(getActivity(), uri);
String[] projection = { MediaStore.MediaColumns.DATA };
Cursor cursor = getActivity().getContentResolver().query(final_uri, projection, null, null, null);
if (cursor != null) {
int column_index = cursor
.getColumnIndexOrThrow(MediaStore.MediaColumns.DATA);
cursor.moveToFirst();
return cursor.getString(column_index);
}else{
return null;
}
}else{
String[] projection = { MediaStore.MediaColumns.DATA };
Cursor cursor = getActivity().getContentResolver().query(final_uri, projection, null, null, null);
if (cursor != null) {
int column_index = cursor
.getColumnIndexOrThrow(MediaStore.MediaColumns.DATA);
cursor.moveToFirst();
return cursor.getString(column_index);
}else{
return null;
}
}
public static Uri 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);
} 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);
}
public Uri setImageUri() {
// Store image in dcim
File file = new File(Environment.getExternalStorageDirectory()
+ "/DCIM/", "image" + new Date().getTime() + ".png");
Uri imgUri = Uri.fromFile(file);
this.image_as_uri_for_parcel = imgUri;
this.imgPath = file.getAbsolutePath();
return imgUri;
}
我没有看到正在创建 Cursor 对象以从 Gallery 中选取图像,试试这个代码
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
callbackManager.onActivityResult(requestCode, resultCode, data);
super.onActivityResult(requestCode, resultCode, data);
//FROM CAMERA
if (requestCode == 1) {
if (resultCode == getActivity().RESULT_OK) {
Bitmap bp = (Bitmap) data.getExtras().get("data");
File fileDirectory = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/Documents/Images/");
}
//FROM GALLERY
else
if (resultCode == getActivity().RESULT_OK && RESULT_LOAD_IMG == 2) {
{
File fileDirectory = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/Documents/TWINE/");
Uri selectedImage = data.getData();
String[] filePathColumn = {MediaStore.Images.Media.DATA};
// Get the cursor
Cursor cursor = AppController.getInstance().getContentResolver().query(selectedImage,
filePathColumn, null, null, null);
// Move to first row
cursor.moveToFirst();
int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
String imgDecodableString = cursor.getString(columnIndex);
File fileGallery = new File(imgDecodableString);
Bitmap bitmap = BitmapFactory.decodeFile(fileGallery.getAbsolutePath());
cursor.close();
// Set the Image in ImageView after decoding the String
Log.d("Bitmap", "Bit");
imageName = UUID.randomUUID().toString() + ".JPG";
imagePath = fileDirectory + "/" + imageName;
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 50, baos);
byte[] b = baos.toByteArray();
File file = new File(fileDirectory, imageName);
try {
FileOutputStream out = new FileOutputStream(file);
out.write(b);
out.flush();
out.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
让用户选择选项的对话框:
private void selectImage() {
final CharSequence[] items = { "Take Photo", "Choose from Gallery", "Cancel" };
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setTitle("Add Photo!");
builder.setItems(items, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int item) {
if (items[item].equals("Take Photo")) {
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(intent, 1);
} else if (items[item].equals("Choose from Gallery")) {
Intent galleryIntent = new Intent(Intent.ACTION_PICK,
android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
// Start the Intent
startActivityForResult(galleryIntent, RESULT_LOAD_IMG);
} else if (items[item].equals("Cancel")) {
dialog.dismiss();
}
}
});
builder.show();
}
Uri 可能是这样的content://com.google.android.apps.photos.content/0/https%3A%2F%2Flh3.googleusercontent.com%2FL-3Jm0TaSqnuKkitli5mK0-d
& 它不是您的本地设备。本地设备的 Uri 会像这样
内容://media/external/images/media/49518
由于这种差异,您的 uriToPath(Uri uri) 返回 null。
所以首先检查 Uri 并相应地从本地设备或服务器获取图像。
您可以使用 DocumentsProvider 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;
}
但是如果您在“照片”应用中有一些本地照片,那么在选择这些照片时您将获得本地 Uri,这将为您提供正确的文件路径。
您还可以在“照片”应用本身中下载照片(在 Google 服务器上)并稍后使用。
来源:
- Android: Error upload image in different android versions
我在使用 google 照片应用选择和裁剪图像时遇到问题。 我这样解决了这个问题
private void pickUserImage() {
if (doHavePermission()) {
Intent photoPickerIntent = new Intent(Intent.ACTION_PICK,
android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
photoPickerIntent.setType("image/*");
photoPickerIntent.putExtra("crop", "true");
photoPickerIntent.putExtra("scale", true);
photoPickerIntent.putExtra("outputX", 256);
photoPickerIntent.putExtra("outputY", 256);
photoPickerIntent.putExtra("aspectX", 1);
photoPickerIntent.putExtra("aspectY", 1);
photoPickerIntent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString());
photoPickerIntent.putExtra(MediaStore.EXTRA_OUTPUT, getTempUri());
startActivityForResult(photoPickerIntent, PICK_FROM_GALLERY);
}
}
在 Whosebug post
中找到我的完整解决方案 hereTry
getPathFromInputStreamUri()
, this will fix the content uri problem from google photo app
Kotlin (UPDATED)
fun getPathFromInputStreamUri(context: Context, uri: Uri): String? {
var filePath: String? = null
uri.authority?.let {
try {
context.contentResolver.openInputStream(uri).use {
val photoFile: File? = createTemporalFileFrom(it)
filePath = photoFile?.path
}
} catch (e: FileNotFoundException) {
e.printStackTrace()
} catch (e: IOException) {
e.printStackTrace()
}
}
return filePath
}
@Throws(IOException::class)
private fun createTemporalFileFrom(inputStream: InputStream?): File? {
var targetFile: File? = null
return if (inputStream == null) targetFile
else {
var read: Int
val buffer = ByteArray(8 * 1024)
targetFile = createTemporalFile()
FileOutputStream(targetFile).use { out ->
while (inputStream.read(buffer).also { read = it } != -1) {
out.write(buffer, 0, read)
}
out.flush()
}
targetFile
}
}
private fun createTemporalFile(): File = File(getDefaultDirectory(), "tempPicture.jpg")
Java
public static String getPathFromInputStreamUri(Context context, Uri uri) {
InputStream inputStream = null;
String filePath = null;
if (uri.getAuthority() != null) {
try {
inputStream = context.getContentResolver().openInputStream(uri);
File photoFile = createTemporalFileFrom(inputStream);
filePath = photoFile.getPath();
} catch (FileNotFoundException e) {
Logger.printStackTrace(e);
} catch (IOException e) {
Logger.printStackTrace(e);
} finally {
try {
if (inputStream != null) {
inputStream.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
return filePath;
}
private static File createTemporalFileFrom(InputStream inputStream) throws IOException {
File targetFile = null;
if (inputStream != null) {
int read;
byte[] buffer = new byte[8 * 1024];
targetFile = createTemporalFile();
OutputStream outputStream = new FileOutputStream(targetFile);
while ((read = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, read);
}
outputStream.flush();
try {
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return targetFile;
}
private static File createTemporalFile() {
return new File(Utils.getDefaultDirectory(), "tempPicture.jpg");
}