从 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 作为正确的路径前缀。
这种方式可以提高性能效率,因为它不使用数据库。
我正在尝试使用一些 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 作为正确的路径前缀。 这种方式可以提高性能效率,因为它不使用数据库。