如何使用新文件夹选择器将 SD 卡中的图像显示到 ListView API?

How to Display images from SD Card to ListView with the New Folder Picker API?

我正在尝试 select SD 卡中的文件夹并显示该文件夹中的图像列表。

在 Android 5.0 之前它工作正常, 所以我开始使用新的 SD 卡访问更新它 API 来选择文件夹。

public void FolderSelectionAlertDialog_Lollipop() {
    Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
    startActivityForResult(intent, 556);
}

@Override
public void onActivityResult(int requestCode, int resultCode, Intent resultData) {          
    if(resultCode == RESULT_OK) {
        // Get Uri from Storage Access Framework.
        Uri_Lollipop = resultData.getData();        

        // Persist access permissions.
        this.getContentResolver().takePersistableUriPermission(Uri_Lollipop,
             Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);           

    }
}

由于某些原因,ListView 中没有显示图像。

代码如下:

public void ListView_Load_Lollipop() {
    DocumentFile documentFile = DocumentFile.fromTreeUri(this, Uri_Lollipop);
    Locale defaultLocale = Locale.getDefault();
    for(DocumentFile file : documentFile.listFiles()) {
        String FileName = file.getName();
        if(FileName.toLowerCase(defaultLocale).endsWith(".jpg") || 
           FileName.toLowerCase(defaultLocale).endsWith(".png") || 
           FileName.toLowerCase(defaultLocale).endsWith(".jpeg")) {

            mListViewObject = new ListViewObject();
            mListViewObject.setName(FileName);
            Uri uri = file.getUri();
            String imagePath = uri.getPath();
            mListViewObject.setImageUrl("file:///" + imagePath); 
            ListViewObject_List.add(mListViewObject); 
        }
    }
}

适配器:

public View getView(final int position, View convertView, ViewGroup parent) {       
  ViewHolder viewHolder = new ViewHolder();

  LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
  if (convertView == null) {
      convertView = inflater.inflate(R.layout.listview_layout, parent, false);
      viewHolder.imageView = (ImageView)convertView.findViewById(R.id.ListViewImage); 
      convertView.setTag(viewHolder);            
  } 
 else 
  {
     viewHolder = (ViewHolder)convertView.getTag();
  }

  Picasso.with(mContext)
  .load(getItem(position).getImageUrl())
  .fit()      
  .centerCrop()
  .into(viewHolder.imageView);
}
class ViewHolder {
RelativeLayout layout;
ImageView imageView;
}

有人可以指导我吗?

非常感谢

更新:16-4-28

我忘了添加这个

listViewAdapter = new ListViewAdapter(this, ListViewObject_List);
listView.setAdapter(listViewAdapter);

public void ListView_Load_Lollipop() {
    DocumentFile documentFile = DocumentFile.fromTreeUri(this, Uri_Lollipop);
    Locale defaultLocale = Locale.getDefault();
    for(DocumentFile file : documentFile.listFiles()) {
        String FileName = file.getName();
        if(FileName.toLowerCase(defaultLocale).endsWith(".jpg") || 
           FileName.toLowerCase(defaultLocale).endsWith(".png") || 
           FileName.toLowerCase(defaultLocale).endsWith(".jpeg")) {

            mListViewObject = new ListViewObject();
            mListViewObject.setName(FileName);
            Uri uri = file.getUri();
            String imagePath = uri.getPath();
            mListViewObject.setImageUrl("file:///" + imagePath); 
            ListViewObject_List.add(mListViewObject); 
        }
    }
}

感谢@CommonsWare 的回答:我能够通过将图像 Uri 而不是 图像路径 直接传递给来解决我的问题对象 class.

我希望它对以后的其他人有所帮助。

  1. 不要求 Uri 以文件扩展名结尾。在 DocumentFile 上使用 getType() 并查看 MIME 类型是否为图像类型。

  2. "file:///" + imagePath 完全没有意义。 Uri 不是文件。将 Uri 本身传递给任何 setImageUrl()

请检查getView()代码中的错误,添加代码:-

Picasso.Builder builder = new Picasso.Builder(mActivity);
    builder.listener(new Picasso.Listener() {

        @Override
        public void onImageLoadFailed(Picasso picasso, Uri uri, Exception exception) {
            Log.e("", "" + uri.getPath());
            exception.printStackTrace();
        }
    });

    Picasso pic = builder.build();
    pic.load(file).into(holder.mDataIV);

