Mic*_*ler 265 android image gallery android-intent
我正试图在我的应用程序内打开Gallery内置应用程序中的图像/图片.
我有一张图片的URI(图片位于SD卡上).
你有什么建议吗?
hcp*_*cpl 349
这是一个完整的解决方案.我刚刚用@mad的答案中提供的信息更新了这个示例代码.另请查看@Khobaib下面的解决方案,解释如何处理picasa图像.
我刚刚回顾了我的原始答案并创建了一个简单的Android Studio项目,您可以从github签出并直接在您的系统上导入.
https://github.com/hanscappelle/SO-2169649
(注意多文件选择仍然需要工作)
由于用户疯狂,支持文件浏览器中的图像.
public class BrowsePictureActivity extends Activity {
    // this is the action code we use in our intent, 
    // this way we know we're looking at the response from our own action
    private static final int SELECT_PICTURE = 1;
    private String selectedImagePath;
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        findViewById(R.id.Button01)
                .setOnClickListener(new OnClickListener() {
                    public void onClick(View arg0) {
                        // in onCreate or any event where your want the user to
                        // select a file
                        Intent intent = new Intent();
                        intent.setType("image/*");
                        intent.setAction(Intent.ACTION_GET_CONTENT);
                        startActivityForResult(Intent.createChooser(intent,
                                "Select Picture"), SELECT_PICTURE);
                    }
                });
    }
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (resultCode == RESULT_OK) {
            if (requestCode == SELECT_PICTURE) {
                Uri selectedImageUri = data.getData();
                selectedImagePath = getPath(selectedImageUri);
            }
        }
    }
    /**
     * helper to retrieve the path of an image URI
     */
    public String getPath(Uri uri) {
            // just some safety built in 
            if( uri == null ) {
                // TODO perform some logging or show user feedback
                return null;
            }
            // try to retrieve the image from the media store first
            // this will only work for images selected from gallery
            String[] projection = { MediaStore.Images.Media.DATA };
            Cursor cursor = managedQuery(uri, projection, null, null, null);
            if( cursor != null ){
                int column_index = cursor
                .getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
                cursor.moveToFirst();
                String path = cursor.getString(column_index);
                cursor.close();
                return path;
            }
            // this is our fallback here
            return uri.getPath();
    }
}
由于有人在评论中要求提供信息,因此最好收集信息.
EXTRA_ALLOW_MULTIPLE在intent上设置一个额外的参数:
intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
并在结果处理检查该参数:
if (Intent.ACTION_SEND_MULTIPLE.equals(data.getAction()))
        && Intent.hasExtra(Intent.EXTRA_STREAM)) {
    // retrieve a collection of selected images
    ArrayList<Parcelable> list = intent.getParcelableArrayListExtra(Intent.EXTRA_STREAM);
    // iterate over these images
    if( list != null ) {
       for (Parcelable parcel : list) {
         Uri uri = (Uri) parcel;
         // TODO handle the images one by one here
       }
   }
} 
请注意,只有API级别18+支持此功能.
mad*_*mad 135
这是hcpl发布的精细代码的更新.但这适用于OI文件管理器,astro文件管理器和媒体库(已测试).所以我想它会适用于每个文件管理器(除了提到的那些之外还有很多其他文件管理器吗?).对他写的代码做了一些修改.
public class BrowsePicture extends Activity {
    //YOU CAN EDIT THIS TO WHATEVER YOU WANT
    private static final int SELECT_PICTURE = 1;
    private String selectedImagePath;
    //ADDED
    private String filemanagerstring;
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        ((Button) findViewById(R.id.Button01))
        .setOnClickListener(new OnClickListener() {
            public void onClick(View arg0) {
                // in onCreate or any event where your want the user to
                // select a file
                Intent intent = new Intent();
                intent.setType("image/*");
                intent.setAction(Intent.ACTION_GET_CONTENT);
                startActivityForResult(Intent.createChooser(intent,
                        "Select Picture"), SELECT_PICTURE);
            }
        });
    }
    //UPDATED
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (resultCode == RESULT_OK) {
            if (requestCode == SELECT_PICTURE) {
                Uri selectedImageUri = data.getData();
                //OI FILE Manager
                filemanagerstring = selectedImageUri.getPath();
                //MEDIA GALLERY
                selectedImagePath = getPath(selectedImageUri);
                //DEBUG PURPOSE - you can delete this if you want
                if(selectedImagePath!=null)
                    System.out.println(selectedImagePath);
                else System.out.println("selectedImagePath is null");
                if(filemanagerstring!=null)
                    System.out.println(filemanagerstring);
                else System.out.println("filemanagerstring is null");
                //NOW WE HAVE OUR WANTED STRING
                if(selectedImagePath!=null)
                    System.out.println("selectedImagePath is the right one for you!");
                else
                    System.out.println("filemanagerstring is the right one for you!");
            }
        }
    }
    //UPDATED!
    public String getPath(Uri uri) {
        String[] projection = { MediaStore.Images.Media.DATA };
        Cursor cursor = managedQuery(uri, projection, null, null, null);
        if(cursor!=null)
        {
            //HERE YOU WILL GET A NULLPOINTER IF CURSOR IS NULL
            //THIS CAN BE, IF YOU USED OI FILE MANAGER FOR PICKING THE MEDIA
            int column_index = cursor
            .getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
            cursor.moveToFirst();
            return cursor.getString(column_index);
        }
        else return null;
    }
