我试图从我的应用程序中打开画廊内置应用程序中的图像/图片。

我有一个图片的URI(图片位于SD卡上)。

你有什么建议吗?


当前回答

请找到从图库中选择单个图像的答案

import android.app.Activity;
import android.net.Uri;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;

import java.io.ByteArrayOutputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;

public class PickImage extends Activity {

    Button btnOpen, btnGet, btnPick;
    TextView textInfo1, textInfo2;
    ImageView imageView;

    private static final int RQS_OPEN_IMAGE = 1;
    private static final int RQS_GET_IMAGE = 2;
    private static final int RQS_PICK_IMAGE = 3;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.image_pick);
        btnOpen = (Button)findViewById(R.id.open);
        btnGet = (Button)findViewById(R.id.get);
        btnPick = (Button)findViewById(R.id.pick);
        textInfo1 = (TextView)findViewById(R.id.info1);
        textInfo2 = (TextView)findViewById(R.id.info2);
        imageView = (ImageView) findViewById(R.id.image);

        btnOpen.setOnClickListener(btnOpenOnClickListener);
        btnGet.setOnClickListener(btnGetOnClickListener);
        btnPick.setOnClickListener(btnPickOnClickListener);
    }

    View.OnClickListener btnOpenOnClickListener = new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Intent intent = new Intent();
            intent.setAction(Intent.ACTION_OPEN_DOCUMENT);
            intent.addCategory(Intent.CATEGORY_OPENABLE);
            intent.setType("image/*");

            startActivityForResult(intent, RQS_OPEN_IMAGE);
        }
    };

    View.OnClickListener btnGetOnClickListener = new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Intent intent = new Intent();
            intent.setAction(Intent.ACTION_GET_CONTENT);
            intent.addCategory(Intent.CATEGORY_OPENABLE);
            intent.setType("image/*");

            startActivityForResult(intent, RQS_OPEN_IMAGE);
        }
    };

    View.OnClickListener btnPickOnClickListener = new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Intent intent = new Intent(Intent.ACTION_PICK,
                    android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
            startActivityForResult(intent, RQS_PICK_IMAGE);
        }
    };

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (resultCode == Activity.RESULT_OK) {


            if (requestCode == RQS_OPEN_IMAGE ||
                    requestCode == RQS_GET_IMAGE ||
                    requestCode == RQS_PICK_IMAGE) {

                imageView.setImageBitmap(null);
                textInfo1.setText("");
                textInfo2.setText("");

                Uri mediaUri = data.getData();
                textInfo1.setText(mediaUri.toString());
                String mediaPath = mediaUri.getPath();
                textInfo2.setText(mediaPath);

                //display the image
                try {
                    InputStream inputStream = getBaseContext().getContentResolver().openInputStream(mediaUri);
                    Bitmap bm = BitmapFactory.decodeStream(inputStream);

                   ByteArrayOutputStream stream = new ByteArrayOutputStream();
                    byte[] byteArray = stream.toByteArray();

                    imageView.setImageBitmap(bm);

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

其他回答

以上答案正确。我遇到了一个不同的问题,在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();
        }

}

这是我对这个主题的回顾,收集了这里的所有信息,再加上其他相关的堆栈溢出问题。它从某些提供者返回图像,同时处理内存不足的情况和图像旋转。它支持画廊,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;
    }
}

引用:

http://developer.android.com/training/displaying-bitmaps/index.html 通过编程方式从Android内置的Gallery应用程序中获取/选择一张图像 在将图像加载到位图对象时出现奇怪的内存不足问题 使用ExifInterface设置图像方向 https://gist.github.com/9re/1990019 如何获得位图信息,然后解码位图从internet-inputStream?

请找到从图库中选择单个图像的答案

import android.app.Activity;
import android.net.Uri;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;

import java.io.ByteArrayOutputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;

public class PickImage extends Activity {

    Button btnOpen, btnGet, btnPick;
    TextView textInfo1, textInfo2;
    ImageView imageView;

    private static final int RQS_OPEN_IMAGE = 1;
    private static final int RQS_GET_IMAGE = 2;
    private static final int RQS_PICK_IMAGE = 3;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.image_pick);
        btnOpen = (Button)findViewById(R.id.open);
        btnGet = (Button)findViewById(R.id.get);
        btnPick = (Button)findViewById(R.id.pick);
        textInfo1 = (TextView)findViewById(R.id.info1);
        textInfo2 = (TextView)findViewById(R.id.info2);
        imageView = (ImageView) findViewById(R.id.image);

        btnOpen.setOnClickListener(btnOpenOnClickListener);
        btnGet.setOnClickListener(btnGetOnClickListener);
        btnPick.setOnClickListener(btnPickOnClickListener);
    }

    View.OnClickListener btnOpenOnClickListener = new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Intent intent = new Intent();
            intent.setAction(Intent.ACTION_OPEN_DOCUMENT);
            intent.addCategory(Intent.CATEGORY_OPENABLE);
            intent.setType("image/*");

            startActivityForResult(intent, RQS_OPEN_IMAGE);
        }
    };

    View.OnClickListener btnGetOnClickListener = new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Intent intent = new Intent();
            intent.setAction(Intent.ACTION_GET_CONTENT);
            intent.addCategory(Intent.CATEGORY_OPENABLE);
            intent.setType("image/*");

            startActivityForResult(intent, RQS_OPEN_IMAGE);
        }
    };

    View.OnClickListener btnPickOnClickListener = new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Intent intent = new Intent(Intent.ACTION_PICK,
                    android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
            startActivityForResult(intent, RQS_PICK_IMAGE);
        }
    };

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (resultCode == Activity.RESULT_OK) {


            if (requestCode == RQS_OPEN_IMAGE ||
                    requestCode == RQS_GET_IMAGE ||
                    requestCode == RQS_PICK_IMAGE) {

                imageView.setImageBitmap(null);
                textInfo1.setText("");
                textInfo2.setText("");

                Uri mediaUri = data.getData();
                textInfo1.setText(mediaUri.toString());
                String mediaPath = mediaUri.getPath();
                textInfo2.setText(mediaPath);

                //display the image
                try {
                    InputStream inputStream = getBaseContext().getContentResolver().openInputStream(mediaUri);
                    Bitmap bm = BitmapFactory.decodeStream(inputStream);

                   ByteArrayOutputStream stream = new ByteArrayOutputStream();
                    byte[] byteArray = stream.toByteArray();

                    imageView.setImageBitmap(bm);

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

以下解决方案适用于2.3(姜饼)-4.4(奇巧),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;
    }

除了前面的答案,如果你在获得正确的路径(如AndroZip)有问题,你可以使用这个:

  public String getPath(Uri uri ,ContentResolver contentResolver) {
        String[] projection = {  MediaStore.MediaColumns.DATA};
        Cursor cursor;
        try{
            cursor = contentResolver.query(uri, projection, null, null, null);
        } catch (SecurityException e){
            String path = uri.getPath();
            String result = tryToGetStoragePath(path);
            return  result;
        }
        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(MediaStore.MediaColumns.DATA);
            String filePath = cursor.getString(columnIndex);
            cursor.close();
            return filePath;
        }
        else
            return uri.getPath();               // FOR OI/ASTRO/Dropbox etc
    }

    private String tryToGetStoragePath(String path) {
        int actualPathStart = path.indexOf("//storage");
        String result = path;

        if(actualPathStart!= -1 && actualPathStart< path.length())
            result = path.substring(actualPathStart+1 , path.length());

        return result;
    }