问题
I am creating an Android application that needs to store some multimedia files in the internal storage. The user can choose that multimedia files from the picker. Those files must be available even when the user removes them, so they are copied to the internal storage.
Here's my code:
final Bitmap bitm = MediaStore.Images.Media.getBitmap( this.getContentResolver(), uri );
final int bitmapRawLength = bitm.getAllocationByteCount();
final ByteBuffer byteBuffer = ByteBuffer.allocate( bitmapRawLength );
bitm.copyPixelsToBuffer( byteBuffer );
data = byteBuffer.array();
final ByteArrayInputStream in = new ByteArrayInputStream( data );
db.store( in );
So, the bytes composing the image are copied into an average file inside the internal store through an InputStream. Apparently it works, since the file has contents.
Later the image is loaded in an ImageView:
private void loadImage(File imgFile)
{
if ( imgFile.exists() ) {
final Bitmap bitmap = BitmapFactory.decodeFile( mediaFile.getPath() );
this.ivPictureBox.setImageBitmap( bitmap );
} else {
this.abortDueToMissingFile( imgFile );
}
return;
}
Unfortunately, this does not work. When it is time to load that image, the ImageView goes blank, nothing is shown.
Actually, in the log appears the following message:
D/skia: --- Failed to create image decoder with message 'unimplemented'
If I use the file explorer in Android Studio and export the image to my computer, then GwenView fails with the message "Failed to load metadata".
How can I correctly store the image, with the complete information, or show it correctly, whatever is easier or feasible?
回答1:
I have develop and test some code in this case. I hope it helps you.
Defining request codes:
private static final int REQUEST_CODE_KITKAT_PICK_PHOTO = 11;
private static final int REQUEST_CODE_PICK_PHOTO = 12;
To call image picker:
if (Build.VERSION.SDK_INT < 19) {
Intent intent = new Intent();
intent.setType("image/*");
intent.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(Intent.createChooser(intent, "Choose a photo"), REQUEST_CODE_PICK_PHOTO);
} else {
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType("image/*");
startActivityForResult(intent, REQUEST_CODE_KITKAT_PICK_PHOTO);
}
To receive the picked image and copy it, in your Activity
:
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == Activity.RESULT_OK) {
if (requestCode == REQUEST_CODE_PICK_PHOTO) {
if (data == null || data.getData() == null) {
Toast.makeText(getApplicationContext(), "Error in retrieving photo!", Toast.LENGTH_SHORT).show();
return;
}
Uri uri = data.getData();
String destPath = getFilesDir() + File.separator + "image.jpg"; // an example path
File imageFile = null;
try {
imageFile = copy(uri, destPath);
} catch (IOException e) {
e.printStackTrace();
}
if (imageFile != null) {
Bitmap bitmap = BitmapFactory.decodeFile(imageFile.getAbsolutePath());
ivPictureBox.setImageBitmap(bitmap);
}
} else if (requestCode == REQUEST_CODE_KITKAT_PICK_PHOTO) {
if (data == null || data.getData() == null) {
Toast.makeText(getApplicationContext(), "Error in retrieving photo!", Toast.LENGTH_SHORT).show();
return;
}
Uri originalUri = data.getData();
final int takeFlags = data.getFlags()
& (Intent.FLAG_GRANT_READ_URI_PERMISSION
| Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
// Check for the freshest data.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
getContentResolver().takePersistableUriPermission(originalUri, takeFlags);
}
String destPath = getFilesDir() + File.separator + "image.jpg"; // an example path
File imageFile = null;
try {
imageFile = copy(originalUri, destPath);
} catch (IOException e) {
e.printStackTrace();
}
if (imageFile != null) {
Bitmap bitmap = BitmapFactory.decodeFile(imageFile.getAbsolutePath());
ivPictureBox.setImageBitmap(bitmap);
}
}
}
}
// To copy the file:
private File copy(Uri inputUri, String destPath) throws IOException {
File inputFile = new File(ImageUtils.getPathFromUri(getApplicationContext(), inputUri));
File outputFile = new File(destPath);
if (!outputFile.exists()) {
outputFile.createNewFile();
}
FileInputStream inStream = new FileInputStream(inputFile);
FileOutputStream outStream = new FileOutputStream(outputFile);
FileChannel inChannel = inStream.getChannel();
FileChannel outChannel = outStream.getChannel();
inChannel.transferTo(0, inChannel.size(), outChannel);
inStream.close();
outStream.close();
return outputFile;
}
ImageUtils.java:
import android.annotation.SuppressLint;
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;
public class ImageUtils {
@SuppressLint("NewApi")
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())) {
// Return the remote address
if (isGooglePhotosUri(uri))
return uri.getLastPathSegment();
return getDataColumn(context, uri, null, null);
}
// File
else if ("file".equalsIgnoreCase(uri.getScheme())) {
return uri.getPath();
}
return null;
}
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 index = cursor.getColumnIndexOrThrow(column);
return cursor.getString(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());
}
/**
* @param uri The Uri to check.
* @return Whether the Uri authority is Google Photos.
*/
public static boolean isGooglePhotosUri(Uri uri) {
return "com.google.android.apps.photos.content".equals(uri.getAuthority());
}
}
Here is the result:
回答2:
Silly of me!
It is as simple as:
final InputStream in = this.getContentResolver().openInputStream( uri );
...and copy it whichever you want.
This works for URI's with both SCHEME_CONTENT and SCHEME_FILE schemes.
来源:https://stackoverflow.com/questions/52538259/cannot-show-in-imageview-a-picture-exported-from-the-gallery