abb*_*ath 24
hcpl的方法完全可以在KitKat之前完成,但不能使用DocumentsProvider API.为此,只需按照文档提供者的官方Android教程:https://developer.android.com/guide/topics/providers/document-provider.html - >打开文档,位图部分.
简单地说,我使用了hcpl的代码并对其进行了扩展:如果带有检索到的图像路径的文件抛出异常,我会调用此函数:
private Bitmap getBitmapFromUri(Uri uri) throws IOException {
        ParcelFileDescriptor parcelFileDescriptor =
             getContentResolver().openFileDescriptor(uri, "r");
        FileDescriptor fileDescriptor = parcelFileDescriptor.getFileDescriptor();
        Bitmap image = BitmapFactory.decodeFileDescriptor(fileDescriptor);
        parcelFileDescriptor.close();
        return image;
}
在Nexus 5上测试过.
小智 11
基于上面的代码,我反映了下面的代码,可能更适合:
public String getPath(Uri uri) {
    String selectedImagePath;
    //1:MEDIA GALLERY --- query from MediaStore.Images.Media.DATA
    String[] projection = { MediaStore.Images.Media.DATA };
    Cursor cursor = managedQuery(uri, projection, null, null, null);
    if(cursor != null){
        int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
        cursor.moveToFirst();
        selectedImagePath = cursor.getString(column_index);
    }else{
        selectedImagePath = null;
    }
    if(selectedImagePath == null){
        //2:OI FILE Manager --- call method: uri.getPath()
        selectedImagePath = uri.getPath();
    }
    return selectedImagePath;
}
Kho*_*aib 11
我从@hcpl和@mad那里得到了解决方案.hcpl的解决方案很好地支持了画廊中的本地图像和疯狂提供了更好的解决方案 - 它也有助于加载OI/Astro/Dropbox图像.但是在我的应用程序中,在处理现在集成在Android Gallery中的picasa库时,两种解决方案都失败了.
我搜索并分析了一下,最终得到了一个更好,更优雅的解决方案,克服了这个限制.感谢Dimitar Darazhanski的博客,在这种情况下帮助了我,我修改了一下以便更容易理解.这是我的解决方案 -
public class BrowsePicture extends Activity {
//YOU CAN EDIT THIS TO WHATEVER YOU WANT
private static final int SELECT_PICTURE = 1;
private String selectedImagePath;
//ADDED
private String filemanagerstring;
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    ((Button) findViewById(R.id.Button01))
    .setOnClickListener(new OnClickListener() {
        public void onClick(View arg0) {
            // in onCreate or any event where your want the user to
            // select a file
            Intent intent = new Intent();
            intent.setType("image/*");
            intent.setAction(Intent.ACTION_GET_CONTENT);
            startActivityForResult(Intent.createChooser(intent,
                    "Select Picture"), SELECT_PICTURE);
        }
    });
}
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (resultCode == RESULT_OK) {
        if (requestCode == SELECT_PICTURE) {
            Uri selectedImageUri = data.getData();
            Log.d("URI VAL", "selectedImageUri = " + selectedImageUri.toString());
            selectedImagePath = getPath(selectedImageUri);
            if(selectedImagePath!=null){         
                // IF LOCAL IMAGE, NO MATTER IF ITS DIRECTLY FROM GALLERY (EXCEPT PICASSA ALBUM),
                // OR OI/ASTRO FILE MANAGER. EVEN DROPBOX IS SUPPORTED BY THIS BECAUSE DROPBOX DOWNLOAD THE IMAGE 
                // IN THIS FORM - file:///storage/emulated/0/Android/data/com.dropbox.android/...
                System.out.println("local image"); 
            }
            else{
                System.out.println("picasa image!");
                loadPicasaImageFromGallery(selectedImageUri);
            }
        }
    }
}
// NEW METHOD FOR PICASA IMAGE LOAD
private void loadPicasaImageFromGallery(final Uri uri) {
    String[] projection = {  MediaColumns.DATA, MediaColumns.DISPLAY_NAME };
    Cursor cursor = getContentResolver().query(uri, projection, null, null, null);
    if(cursor != null) {
        cursor.moveToFirst();
        int columnIndex = cursor.getColumnIndex(MediaColumns.DISPLAY_NAME);
        if (columnIndex != -1) {
            new Thread(new Runnable() {
                // NEW THREAD BECAUSE NETWORK REQUEST WILL BE MADE THAT WILL BE A LONG PROCESS & BLOCK UI
                // IF CALLED IN UI THREAD 
                public void run() {
                    try {
                        Bitmap bitmap = android.provider.MediaStore.Images.Media.getBitmap(getContentResolver(), uri);
                        // THIS IS THE BITMAP IMAGE WE ARE LOOKING FOR.
                    } catch (Exception ex) {
                        ex.printStackTrace();
                    }
                }
            }).start();
        }
    }
    cursor.close();
}
public String getPath(Uri uri) {
    String[] projection = {  MediaColumns.DATA};
    Cursor cursor = getContentResolver().query(uri, projection, null, null, null);
    if(cursor != null) {
        //HERE YOU WILL GET A NULLPOINTER IF CURSOR IS NULL
        //THIS CAN BE, IF YOU USED OI FILE MANAGER FOR PICKING THE MEDIA
        cursor.moveToFirst();
        int columnIndex = cursor.getColumnIndexOrThrow(MediaColumns.DATA);
        String filePath = cursor.getString(columnIndex);
        cursor.close();
        return filePath;
    }
    else 
        return uri.getPath();               // FOR OI/ASTRO/Dropbox etc
}
检查一下,如果有问题,请告诉我.我已经对它进行了测试,并且在每种情
希望这对每个人都有帮助.
Ant*_*ney 10
假设您的SD卡目录中有一个图像文件夹仅用于图像.
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
// tells your intent to get the contents
// opens the URI for your image directory on your sdcard
intent.setType("file:///sdcard/image/*"); 
startActivityForResult(intent, 1);
然后,您可以决定要对活动中的内容做什么.
这是一个检索图像路径名的示例,使用您的代码对其进行测试,以确保您可以处理返回的结果.您可以根据需要更改代码以更好地满足您的需求.
protected final void onActivityResult(final int requestCode, final int
                     resultCode, final Intent i) {
    super.onActivityResult(requestCode, resultCode, i);
  // this matches the request code in the above call
  if (requestCode == 1) {
      Uri _uri = i.getData();
    // this will be null if no image was selected...
    if (_uri != null) {
      // now we get the path to the image file
     cursor = getContentResolver().query(_uri, null,
                                      null, null, null);
     cursor.moveToFirst();
     String imageFilePath = cursor.getString(0);
     cursor.close();
     }
   }
我的建议是尝试检索图像正常工作,我认为问题是访问SD卡上的图像的内容.看看在SD卡上显示图像.
如果您可以通过提供正确提供程序的示例来启动并运行,那么您应该能够找到适合您的代码的解决方法.
通过使用您的进度更新此问题让我更新.祝好运
hda*_*nte 10
这是我对这个主题的重新审视,收集了这里的所有信息,以及其他相关的堆栈溢出问题.它返回来自某个提供程序的图像,同时处理内存不足的情况和图像旋转.它支持图库,picasa和文件管理器,如下拉框.用法很简单:作为输入,构造函数接收内容解析器和uri.输出是最终的位图.
/**
 * Creates resized images without exploding memory. Uses the method described in android
 * documentation concerning bitmap allocation, which is to subsample the image to a smaller size,
 * close to some expected size. This is required because the android standard library is unable to
 * create a reduced size image from an image file using memory comparable to the final size (and
 * loading a full sized multi-megapixel picture for processing may exceed application memory budget).
 */
public class UserPicture {
    static int MAX_WIDTH = 600;
    static int MAX_HEIGHT = 800;
    Uri uri;
    ContentResolver resolver;
    String path;
    Matrix orientation;
    int storedHeight;
    int storedWidth;
    public UserPicture(Uri uri, ContentResolver resolver) {
        this.uri = uri;
        this.resolver = resolver;
    }
    private boolean getInformation() throws IOException {
        if (getInformationFromMediaDatabase())
            return true;
        if (getInformationFromFileSystem())
            return true;
        return false;
    }
    /* Support for gallery apps and remote ("picasa") images */
    private boolean getInformationFromMediaDatabase() {
        String[] fields = { Media.DATA, ImageColumns.ORIENTATION };
        Cursor cursor = resolver.query(uri, fields, null, null, null);
        if (cursor == null)
            return false;
        cursor.moveToFirst();
        path = cursor.getString(cursor.getColumnIndex(Media.DATA));
        int orientation = cursor.getInt(cursor.getColumnIndex(ImageColumns.ORIENTATION));
        this.orientation = new Matrix();
        this.orientation.setRotate(orientation);
        cursor.close();
        return true;
    }
    /* Support for file managers and dropbox */
    private boolean getInformationFromFileSystem() throws IOException {
        path = uri.getPath();
        if (path == null)
            return false;
        ExifInterface exif = new ExifInterface(path);
        int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION,
                                               ExifInterface.ORIENTATION_NORMAL);
        this.orientation = new Matrix();
        switch(orientation) {
            case ExifInterface.ORIENTATION_NORMAL:
                /* Identity matrix */
                break;
            case ExifInterface.ORIENTATION_FLIP_HORIZONTAL:
                this.orientation.setScale(-1, 1);
                break;
            case ExifInterface.ORIENTATION_ROTATE_180:
                this.orientation.setRotate(180);
                break;
            case ExifInterface.ORIENTATION_FLIP_VERTICAL:
                this.orientation.setScale(1, -1);
                break;
            case ExifInterface.ORIENTATION_TRANSPOSE:
                this.orientation.setRotate(90);
                this.orientation.postScale(-1, 1);
                break;
            case ExifInterface.ORIENTATION_ROTATE_90:
                this.orientation.setRotate(90);
                break;
            case ExifInterface.ORIENTATION_TRANSVERSE:
                this.orientation.setRotate(-90);
                this.orientation.postScale(-1, 1);
                break;
            case ExifInterface.ORIENTATION_ROTATE_270:
                this.orientation.setRotate(-90);
                break;
        }
        return true;
    }
    private boolean getStoredDimensions() throws IOException {
        InputStream input = resolver.openInputStream(uri);
        Options options = new Options();
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeStream(resolver.openInputStream(uri), null, options);
        /* The input stream could be reset instead of closed and reopened if it were possible
           to reliably wrap the input stream on a buffered stream, but it's not possible because
           decodeStream() places an upper read limit of 1024 bytes for a reset to be made (it calls
           mark(1024) on the stream). */
        input.close();
        if (options.outHeight <= 0 || options.outWidth <= 0)
            return false;
        storedHeight = options.outHeight;
        storedWidth = options.outWidth;
        return true;
    }
    public Bitmap getBitmap() throws IOException {
        if (!getInformation())
            throw new FileNotFoundException();
        if (!getStoredDimensions())
            throw new InvalidObjectException(null);
        RectF rect = new RectF(0, 0, storedWidth, storedHeight);
        orientation.mapRect(rect);
        int width = (int)rect.width();
        int height = (int)rect.height();
        int subSample = 1;
        while (width > MAX_WIDTH || height > MAX_HEIGHT) {
            width /= 2;
            height /= 2;
            subSample *= 2;
        }
        if (width == 0 || height == 0)
            throw new InvalidObjectException(null);
        Options options = new Options();
        options.inSampleSize = subSample;
        Bitmap subSampled = BitmapFactory.decodeStream(resolver.openInputStream(uri), null, options);
        Bitmap picture;
        if (!orientation.isIdentity()) {
            picture = Bitmap.createBitmap(subSampled, 0, 0, options.outWidth, options.outHeight,
                                          orientation, false);
            subSampled.recycle();
        } else
            picture = subSampled;
        return picture;
    }
}
参考文献:
有两个关于图像选择器的有用教程,其中包含可下载的源代码:
但是,应用程序将被强制关闭,您可以通过将android:configChanges属性添加到Manifest文件中的主要活动来修复它,如:
<activity android:name=".MainActivity"
                  android:label="@string/app_name" android:configChanges="keyboardHidden|orientation" >
