从 SD 卡上的特定目录获取照片

Get photos from a specific directory on SD Card

我正在尝试使用一些 MediaStore.Images.Thumbnails 代码从我的 SD 卡上的特定目录加载所有图像,但在我的 cursor 上得到一个空指针,这可能意味着它没有取回任何东西。有谁知道如何正确使用 MediaStore.Images.Thumbnails.getContentUri(String volumeName) 吗?我假设它是您 SD 卡上目录的特定名称,但我想那是错误的,因为我的代码不起作用。 Android doc pages 非常模糊,所以没有帮助,而且我找不到有人试图从特定目录获取图像的单个示例。通常使用的是这个MediaStore.Images.Thumbnails.EXTERNAL_CONTENT_URI,它可以工作,但它会从谁知道从哪里拉照片。我想只是你 SD 卡上的所有照片,任何地方。

或者,如果您知道从 SD 卡特定目录中提取文件的解决方法,我将不胜感激。

更新

这里是需要修改的方法。目前无法从 SD 卡上传任何内容,即使其中有 2 张照片。

private ArrayList<PhotoGridItem> loadSDCard() {

        try {
            // gets directory CutePhotos from sd card
            File cutePhotosDir = new File(Environment.getExternalStoragePublicDirectory
                    (Environment.DIRECTORY_DOCUMENTS), "CutePhotos");
            // lists all files in CutePhotos, loads in Files[] array
            files = cutePhotosDir.listFiles();


            for (File singleFile : files) {
                String filePath = singleFile.getAbsolutePath();
                Bitmap bitmap = BitmapFactory.decodeFile(filePath);
                photoList.add(new PhotoGridItem(bitmap));
            }

        } catch (Exception e) {
            e.printStackTrace();
        }

        return photoList;
    }

PhotoTab.java

package org.azurespot.cutecollection;

import android.content.Context;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Bundle;
import android.provider.MediaStore;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.GridView;
import android.widget.ImageView;

import org.azurespot.R;

/**
 * Created by mizu on 2/8/15.
 */
public class PhotoTab extends Fragment{

    private GridView gridView;
    private GridViewPhotoAdapter gvPhotoAdapter;
    Bitmap bitmap;

    //  Cursor used to access the results from querying for images on the SD card.
    protected Cursor cursor;

    // Column index for the Thumbnails Image IDs.
    protected int columnIndex;

