gpt4 book ai didi

android - 查询 MediaStore : Joining thumbnails and images (on ID)

转载 作者:塔克拉玛干 更新时间:2023-11-02 19:53:50 25 4
gpt4 key购买 nike

我正在为 Android 开发一个“照片库”类型的应用程序。它最初是 Udacity 开发 Android 应用程序的最终项目,因此它的整体结构( Activity 、内容提供者等)应该非常健全,并且被 Udacity/Google 接受认证。

然而,它还没有 100% 完成,我仍在努力改进它。

我想做的事情应该非常简单;将设备上的所有图像(作为缩略图)加载到 MainActivity 中的 GridView,DetailActivity 显示全尺寸图像 + 一些元数据(标题、大小、日期等)。

类(class)要求我们编写一个 ContentProvider,所以我有一个 query() 函数,它基本上从 MediaStore 获取数据,并将游标返回到 MainActivity 的 GridView。至少在我的设备(Sony Xperia Z1、Android 5.1.1)上,这几乎可以完美运行。有一些错误和怪癖,但总的来说,我可以始终在我的应用程序中找到我手机上的所有图像,然后单击它们以查看详细信息。

但是,当我尝试在我 friend 的 Sony Xperia Z3 上安装该应用程序时,一切都失败了。没有图像出现,虽然我显然检查过他手机上实际上有大约 100 张照片。在另一位 friend 的手机(全新的三星 S6)上也一样:-(

这是主要问题。在我的手机上,东西正常,“次要”错误涉及相机拍摄新照片时,它不会自动加载到我的应用程序中(作为缩略图)。看来我需要弄清楚如何触发扫描,或者加载/生成新拇指所需的任何东西。这在我的愿望 list 上也很靠前。

正如我所说,我相信所有这一切真的应该非常简单,所以也许我所有的困难都表明我正在以完全错误的方式解决问题? 这是我的 query() 函数正在执行的操作:

  1. 获取所有缩略图的光标,来自 MediaStore.Media.Thumbnails.EXTERNAL_CONTENT_URI

  2. 获取所有图像的光标,来自 MediaStore.Media.Images.EXTERNAL_CONTENT_URI

  3. 加入这些,在 MediaStore.Media.Thumbnails.IMAGE_ID = MediaStore.Media.Images._ID 使用 CursorJoiner

  4. 返回结果 retCursor(在连接中生成)

-- 请查找完整代码 in this previous post.

虽然这看起来(对我来说)是正确的,但也许这真的不是解决这个问题的方法?顺便说一下,我加入了缩略图和图像,这样我就可以在 GridView 中显示一些元数据(例如拍摄日期)和缩略图。我已经确定了加入的问题,特别是因为如果我将其简化为仅将拇指加载到 GridView 中,那么这一切都可以正常工作——在我 friend 的手机上也是如此。 (加载新照片除外。)

不知何故,我关于 IMAGE_ID_ID 始终一致的假设是不正确的?我见过 post on AirPair ,描述了一个类似的图库应用程序,而教程实际上在这方面略有不同。他没有尝试连接游标,而是获取缩略图游标并对其进行迭代,adding data from Images using individual queries to the MediaStore ... 但这是最​​有效的方法吗?- 然而,他的解决方案确实将缩略图加入了 ID 上的相应图像:

Cursor imagesCursor = context.getContentResolver().query(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
filePathColumn,
MediaStore.Images.Media._ID + "=?", new String[]{imageId}, // NB!
null);

总而言之,我需要以下方面的帮助:

  • 我是否正确查询了 MediaStore?
  • 在 ID 上加入拇指和图像是否安全——这会始终保持稳定/同步吗?
  • 我的应用如何自动生成/获取新图像的缩略图?

最佳答案

好吧,看来我终于想通了这一切。我想我会在这里分享给任何可能感兴趣的人。

我想达到什么目的?

  • 查询设备上的缩略图和图像(通过 MediaStore)
  • 将这些加入一个游标,按降序排序(最新图像在最上面)
  • 处理丢失缩略图的情况

经过大量试验和错误,并尝试使用 MediaStore,我了解到缩略图表 (MediaStore.Images.Thumbnails) 不能期望在任何给定时间都是最新的。 缺少缩略图的图像,反之亦然(孤立的缩略图)。特别是当相机应用程序拍摄新照片时,显然它不会立即创建缩略图。直到图库应用程序(或等效应用程序)打开,缩略图表才会更新。

关于如何解决这个问题,我得到了各种有用的建议,主要集中在查询图像表 (MediaStore.Images.Media) 上,然后以某种方式一次一行地使用缩略图扩展光标。虽然这确实有效,但它导致应用程序非常慢,并且在我的设备上为大约 2000 张图像消耗了大量内存。

确实应该可以简单地 JOIN(左外连接)缩略图表和图像表,这样我们就可以获得所有图像和缩略图(当它们存在时)。否则,我们将缩略图 DATA 列保留为 null,并自行生成那些特定的缺失缩略图。真正酷的是将这些缩略图插入到 MediaStore 中,但我还没有研究过。

所有这一切的主要问题是使用 CursorJoiner .出于某种原因,它要求两个游标都按升序排序,比方说按 ID。然而,这意味着最旧的图像优先,这确实是一个蹩脚的画廊应用程序。然而,我发现 CursorJoiner 可以被“愚弄”,通过简单地按 ID*(-1) 排序来允许降序:

Cursor c_thumbs = getContext().getContentResolver().query(
MediaStore.Images.Thumnails.EXTERNAL_CONTENT_URI,
null, null, null,
"(" + MediaStore.Images.Thumnails.IMAGE_ID + "*(-1))");

Cursor c_images= getContext().getContentResolver().query(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
null, null, null,
"(" + MediaStore.Images.Media._ID + "*(-1))");

不过,只要行匹配,就可以正常工作(BOTH 情况)。但是,当您遇到游标唯一的行(LEFTRIGHT 情况)时,反向排序会扰乱 CursorJoiner 类的内部工作。但是,对左右游标进行简单的补偿就足以“重新对齐”连接,使其回到正轨。请注意 moveToNext()moveToPrevious() 调用。

// join these and return
// the join is on images._ID = thumbnails.IMAGE_ID
CursorJoiner joiner = new CursorJoiner(
c_thumbs, new String[] { MediaStore.Images.Thumnails.IMAGE_ID }, // left = thumbnails
c_images, new String[] { MediaStore.Images.Media._ID } // right = images
);

String[] projection = new String{"thumb_path", "ID", "title", "desc", "datetaken", "filename", "image_path"};

MatrixCursor retCursor = new MatrixCursor(projection);

try {
for (CursorJoiner.Result joinerResult : joiner) {

switch (joinerResult) {
case LEFT:
// handle case where a row in cursorA is unique
// images is unique (missing thumbnail)

// we want to show ALL images, even (new) ones without thumbnail!
// data = null will cause a temporary thumbnail to be generated in PhotoAdapter.bindView()

retCursor.addRow(new Object[]{
null, // data
c_images.getLong(1), // image id
c_images.getString(2), // title
c_images.getString(3), // desc
c_images.getLong(4), // date
c_images.getString(5), // filename
c_images.getString(6)
});

// compensate for CursorJoiner expecting cursors ordered ascending...
c_images.moveToNext();
c_thumbs.moveToPrevious();
break;

case RIGHT:
// handle case where a row in cursorB is unique
// thumbs is unique (missing image)

// compensate for CursorJoiner expecting cursors ordered ascending...
c_thumbs.moveToNext();
c_images.moveToPrevious();
break;

case BOTH:

// handle case where a row with the same key is in both cursors
retCursor.addRow(new Object[]{
c_thumbs.getString(1), // data
c_images.getLong(1), // image id
c_images.getString(2), // title
c_images.getString(3), // desc
c_images.getLong(4), // date
c_images.getString(5), // filename
c_images.getString(6)
});

break;
}
}
} catch (Exception e) {
Log.e("myapp", "JOIN FAILED: " + e);
}

c_thumbs.close();
c_images.close();

return retCursor;

然后,在“PhotoAdapter”类中,它为我的 GridView 创建元素并将数据从 ContentProvider(上面的 retCursor)返回的游标绑定(bind)到这些元素中,我按以下方式创建缩略图(当 thumb_path 字段为 null 时):

String thumbData = cursor.getString(0);  // thumb_path
if (thumbData != null) {
Bitmap thumbBitmap;
try {
thumbBitmap = BitmapFactory.decodeFile(thumbData);
viewHolder.iconView.setImageBitmap(thumbBitmap);
} catch (Exception e) {
Log.e("myapp", "PhotoAdapter.bindView() can't find thumbnail (file) on disk (thumbdata = " + thumbData + ")");
return;
}

} else {

String imgPath = cursor.getString(6); // image_path
String imgId = cursor.getString(1); // ID
Log.v("myapp", "PhotoAdapter.bindView() thumb path for image ID " + imgId + " is null. Trying to generate, with path = " + imgPath);

try {
Bitmap thumbBitmap = ThumbnailUtils.extractThumbnail(BitmapFactory.decodeFile(imgPath), 512, 384);
viewHolder.iconView.setImageBitmap(thumbBitmap);
} catch (Exception e) {
Log.e("myapp", "PhotoAdapter.bindView() can't generate thumbnail for image path: " + imgPath);
return;
}
}

关于android - 查询 MediaStore : Joining thumbnails and images (on ID),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32782085/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com