由此您将能够识别错误。它将帮助您解决问题。根据我的理解,如果无法找到图像,毕加索将无法加载图像。这是帮助程序 class,它将 return 您图像的实际路径:-

FilePathHelper.javaReferral Link

public class FilePathHelper {
@TargetApi(Build.VERSION_CODES.KITKAT)
public static String getPath(final Context context, final Uri uri) {

    final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;

    // DocumentProvider
    if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) {
        // ExternalStorageProvider
        if (isExternalStorageDocument(uri)) {
            final String docId = DocumentsContract.getDocumentId(uri);
            final String[] split = docId.split(":");
            final String type = split[0];

            if ("primary".equalsIgnoreCase(type)) {
                return Environment.getExternalStorageDirectory() + "/" + split[1];
            }

            // TODO handle non-primary volumes
        }
        // DownloadsProvider
        else if (isDownloadsDocument(uri)) {

            final String id = DocumentsContract.getDocumentId(uri);
            final Uri contentUri = ContentUris.withAppendedId(
                    Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));

            return getDataColumn(context, contentUri, null, null);
        }
        // MediaProvider
        else if (isMediaDocument(uri)) {
            final String docId = DocumentsContract.getDocumentId(uri);
            final String[] split = docId.split(":");
            final String type = split[0];

            Uri contentUri = null;
            if ("image".equals(type)) {
                contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
            } else if ("video".equals(type)) {
                contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
            } else if ("audio".equals(type)) {
                contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
            }

            final String selection = "_id=?";
            final String[] selectionArgs = new String[] {
                    split[1]
            };

            return getDataColumn(context, contentUri, selection, selectionArgs);
        }
    }
    // MediaStore (and general)
    else if ("content".equalsIgnoreCase(uri.getScheme())) {

        // Return the remote address
        if (isGooglePhotosUri(uri))
            return uri.getLastPathSegment();

        return getDataColumn(context, uri, null, null);
    }
    // File
    else if ("file".equalsIgnoreCase(uri.getScheme())) {
        return uri.getPath();
    }

    return null;
}

public static String getDataColumn(Context context, Uri uri, String selection,
                                   String[] selectionArgs) {

    Cursor cursor = null;
    final String column = "_data";
    final String[] projection = {
            column
    };

    try {
        cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs,
                null);
        if (cursor != null && cursor.moveToFirst()) {
            final int index = cursor.getColumnIndexOrThrow(column);
            return cursor.getString(index);
        }
    } finally {
        if (cursor != null)
            cursor.close();
    }
    return null;
}


/**
 * @param uri The Uri to check.
 * @return Whether the Uri authority is ExternalStorageProvider.
 */
public static boolean isExternalStorageDocument(Uri uri) {
    return "com.android.externalstorage.documents".equals(uri.getAuthority());
}

/**
 * @param uri The Uri to check.
 * @return Whether the Uri authority is DownloadsProvider.
 */
public static boolean isDownloadsDocument(Uri uri) {
    return "com.android.providers.downloads.documents".equals(uri.getAuthority());
}

/**
 * @param uri The Uri to check.
 * @return Whether the Uri authority is MediaProvider.
 */
public static boolean isMediaDocument(Uri uri) {
    return "com.android.providers.media.documents".equals(uri.getAuthority());
}

/**
 * @param uri The Uri to check.
 * @return Whether the Uri authority is Google Photos.
 */
public static boolean isGooglePhotosUri(Uri uri) {
    return "com.google.android.apps.photos.content".equals(uri.getAuthority());
    }
}

你只需要编辑你的方法 ListView_Load_Lollipop()

public void ListView_Load_Lollipop() {
    DocumentFile documentFile = DocumentFile.fromTreeUri(this, Uri_Lollipop);
    Locale defaultLocale = Locale.getDefault();
    for(DocumentFile file : documentFile.listFiles()) {
        String FileName = file.getName();
        if(FileName.toLowerCase(defaultLocale).endsWith(".jpg") ||
                FileName.toLowerCase(defaultLocale).endsWith(".png") ||
                FileName.toLowerCase(defaultLocale).endsWith(".jpeg")) {

            Uri uri = file.getUri();
            Uri docUri = DocumentsContract.buildDocumentUriUsingTree(uri,
                    DocumentsContract.getTreeDocumentId(uri));
            String path = FilePathHelper.getPath(this, docUri);
            mListData.add(path+ File.separator+FileName);
        }
    }
    NewImageAdapter newImageAdapter = new NewImageAdapter(this,this,mListData);
    mUserListRV.setAdapter(newImageAdapter);
}