    public PhotoTab(){
        super();
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {

        // Inflate the layout for this fragment
        View v = inflater.inflate(R.layout.photo_tab, container, false);

        // Set up an array of the Thumbnail Image ID column we want
        String[] thumbNails = {MediaStore.Images.Thumbnails._ID};

        cursor = getActivity().getContentResolver().query
                (MediaStore.Images.Thumbnails.getContentUri("/Documents/CutePhotos"),
                thumbNails, // Which columns to return
                null,       // Return all rows
                null,
                MediaStore.Images.Thumbnails.IMAGE_ID);

        // Get the column index of the Thumbnails Image ID
        columnIndex = cursor.getColumnIndexOrThrow(MediaStore.Images.Thumbnails._ID);

        // with fragments, make sure you include the rootView when finding id
        gridView = (GridView) v.findViewById(R.id.photo_grid);
        // Create the Custom Adapter Object, must use v.getContext() instead of
        // getActivity()
        gvPhotoAdapter = new GridViewPhotoAdapter(v.getContext());
        // Set the Adapter to GridView
        gridView.setAdapter(gvPhotoAdapter);


        return v;
    }
    private class GridViewPhotoAdapter extends BaseAdapter {

        public Context context;
        public ImageView photoView;


        public GridViewPhotoAdapter(Context context) {
            this.context = context;

        }

        public int getCount() {
            return 24;
        }

        public Object getItem(int position) {
            return position;
        }
        public long getItemId(int position) {
            return position;
        }


        @Override
        public View getView(int position, View convertView, ViewGroup parent) {

            if (convertView == null) {
                photoView = new ImageView(context);

                // Move cursor to current position
                cursor.moveToPosition(position);

                // Get the current value for the requested column
                int imageID = cursor.getInt(columnIndex);

                // Set the content of the image based on the provided URI
                photoView.setImageURI(Uri.withAppendedPath(
                        MediaStore.Images.Thumbnails.EXTERNAL_CONTENT_URI, "" + imageID));
                // positioning the image in the GridView slot
                photoView.setScaleType(ImageView.ScaleType.CENTER_CROP);
                photoView.setLayoutParams(new GridView.LayoutParams(320, 320));
            }
            else {
                photoView = (ImageView)convertView;
            }

            return photoView;

        }
    }
}

Logcat

FATAL EXCEPTION: main
    Process: org.azurespot, PID: 10577
    java.lang.NullPointerException
            at org.azurespot.cutecollection.PhotoTab.onCreateView(PhotoTab.java:65)
            at android.support.v4.app.Fragment.performCreateView(Fragment.java:1786)
            at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:947)
            at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1126)
            at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:739)
            at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1489)
            at android.support.v4.app.FragmentManagerImpl.executePendingTransactions(FragmentManager.java:486)
            at android.support.v4.app.FragmentPagerAdapter.finishUpdate(FragmentPagerAdapter.java:141)
            at android.support.v4.view.ViewPager.populate(ViewPager.java:1073)
            at android.support.v4.view.ViewPager.populate(ViewPager.java:919)
            at android.support.v4.view.ViewPager.onMeasure(ViewPager.java:1441)
            at android.view.View.measure(View.java:17619)
            at android.widget.RelativeLayout.measureChildHorizontal(RelativeLayout.java:719)
            at android.widget.RelativeLayout.onMeasure(RelativeLayout.java:455)
            at android.view.View.measure(View.java:17619)
            at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5428)
            at android.widget.FrameLayout.onMeasure(FrameLayout.java:310)
            at android.view.View.measure(View.java:17619)
            at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5428)
            at android.support.v7.internal.widget.ActionBarOverlayLayout.onMeasure(ActionBarOverlayLayout.java:453)
            at android.view.View.measure(View.java:17619)
            at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5428)
            at android.widget.FrameLayout.onMeasure(FrameLayout.java:310)
            at android.view.View.measure(View.java:17619)
            at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5428)
            at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1410)
            at android.widget.LinearLayout.measureVertical(LinearLayout.java:695)
            at android.widget.LinearLayout.onMeasure(LinearLayout.java:588)
            at android.view.View.measure(View.java:17619)
            at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5428)
            at android.widget.FrameLayout.onMeasure(FrameLayout.java:310)
            at com.android.internal.policy.impl.PhoneWindow$DecorView.onMeasure(PhoneWindow.java:2588)
            at android.view.View.measure(View.java:17619)
            at android.view.ViewRootImpl.performMeasure(ViewRootImpl.java:2317)
            at android.view.ViewRootImpl.measureHierarchy(ViewRootImpl.java:1412)
            at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1613)
            at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1270)
            at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6691)
            at android.view.Choreographer$CallbackRecord.run(Choreographer.java:813)
            at android.view.Choreographer.doCallbacks(Choreographer.java:613)
            at android.view.Choreographer.doFrame(Choreographer.java:583)
            at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:799)
            at android.os.Handler.handleCallback(Handler.java:733)
            at android.os.Handler.dispatchMessage(Handler.java:95)
            at android.os.Looper.loop(Looper.java:146)
            at android.app.ActivityThread.main(ActivityThread.java:5731)
            at java.lang.reflect.Method.invokeNative(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:515)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1291)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1107)
            at dalvik.system.NativeStart.main(Native Method)
03-18 22:38:22.062  10577-10577/org.azurespot I/Process﹕ Sending signal. PID: 10577 SIG: 9

看看这个post:Listing thumbnails per bucket 它开始带来一个包含所有文件夹的网格视图。然后在单击一个文件夹项目时,它会显示该文件夹中的图片。好吧,这就是 OP 想要的。

在 onClick 侦听器中使用 String bucketId = thumbnails.getId(position); 获取正确的文件夹。您需要稍微更改 class Th 以将 bucketId 作为参数。那么selection = MediaStore.Images.Media.BUCKET_ID + "=" + buckedId;

我假设您只想从相机捕获的照片中获取照片。这是一个很好的网页@ Camera Saving Media。看看Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES)。这是图片的目录。 static class Environment 适用于其他有效目录。示例相关代码:

File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(
              Environment.DIRECTORY_PICTURES), "MyApp");

对象 mediaStorageDir 至少包含目录名称。

如果我没理解错的话,你只是想正确设置Uri。我查看了 MediaScannerService 的代码,这就是我所知道的。 Uri 前缀可以是:

content://media/internal/
file://

对于您的情况,您可以尝试 file://Documents/CutePhotos

因为您已经知道要使用哪个文件夹,您可以简单地使用 File class,并将路径设置为 /Documents/CutePhotos。但是使用 Environment.DIRECTORY_DOCUMENTS 作为正确的路径前缀。 这种方式可以提高性能效率,因为它不使用数据库。