Android:扫描目录并显示图片(缩略图)(图片不存储在mediastore中)

2024-04-10

我最近使用我使用媒体查询和媒体存储设计的自定义图库进行了一些显示图片的测试...它效果很好,但我确实需要做一些自定义的事情。

我不希望图片被扫描或在媒体存储中可用,因此我想让我的应用程序扫描目录并创建缩略图并显示这些缩略图。

我发现很难找到任何高质量的例子来做到这一点。

任何人都可以帮忙举一个小例子。

这就是我想要做的。

  1. 图片存放在sdcard的某个目录下。
  2. 使用我的自定义图库,它将扫描此目录,但使用媒体存储“不”
  3. 我需要显示目录的内容,但作为缩略图,我想我需要先创建这个缩略图?
  4. 单击缩略图将显示我的自定义图库中的全屏图像。

我想我只需要一点帮助来从目录中获取图片,因为没有存储在媒体存储中,所以我无法使用查询。我担心的另一件事是,我需要为每个图像创建缩略图(即时?),因为显示图像但尺寸缩小,我怀疑这对性能来说非常糟糕。

有人可以伸出援助之手吗?

提前致谢


不久前我也做了同样的事情。您必须传递图像所在的文件夹名称setBaseFolder。该方法依次调用refresh()其中 - 使用FilenameFilter(不包括代码,但很容易实现)获取所有命名的图像orig_....jpg从该文件夹并将其保存在mFileList。然后我们打电话notifyDataSetChanged()这反过来会触发getView()对于每个细胞。

Now, in getView()如果我们已经有缩略图位图,我们要么从缓存中获取它,否则我们创建一个灰色占位符并启动一个ThumbnailBuilder创建缩略图。从中获取位图。

我想你必须改变ThumbnailBuilder有点,因为我创建了相当大的“缩略图”(500x500),因为我也需要调整大小的图像用于其他目的。另外,当我处理相机拍摄的照片时,那里有一些东西,根据 exif 信息旋转图像。但基本上,ThumbnailBuilder只是检查是否已经有缩略图(我的缩略图放置在同一文件夹中,但有前缀small_代替orig_) - 如果缩略图已经存在,我们将其作为Bitmap并完成,否则生成图像。最后,在onPostExecute()位图设置为 ImageView。

public class PhotoAdapter extends BaseAdapter {

private Context mContext;
private int mCellSize;
private File mFolder;
private File[] mFileList;
private Map<Object, Bitmap> mThumbnails = new HashMap<Object, Bitmap>();
private Set<Object> mCreatingTriggered = new HashSet<Object>(); // flag that creating already triggered

public PhotoAdapter(Context context, int cellSize) {
    mContext = context;
    mCellSize = cellSize;
}

@Override
public int getCount() {
    if (mFolder == null) {
        return 0;   // don't do this
    } else {
        return mFileList.length;
    }
}

@Override
public Object getItem(int position) {
    return mFileList[position];
}

@Override
public long getItemId(int position) {
    return position;
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    ImageView view = (ImageView)convertView;
    if (view == null) {
        view = new ImageView(mContext);
        view.setLayoutParams(new GridView.LayoutParams(mCellSize, mCellSize));
        view.setScaleType(ImageView.ScaleType.CENTER_CROP);
        view.setPadding(8, 8, 8, 8);
        view.setBackgroundColor(0xFFC6CCD3);
    }
    Object item = getItem(position);
    Bitmap bm = mThumbnails.get(item);
    if (bm == null) {
        view.setImageBitmap(null);
        if (!mCreatingTriggered.contains(item)) {
            mCreatingTriggered.add(item);
            new ThumbnailBuilder(view, (File)item).execute();
        }
    } else {
        view.setImageBitmap(bm);
    }
    return view;
}

public void setBaseFolder(File baseFolder) {
    if (baseFolder == null) return;
    if (!baseFolder.equals(mFolder)) {
        releaseThumbnails();
        mFolder = baseFolder;
    }
    refresh();
}

public void refresh() {
    if (mFolder == null) {
        return;
    }
    mFileList = mFolder.listFiles(EtbApplication.origImageFilenameFilter);
    if (mFileList == null) mFileList = new File[0];
    notifyDataSetChanged();
}

public void releaseThumbnails() {
    for (Bitmap bm : mThumbnails.values()) {
        bm.recycle();
    }
    mThumbnails.clear();
}

// ------------------------------------------------------------------------------------ Asynchronous Thumbnail builder

private class ThumbnailBuilder extends AsyncTask<Void, Integer, Bitmap> {

