【问题标题】:How can I get image path from all images on phone如何从手机上的所有图像中获取图像路径
【发布时间】:2015-12-25 19:29:45
【问题描述】:

我想从手机上的所有图像中获取路径。我使用了这段代码,但这给了我 dcim/camera/ 目录中的每个文件(它包括我不想获取的视频(.mp4)文件)。我想在每个目录中获取图像的路径。

String targetPath = ExternalStorageDirectoryPath + "/DCIM/Camera/";

File targetDirector = new File(targetPath);

final File[] files = targetDirector.listFiles();
for (File file : files){
    // file is path to file
}

【问题讨论】:

  • 如果你想使用FilelistFiles,你必须递归进入每个目录,嗅出具有适当扩展名(或元数据)的文件,因为它只给你当前目录中的条目。像this answer 这样的东西会有所帮助,但你必须确保你在自己的线程中运行它。

标签: java android image file path


【解决方案1】:

为此,您必须查询 Media Store Content Provider。在我的项目中,我使用以下方法获取列表以及与每个图像关联的一些其他数据。

public static ArrayList<MediaStorePhoto> getAllPhotosFromExternalStorage(ContentResolver mContentResolver) {

    MediaStorePhoto photo;
    ArrayList<MediaStorePhoto> photoList = new ArrayList<>();

    // which image properties are we querying
    String[] projection = new String[]{
            MediaStore.Images.Media.BUCKET_ID,
            MediaStore.Images.Media.BUCKET_DISPLAY_NAME,
            MediaStore.Images.Media._ID,
            MediaStore.Images.Media.DATE_TAKEN,
            MediaStore.Images.Media.SIZE,
            MediaStore.Images.Media.DISPLAY_NAME,
            MediaStore.Images.Media.DATA
    };

    // content:// style URI for the "primary" external storage volume
    Uri images = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;

    // Make the query.
    Cursor cur = mContentResolver.query(images,
            projection, // Which columns to return
            null,       // Which rows to return (all rows)
            null,       // Selection arguments (none)
            null        // Ordering
    );

    Log.i("ListingImages", " query count=" + cur.getCount());

    if (cur.moveToFirst()) {
        String bucketId;
        long id;
        long size;
        String bucket;
        String date;
        String name;
        String dataUri;

        int bucketIdColumn = cur.getColumnIndex(
                MediaStore.Images.Media.BUCKET_ID);

        int idColumn = cur.getColumnIndex(
                MediaStore.Images.Media._ID);

        int bucketColumn = cur.getColumnIndex(
                MediaStore.Images.Media.BUCKET_DISPLAY_NAME);

        int dateColumn = cur.getColumnIndex(
                MediaStore.Images.Media.DATE_TAKEN);

        int sizeColumn = cur.getColumnIndex(
                MediaStore.Images.Media.SIZE);

        int nameColumn = cur.getColumnIndex(
                MediaStore.Images.Media.DISPLAY_NAME);

        int dataColumn = cur.getColumnIndex(
                MediaStore.Images.Media.DATA);
        do {
            // Get the field values
            bucketId = cur.getString(bucketIdColumn);
            bucket = cur.getString(bucketColumn);
            date = cur.getString(dateColumn);
            size = cur.getLong(sizeColumn);
            id = cur.getLong(idColumn);
            name = cur.getString(nameColumn);
            dataUri = cur.getString(dataColumn);

            // Store photo in Photo object
            photo = new MediaStorePhoto(String.valueOf(id), name,
                    bucket, date, String.valueOf(size), "null", dataUri, bucketId);

            // Add photo to photo list
            photoList.add(photo);
        } while (cur.moveToNext());

    }
    cur.close();
    return photoList;
} 

注意:这里 MediaStorePhoto 是我制作的一个类

public class MediaStorePhoto implements Parcelable {

    public static final Creator CREATOR = new Creator() {
        public MediaStorePhoto createFromParcel(Parcel in) {
            return new MediaStorePhoto(in);
        }

        public MediaStorePhoto[] newArray(int size) {
            return new MediaStorePhoto[size];
        }
    };
    private String id;
    private String displayName;
    private String bucket;
    private String date;
    private String size;
    private String status;
    private String dataUri;
    private String bucketId;

    public MediaStorePhoto(String id, String displayName, String bucket, String date, String size, String status, String dataUri, String bucketId) {
        this.id = id;
        this.displayName = displayName;
        ...
        ...
        this.bucketId = bucketId;
    }

    public MediaStorePhoto(Parcel in) {
        String[] data = new String[8];

        in.readStringArray(data);
        this.id = data[0];
        this.displayName = data[1];
        ...
        ...
        this.bucketId = data[7];
    }

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeStringArray(new String[]{this.id,
                this.displayName,
                this.bucket,
                ...
                ...
                this.bucketId});
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    ...
    ...
    ...

    public String getBucketId() {
        return bucketId;
    }

    public void setBucketId(String bucketId) {
        this.bucketId = bucketId;
    }
}

所以,图片的 uri 将在 mediaStorePhoto.getDataUri() mediaStorePhoto.getBucket() 也会为您提供目录的名称。

【讨论】:

    【解决方案2】:

    好的,你有一个好的开始,但你需要稍微改变一下。首先,为了通过可能是可变数量的文件路径,您需要一个在目录上调用自身的递归函数。

    public void walk(File currDir, List<String> fileNames) {
        File[] list = null;
        try {
            list = currDir.listFiles();
        } catch (SecurityException e) {
            // Can't read this file, just do nothing.
            return;
        }
        File[] list = currDir.listFiles();
        for (File f : list) {
            if (f.isDirectory()) {
                walk(f, fileNames);
            } else {
                // Add only images with the extension "jpg" (substitute your own logic here if necessary)
                String fileName = f.getName();
                String extension = fileName.substring(fileName.lastIndexOf(".")+1);
                if ("jpg".equalsIgnoreCase(extension)) {
                    fileNames.add(fileName);
                }
            }
        }
    }
    

    完成此操作后,您需要做的就是在当前目录中调用它来启动链。但是请注意,这可能需要一段时间,因此如果您需要大量图像,则需要在与 UI 不同的线程中运行它。

    List<String> files = new LinkedList<String>();
    String targetPath = ExternalStorageDirectoryPath + "/DCIM/Camera/"; // TODO Change me as needed!
    File targetDirectory = new File(targetPath);
    walk(targetDirectory, files);
    

    在此之后,files 应该在给定目录和所有子目录中包含所有 JPG 文件。

    【讨论】:

    • 我尝试了代码,它找到了所有 .jpg 图片,但仅在定义的目录 (/DCIM/Camera/) 中,当您仅放置 /DCIM/ 时,它会在该目录中找到 .jpg 文件,但我希望它查看每个目录(dcim、图像、图片或任何其他目录)。我试图删除 /dcim/camera/ 并只留下 ExternalStorageDirectoryPath 但它崩溃了应用程序。
    • 是的,首先,当然它只检查 DCIM/Camera;那是指定的根路径,它不会从那里向后退。其次,您需要处理listFiles() 周围的异常,因为您需要处理该方法抛出的SecurityExceptions。
    • 另外,您是否尝试过使用ExternalStorageDirectoryPath + "/"
    • 我试过你的代码,但它不起作用。我尝试使用 ExternalStorageDirectoryPath + "/" 并从 sdcard 获取 .jpg 图像,但它不会在其他目录 (dcim/images/videos/....) 中搜索。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-10
    • 2021-03-21
    • 2012-06-08
    相关资源
    最近更新 更多