I have a video and I need get its thumbnail. I use ThumbnailUtils
class for this purpose, but it returns null instead of expected Bitmap
. When I debug my app, I see that inside createVideoThumbnail
method MediaMetadataRetriever.setDataSource
invokes and it throws IllegalArgumentException
. Inside setDataSource
I see this code:
public void setDataSource(String path) throws IllegalArgumentException {
if (path == null) {
throw new IllegalArgumentException();
}
try (FileInputStream is = new FileInputStream(path)) {
FileDescriptor fd = is.getFD();
setDataSource(fd, 0, 0x7ffffffffffffffL);
} catch (FileNotFoundException fileEx) {
throw new IllegalArgumentException(); // and I've found out that method throws IllegalArgimentException inside this catch block
} catch (IOException ioEx) {
throw new IllegalArgumentException();
}
}
I think it means that file with given file doesn't exist. But I see it in file system and it plays fine. Maybe there's another reason?
The question is what you're passing to that method and from what you're obtaining it?
Below is the way I am doing this, and this works for me, so it should work for you as well.
File videoFile = new File(selectedVideoPath);
Bitmap bitmap = ThumbnailUtils.createVideoThumbnail(videoFile.getAbsolutePath(), MediaStore.Video.Thumbnails.FULL_SCREEN_KIND);
To get selectedVideoPath you should use https://github.com/iPaulPro/aFileChooser/blob/master/aFileChooser/src/com/ipaulpro/afilechooser/utils/FileUtils.java#L257 getPath(Context context, Uri uri)
method. Originally it looked like:
public static String getPath(final Context context, final Uri uri) {
if (DEBUG)
Log.d(TAG + " File -",
"Authority: " + uri.getAuthority() +
", Fragment: " + uri.getFragment() +
", Port: " + uri.getPort() +
", Query: " + uri.getQuery() +
", Scheme: " + uri.getScheme() +
", Host: " + uri.getHost() +
", Segments: " + uri.getPathSegments().toString()
);
final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;
// DocumentProvider
if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) {
// LocalStorageProvider
if (isLocalStorageDocument(uri)) {
// The path is the id
return DocumentsContract.getDocumentId(uri);
}
// ExternalStorageProvider
else 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;
}
Additionally you can add checking if videoFile exists by calling videoFile.exists().
Additionally if you're trying to read from external storage you can check if you have included READ_EXTERNAL_STORAGE permission in Manifest file, and if you're saving file and trying to get it thumbnail you should also need WRITE_EXTERNAL_STORAGE permission.
There two reason behind the null for create a thumbnail of a video. either video is corrupt or the format is not supported to ThumbnailUtils.
Double check your file format and use the below code for thumbnail
// Create VideoThumbnail from sdcard path like this.
Bitmap thumb = ThumbnailUtils.createVideoThumbnail(filePath, Thumbnails.MINI_KIND);