似乎相机API失去了控制方向,所以这将有助于它.:)
下面解决方案工作2.3(姜饼)-4.4(Kitkat),5.0(棒棒糖)和6.0(棉花糖)也: -
步骤1打开图库以选择图片的代码:
public static final int PICK_IMAGE = 1;
private void takePictureFromGalleryOrAnyOtherFolder() 
{
    Intent intent = new Intent();
    intent.setType("image/*");
    intent.setAction(Intent.ACTION_GET_CONTENT);
    startActivityForResult(Intent.createChooser(intent, "Select Picture"), PICK_IMAGE);
}
步骤2获取数据的代码onActivityResult:
 @Override
 protected void onActivityResult(int requestCode, int resultCode, Intent data) {
            super.onActivityResult(requestCode, resultCode, data);
            if (resultCode == Activity.RESULT_OK) {
               if (requestCode == PICK_IMAGE) {
                    Uri selectedImageUri = data.getData();
                    String imagePath = getRealPathFromURI(selectedImageUri);
                   //Now you have imagePath do whatever you want to do now
                 }//end of inner if
             }//end of outer if
      }
 public String getRealPathFromURI(Uri contentUri) {
        //Uri contentUri = Uri.parse(contentURI);
        String[] projection = { MediaStore.Images.Media.DATA };
        Cursor cursor = null;
        try {
            if (Build.VERSION.SDK_INT > 19) {
                // Will return "image:x*"
                String wholeID = DocumentsContract.getDocumentId(contentUri);
                // Split at colon, use second item in the array
                String id = wholeID.split(":")[1];
                // where id is equal to
                String sel = MediaStore.Images.Media._ID + "=?";
                cursor = context.getContentResolver().query(
                        MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
                        projection, sel, new String[] { id }, null);
            } else {
                cursor = context.getContentResolver().query(contentUri,
                        projection, null, null, null);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        String path = null;
        try {
            int column_index = cursor
                    .getColumnIndex(MediaStore.Images.Media.DATA);
            cursor.moveToFirst();
            path = cursor.getString(column_index).toString();
            cursor.close();
        } catch (NullPointerException e) {
            e.printStackTrace();
        }
        return path;
    }
小智 6
要显示图像和视频,请尝试:
    Intent intent = new Intent();
    intent = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
    startActivityForResult(intent, 1);
    startActivityForResult(Intent.createChooser(intent,"Wybierz plik"), SELECT_FILE);
以防它有帮助; 我这样做是为了得到位图:
InputStream is = context.getContentResolver().openInputStream(imageUri);
Bitmap bitmap = BitmapFactory.decodeStream(is);
小智 5
以上答案是正确的.我遇到了一个不同的问题,在HTC M8中,我的应用程序在从图库中选择图像时崩溃了.我为图像路径获取空值.我使用以下解决方案进行了修复和优化.在onActivityResult方法中
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if ((requestCode == RESULT_LOAD_IMAGE) && (resultCode == RESULT_OK)) {
     if (data != null) {
            Uri selectedImageUri = null;
            selectedImageUri = data.getData();
            String[] filePathColumn = { MediaStore.Images.Media.DATA };
            Cursor imageCursor = mainActivity.getContentResolver().query(
                    selectedImageUri, filePathColumn, null, null, null);
            if (imageCursor == null) {
                return;
            }
            imageCursor.moveToFirst();
            int columnIndex = imageCursor.getColumnIndex(filePathColumn[0]);
            picturePath = imageCursor.getString(columnIndex);
            if (picturePath == null) {
                picturePath = selectedImageUri.getPath();
                String wholeID = DocumentsContract
                        .getDocumentId(selectedImage);
                // Split at colon, use second item in the array
                String id = wholeID.split(":")[1];
                String[] column = { MediaStore.Images.Media.DATA };
                // where id is equal to
                String sel = MediaStore.Images.Media._ID + "=?";
                Cursor cursor = mainActivity.getContentResolver().query(
                        MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
                        column, sel, new String[] { id }, null);
                columnIndex = cursor.getColumnIndex(column[0]);
                if (cursor.moveToFirst()) {
                    picturePath = cursor.getString(columnIndex);
                }
                cursor.close();
            }
            picturePathAbs = new File(picturePath).getAbsolutePath();
            imageCursor.close();
        }
}
| 归档时间: | 
 | 
| 查看次数: | 304239 次 | 
| 最近记录: |