    private ImageView mView;
    private File mFile;

    public ThumbnailBuilder(ImageView view, File file) {
        mView = view;
        mFile = file;
    }

    @Override
    protected Bitmap doInBackground(Void... params) {
        Log.d("adapter", "make small image and thumbnail");
        try {
            return createThumbnail(mFile.getAbsolutePath());
        } catch (Exception e) {
            return null;
        }
    }

    @Override
    protected void onPostExecute(Bitmap result) {
        if (result != null) {
            mView.setImageBitmap(result);
            mThumbnails.put(mFile, result);
        } else {
            mView.setImageResource(R.drawable.ic_launcher);
        }
    }

    /**
     * Creates Thumbnail (also rotates according to exif-info)
     * @param file
     * @return
     * @throws IOException
     */
    private Bitmap createThumbnail(String file) throws IOException {

        File thumbnailFile = new File(file.replace("orig_", "small_"));

        // If a small image version already exists, just load it and be done.
        if (thumbnailFile.exists()) {
            return BitmapFactory.decodeFile(thumbnailFile.getAbsolutePath());
        }

        // Decode image size
        BitmapFactory.Options bounds = new BitmapFactory.Options();
        bounds.inJustDecodeBounds = true;
        BitmapFactory.decodeFile(file, bounds);

        if ((bounds.outWidth == -1) || (bounds.outHeight == -1))
            return null;

        int w, h;

        if (bounds.outWidth > bounds.outHeight) {   // Querformat
            w = 500;
            h = 500 * bounds.outHeight / bounds.outWidth;
        } else {    // Hochformat
            h = 500;
            w = 500 * bounds.outWidth / bounds.outHeight;
        }

        BitmapFactory.Options opts = new BitmapFactory.Options();
        opts.inSampleSize = 4;  // resample -- kleiner aber noch nicht die 500 Pixel, die kommen dann unten
        Bitmap resizedBitmap = BitmapFactory.decodeFile(file, opts);
        resizedBitmap = Bitmap.createScaledBitmap(resizedBitmap, w, h, true);

        ExifInterface exif = new ExifInterface(file);
        String orientString = exif.getAttribute(ExifInterface.TAG_ORIENTATION);
        int orientation = orientString != null ? Integer.parseInt(orientString) : ExifInterface.ORIENTATION_NORMAL;
        int rotationAngle = 0;
        if (orientation == ExifInterface.ORIENTATION_ROTATE_90) rotationAngle = 90;
        if (orientation == ExifInterface.ORIENTATION_ROTATE_180) rotationAngle = 180;
        if (orientation == ExifInterface.ORIENTATION_ROTATE_270) rotationAngle = 270;

        Matrix matrix = new Matrix();
        matrix.setRotate(rotationAngle, (float) resizedBitmap.getWidth() / 2, (float) resizedBitmap.getHeight() / 2);
        Bitmap rotatedBitmap = Bitmap.createBitmap(resizedBitmap, 0, 0, w, h, matrix, true);
        resizedBitmap.recycle();
        ByteArrayOutputStream bytes = new ByteArrayOutputStream();
        rotatedBitmap.compress(Bitmap.CompressFormat.JPEG, 90, bytes);

        thumbnailFile.createNewFile();
        FileOutputStream fo = new FileOutputStream(thumbnailFile);
        fo.write(bytes.toByteArray());
        fo.close();

        //new File(file).delete();  // Originalbild löschen

        return rotatedBitmap;
    }
}
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Android:扫描目录并显示图片(缩略图)(图片不存储在mediastore中) 的相关文章

  • 使用 google Directions API 的地图视图绘制方向 - 解码折线

    我正在尝试使用 Google 方向 API 在我的地图视图上显示方向 但我在从 JSON 响应获取数据时遇到困难 我可以获得 级别 和 点 字符串 但无法弄清楚如何将它们解码为地图上的点 任何帮助将非常感激 我有一个类可以为您解码它们 添加
  • Android:使用 OAuth 访问 google 任务时出现问题

    由于 google 任务没有公共 api 我想编写解决方法并像浏览器一样请求数据 然后解析结果以进一步显示 为了访问数据 我使用 google 实现了 OAuth 身份验证来访问此 url https mail google com htt
  • Manifest Merger工具:替换失败

    我正在使用一个使用自己的 android theme 的库 因此在构建时收到以下错误 错误 55 9 任务 contacit processDebugManifest 执行失败 清单合并失败 AndroidManifest xml 中的属性
  • FTS3 在 ORMLite 中搜索?

