【问题标题】:Is it possible to display video thumbnails using Universal Image Loader, and how?是否可以使用 Universal Image Loader 显示视频缩略图,以及如何显示?
【发布时间】:2014-01-22 18:31:31
【问题描述】:

我正在尝试使用 Universal Image Loader (https://github.com/nostra13/Android-Universal-Image-Loader) 在网格视图中显示视频缩略图。我可以让它毫无问题地显示图像缩略图。

如何在Application类中初始化UIL:

@Override
public void onCreate() {
    super.onCreate();
    initUil();
}

private void initUil() {
    DisplayImageOptions displayOptions = new DisplayImageOptions.Builder()
            .cacheInMemory(true)
            .cacheOnDisc(true)
            .build();

    ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(getApplicationContext())
            .taskExecutor(ThreadPool.getExecutorService())
            .defaultDisplayImageOptions(displayOptions)
            .build();

    ImageLoader.getInstance().init(config);
}

我如何使用它来显示缩略图:

public class MediaCursorAdapter extends SimpleCursorAdapter implements Filterable {
    @Override
    public void bindView(View rowView, Context context, Cursor cursor) {
        String contentUri = getContentUri(cursor);

        ImageView imgThumb = (ImageView) rowView.findViewById(R.id.imgThumb);

        ImageLoader.getInstance().displayImage(contentUri, imgThumb);
    }
}

为简单起见,省略了一些代码。 contentUri 可以是图像 URI 或视频 URI,在这两种情况下都是 content://...

是否可以使用此库显示来自视频内容 URI 的视频缩略图?怎么样?

【问题讨论】:

    标签: android image video universal-image-loader


    【解决方案1】:

    好的,我想通了。 ImageLoaderConfiguration 有一个选项,您可以在其中传入图像解码器。

    这是我更改初始化的方式:

    ImageDecoder smartUriDecoder = new SmartUriDecoder(getContentResolver(), new BaseImageDecoder(false));
    
    ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(getApplicationContext())
                .taskExecutor(ThreadPool.getExecutorService())
                .defaultDisplayImageOptions(displayOptions)
                .imageDecoder(smartUriDecoder)
                .build();
    

    还有SmartUriDecoder 类:

    public class SmartUriDecoder implements ImageDecoder {
        private final ContentResolver m_contentResolver;
        private final BaseImageDecoder m_imageUriDecoder;
    
        public SmartUriDecoder(ContentResolver contentResolver, BaseImageDecoder imageUriDecoder) {
            if (imageUriDecoder == null) {
                throw new NullPointerException("Image decoder can't be null");
            }
    
            m_contentResolver = contentResolver;
            m_imageUriDecoder = imageUriDecoder;
        }
    
        @Override
        public Bitmap decode(ImageDecodingInfo info) throws IOException {
            if (TextUtils.isEmpty(info.getImageKey())) {
                return null;
            }
    
            String cleanedUriString = cleanUriString(info.getImageKey());
            Uri uri = Uri.parse(cleanedUriString);
            if (isVideoUri(uri)) {
                return makeVideoThumbnail(info.getTargetSize().getWidth(), info.getTargetSize().getHeight(), getVideoFilePath(uri));
            }
            else {
                return m_imageUriDecoder.decode(info);
            }
        }
    
        private Bitmap makeVideoThumbnail(int width, int height, String filePath) {
            if (filePath == null) {
                return null;
            }
            Bitmap thumbnail = ThumbnailUtils.createVideoThumbnail(filePath, MediaStore.Video.Thumbnails.MINI_KIND);
            Bitmap scaledThumb = scaleBitmap(thumbnail, width, height);
            thumbnail.recycle();
            return scaledThumb;
        }
    
        private boolean isVideoUri(Uri uri) {
            String mimeType = m_contentResolver.getType(uri);
            return mimeType.startsWith("video/");
        }
    
        private String getVideoFilePath(Uri uri) {
            String columnName = MediaStore.Video.VideoColumns.DATA;
            Cursor cursor = m_contentResolver.query(uri, new String[] { columnName }, null, null, null);
            try {
                int dataIndex = cursor.getColumnIndex(columnName);
                if (dataIndex != -1 && cursor.moveToFirst()) {
                    return cursor.getString(dataIndex);
                }
            }
            finally {
                cursor.close();
            }
            return null;
        }
    
        private Bitmap scaleBitmap(Bitmap origBitmap, int width, int height) {
            float scale = Math.min(
                    ((float)width) / ((float)origBitmap.getWidth()),
                    ((float)height) / ((float)origBitmap.getHeight())
            );
            return Bitmap.createScaledBitmap(origBitmap,
                    (int)(((float)origBitmap.getWidth()) * scale),
                    (int)(((float)origBitmap.getHeight()) * scale),
                    false
            );
        }
    
        private String cleanUriString(String contentUriWithAppendedSize) {
            // replace the size at the end of the URI with an empty string.
            // the URI will be in the form "content://....._256x256
            return contentUriWithAppendedSize.replaceFirst("_\\d+x\\d+$", "");
        }
    }
    

    在 UIL 的文档中,它说 info.getImageKey() 将返回为该图像指定的原始 URI,但最后会附加大小,我找不到获取原始 URI 的方法。这就是cleanUriString() 代码异味的原因。

    【讨论】:

    • 请注意,我尝试了这种方法,但是当我为一堆媒体项目生成缩略图时,我注意到速度大大降低。看起来 UIL 正在数据目录中为视频本身创建一个缓存条目,这意味着大量的处理时间和大文件(查看 50 mb 文件等)。我仍在研究它,但感谢您在将 vids 与 uil 集成方面取得了良好的开端。
    • 我也注意到了这一点,但它只是第一次发生。我认为这是因为MediaStore 中没有视频的缩略图,所以调用ThumbnailUtils.createVideoThumbnail() 会强制创建所有视频​​缩略图。但我不确定该方法是如何工作的,所以我在这里可能完全错了。
    • 嗨,我尝试根据您的工作制作自定义 ImageDecoder,但是当我尝试使用它时,解码器失败并出现此错误:E/ImageLoader﹕null java.lang.NullPointerException?任何线索为什么?
    • 你应该查看堆栈跟踪,看看它到底在哪里失败。
    • @DanielGabriel : 抱歉,看起来你的智能解码器可以支持非常好的视频,但无法加载照片ImageDecoder 尝试加载照片时发生异常。哪些方法需要放入Smart Decoder,请告诉我们?
    【解决方案2】:

    我会查看这个答案,看起来这个人已经解决了,但它没有使用通用图像加载器。

    Android: Is it possible to display video thumbnails?

    【讨论】:

    • 我知道如何生成视频缩略图,但我正在寻找具有缓存和同步功能的可配置解决方案,而 UIL 似乎是一个完美的候选者。
    猜你喜欢
    • 2016-07-15
    • 2010-11-23
    • 2018-08-28
    • 2014-05-01
    • 1970-01-01
    • 2012-11-24
    • 2011-03-25
    • 1970-01-01
    • 2016-12-13
    相关资源
    最近更新 更多