How to get video thumbnail from file or content Uri? - android

I have tried:
ThumbnailUtils.createVideoThumbnail(uri.getPath(),
MediaStore.Video.Thumbnails.MINI_KIND);
But this returns null for a content Uri. I have also tried this:
private Bitmap getVideoThumbnail(Context context, Uri uri) throws IllegalArgumentException,
SecurityException{
MediaMetadataRetriever retriever = new MediaMetadataRetriever();
retriever.setDataSource(context,uri);
return retriever.getFrameAtTime();
}
This works for both file scheme and content scheme Uris. But it takes ~1.5s to get thumbnail of content Uris representing remote data blocking the UI. I suppose I could make this async and receive the thumbnail is a callback. But I thought there must be a simpler approach to get thumbnails for both file and content Uris. Also this method throws IllegalArgumentExceptions sporadically.
So, is there a way to reliably get thumbnail from file or content Uri schemes?

Related

Re-create uri from decoded string

I get an Uri and I do:
String s = Uri.decode(uri.toString());
But when I encode the string again I haven't got the same result:
Uri uri = Uri.parse(Uri.encode(s));
Uri received without decoding (just called toString()):
content://com.android.externalstorage.documents/document/primary%3APictures%2FScreenshots%2FScreenshot_20190807-153556.png
Uri created via parse/encode method:
content%3A%2F%2Fcom.android.externalstorage.documents%2Fdocument%2Fprimary%3APictures%2FScreenshots%2FScreenshot_20190807-153556.png
Is there a way to re-parse correctly the Uri?
Is there a way to re-parse correctly the Uri?
No. Hold onto the original Uri. This is not significantly different than converting an image to monochrome, then wondering how to get the original color image back. The decode() and encode() methods are not designed to decode and encode Uri values, but rather specific pieces (e.g., query parameter values).

Android Upload Image using path or uri?

I'm having a trouble bringing the images from the gallery to my app.
The hard part is that, in some articles they use uri rather than path, but in others vice versa.
Plus, I'm not also sure... when I get Uri from the intent coming back, should I use cursor to get images data? (How to get Images from Cursor in android?) In some other references, they do it in the easy way, just with 'getPath()' method.
Do I need either of path or uri? or Only one of these?
I'm so confused now..
Always use Uri:
File file = new File(uri.getPath());
then
Bitmap bitmap= BitmapFactory.decodeFile(file.getAbsolutePath());
and when you have bitmap simply load it in to ImageView
imageView.setImageBitmap(bitmap);

Sharing image from app private storage to Facebook

I'm attempting to take a very generic approach in providing sharing options for sharing images from my app's private storage, but I've encountered a problem that appears to be specific to sharing images to the Facebook app (com.facebook.katana):
I launch an intent with EXTRA_STREAM containing a Uri to an image inside the private directory of my app.
Through a ContentProvider, I provide access to the desired file by returning the following in openFile():
return ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY);
When sharing to Facebook, the image doesn't appear. Every other app, however, does work. Debugging calls into my ContentProvider, I see that Facebook does indeed query the ContentProvider, and openFile() is hit. Nevertheless, the image doesn't appear.
After much head scratching, I realized I was returning null as the MIME type. I changed the result of getType() to return "image/png", and that was it: Facebook accepted my image:
#Nullable
#Override
public String getType(#NonNull Uri uri) {
// It's absolutely imperative that we provide the MIME type, otherwise some apps like
// Facebook will simply ignore the file
return "image/png";
}
I would point out that you should return the actual MIME type of the file associated with the Uri; I'm returning PNG here because I'm lazy, and I know that all my images are of that type.

Wrong image file path obtained from Android file manager

In my application I would like to open an image and "load" it to the app using File Manager. I've already doneit using Intent.ACTION_GET_CONTENT and onActivityResult() method. Everything works fine, except from the path which I get. It is in a strange format and I can't show the image in ImageView
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == SELECT_PICTURE) {
Uri selectedImageUri = data.getData();
mFileManagerString = selectedImageUri.getPath();
showPreviewDialog(mFileManagerString);
}
}
Here mFileManagerString = /document/image:19552
When I call a method to show the image in the ImageView:
public void setPreviewIV(String pPath) {
Bitmap bmImg = BitmapFactory.decodeFile(pPath);
receiptPreviewIV.setImageBitmap(bmImg);
}
I get the following error:
E/BitmapFactory: Unable to decode stream: java.io.FileNotFoundException: /document/image:19552: open failed: ENOENT (No such file or directory)
How to get the proper path to the image, so that I can show it in the ImageView?
How to get the proper path to the image
You already have it. It is the Uri that is passed into onActivityResult() via the Intent parameter. Pulling just getPath() out of that Uri is pointless. That's akin to thinking that /questions/33827687/wrong-image-file-path-obtained-from-android-file-manager is a path on your hard drive, just because your Web browser shows a URL that contains that path.
In addition, your current code is loading and decoding the Bitmap on the main application thread. Do not do this, because it freezes the UI while that work is being done.
I recommend that you use any one of the many image-loading libraries available for Android. All the decent ones (e.g., Picasso, Universal Image Loader) not only take a Uri as input but also will load the image on a background thread for you, applying it to your ImageView on the main application thread only when the bitmap is ready.
If, for whatever reason, you feel that you have to do this yourself, use ContentResolver and its openInputStream() to get an InputStream for the data represented by the Uri. Then, pass that to decodeStream() on BitmapFactory. Do all of that in a background thread (e.g., doInBackground() of an AsyncTask), and then apply the Bitmap to the ImageView on the main application thread (e.g., onPostExecute() of an AsyncTask).

Get mime type of content scheme

In order to send an image to a server from my android application, I have to get mime type of the image (or, at least, its extension).
I get the image from a ACTION_GET_CONTENT intent. Some applications, like Dropbox, send a file:// scheme data, so I can guess the extension using MimeTypeMap.getFileExtensionFromUrl(), but some others, like Google Drive, send a content:// scheme, which not permit to do so.
I've tried many things before posting here, like this:
AssetFileDescriptor asset = getContentResolver().openAssetFileDescriptor(getIntent().getData(), "r");
FileInputStream stream = asset.createInputStream();
String mime = URLConnection.guessContentTypeFromStream(stream); // returns null
The only workaround I think is to decode the asset into a Bitmap, then generate a new compressed image (using Bitmap.compress()), but it will add some work to the phone, and it could change the format/quality of original image, so I reserve it only if there is no other solution.
Does anyone have an idea about my problem? Thanks a lot for help ;)
As suggested by #sh3psheep on Twitter, I've tried this, and it works for content:// schemes:
Uri data = getIntent().getData();
String mime = getContentResolver().getType(data); // returns correct MIME type, such as "image/png"
The only con I found is that it does not support file:// scheme, but we can handle it using method I described in question.

Categories

Resources