    我对 FTS3 一无所知 除了http developer android com guide topics search search dialog html http developer android com guide topics
  • 通过 WhatsApp 发送消息

    由于我发现了一些较旧的帖子 表明 Whatsapp 不支持此功能 我想知道是否发生了变化 以及是否有办法打开与我通过意图发送的号码进行 Whatsapp 聊天 UPDATE请参阅https faq whatsapp com en andro
  • Android 上的 SVG 支持

    Android 支持 SVG 吗 有什么例子吗 最完整的答案是这样的 Android 2 x 默认浏览器本身不支持 SVG Android 3 默认浏览器支持 SVG 要将 SVG 支持添加到 2 x 版本的平台 您有两个基本选择 安装功能
  • 自定义选择器活动:SecurityException UID n 无权 content:// uri

    我正在构建一个选择器应用程序来替换本机 Android 共享对话框 它工作正常 除非我尝试通过长按图像 gt 共享图像从 Chrome 共享图像 我发现 Google 没有捕获异常 它崩溃了 所以我可以通过 Logcat 查看它 在 Goo
  • 从 Android 代码设置的 SECRET_CODE

    我知道如何使用清单文件中的秘密代码 它与此源代码配合良好
  • 播放 SoundCloud 曲目

    我可以在 Android 应用程序中播放 SoundCloud 中的曲目吗 我正在尝试这段代码 但它不起作用 String res https api soundcloud com tracks 84973999 stream client
  • 带操作按钮的颤动本地通知

    我在我的 flutter 项目中尝试了 flutter 本地通知插件 它在简单通知上工作正常 但我需要带有操作按钮的通知功能 请帮助我或建议我实现此功能 不幸的是 flutter local notifications 插件尚不支持操作按钮
  • 调试:在 Android 1.0 中找不到文件

    今天我更新到 Android Studio v 1 0 在尝试编译任何项目时出现以下错误 app build intermediates classes debug 找不到文件 问题是在更新之前我没有任何问题 这是我实际尝试编译的代码 构建
  • android EditText 输入类型用于 StreetNumber 字段

    我试图在地址对话框的 streetNumber 字段中选择正确的 inputType 我想先显示数字键盘 然后让用户输入字母字符 对于一些非常特殊的情况 更接近这个的是 inputType datetime 但这不允许输入字母字符 那么如何
  • Camera.open()返回NULL Android开发

    我正在按照构建相机应用程序的教程进行操作http developer android com tools device html http developer android com tools device html我对 Camera o
  • 如何检查 Android 中连接的 wifi 网络是否处于活动状态

    如何自动检查android中连接的WiFi网络上的互联网是否处于活动状态 我可以检查 wifi 是否已启用或 wifi 网络是否已连接 但我不确定如何检查互联网是否已连接 这可能吗 private boolean connectionAva
  • Android Studio:未找到 Gradle DSL 方法:“classpath()”

    首先 我已阅读所有其他解决方案帖子以及有关迁移到 1 0 的官方文档 到目前为止 还没有任何效果 Error Error 23 0 Gradle DSL method not found classpath Possible causes
  • 菜单在片段的 onCreateOptionsMenu 处多次膨胀调用

    我使用 Fragments 当我切换到嵌套 Fragment 时 它实现了public void onCreateOptionsMenu Menu menu MenuInflater inflater 当我到达该嵌套片段时 我的菜单会多次膨
  • Android 相机未保存在特定文件夹 [MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA]

    当我在 Intent 中使用 MediaStore INTENT ACTION STILL IMAGE CAMERA 时遇到问题 相机正常启动 但它不会将文件保存在我的特定文件夹 photo 中 但是当我使用 MediaStore ACTI
  • Android:监听状态栏通知

    有没有办法在状态栏被下拉时监听通知 1 用于检测状态栏变化 您可以注册一个监听器来获取系统UI可见性变化的通知 因此 要在您的活动中注册侦听器 Detecting if the user swipe from the top down to
  • Android 中循环事件的星期几和时间选择器

    我想创建一个控件 允许用户在我的 Android 活动中选择一周中的某一天 星期一 和一天中的某个时间 下午 1 00 找不到任何关于此的好帖子 好吧 我想我已经明白了 我只是不喜欢这个解决方案 因为我在一周中的某一天使用的微调器与时间选择
  • 尝试将 SQLite DB 从数据复制到 SD 卡

    我正在使用以下代码 该代码发布在 Stack Overflow 上的某个位置 并根据我的目的进行了修改 try File sd Environment getExternalStorageDirectory File data Enviro

随机推荐