选择图像时无法解码流

unable to decode stream while selecting an image

在我的应用程序中从图库中选择图像时,它没有崩溃,而是无法解码路径流。直接从相机拍摄照片效果很好,但从图库中它不在这里是我 activity 结果中的代码。

//enter code here
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    Uri selectedImageUri = null;
    String filePath = null;
    switch (requestCode) {
        case PICK_IMAGE:
            if (resultCode == Activity.RESULT_OK)
            {
                selectedImageUri = data.getData();
                name = getPath(selectedImageUri);
            }
            break;
        case PICK_Camera_IMAGE:
            if (resultCode == RESULT_OK) {
                //use imageUri here to access the image
                selectedImageUri = imageUri;
            } else if (resultCode == RESULT_CANCELED) {
                Toast.makeText(this, "Picture was not taken", Toast.LENGTH_SHORT).show();
            } else {
                Toast.makeText(this, "Picture was not taken", Toast.LENGTH_SHORT).show();
            }
            break;
    }
    if(selectedImageUri != null)
    {
        try
        {
            // OI FILE Manager
            String filemanagerstring = selectedImageUri.getPath();


            // MEDIA GALLERY
            String selectedImagePath = getPath(selectedImageUri);

            if (selectedImagePath != null) {
                filePath = selectedImagePath;

            } else if (filemanagerstring != null) {
                filePath = filemanagerstring;
            } else {
                Toast.makeText(getApplicationContext(), "Unknown path",
                        Toast.LENGTH_LONG).show();
                Log.e("Bitmap", "Unknown path");
            }

            if (filePath != null)
            {
                decodeFile(filePath);
            } else {
                bitmap = null;
            }
        }
        catch (Exception e)
        {
            Toast.makeText(getApplicationContext(), "Internal error",
                    Toast.LENGTH_LONG).show();
            Log.e(e.getClass().getName(), e.getMessage(), e);
        }
    }
}
  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();
        return cursor.getString(column_index);
    }
    // this is our fallback here
    return uri.getPath();
}
public void decodeFile(String filePath)
{
    // Decode image size
    BitmapFactory.Options o = new BitmapFactory.Options();
    o.inJustDecodeBounds = true;
    BitmapFactory.decodeFile(filePath, o);

    // The new size we want to scale to
    final int REQUIRED_SIZE = 1024;

    // Find the correct scale value. It should be the power of 2.
    int width_tmp = o.outWidth, height_tmp = o.outHeight;
    int scale = 1;
    while (true)
    {
        if (width_tmp < REQUIRED_SIZE && height_tmp < REQUIRED_SIZE)
            break;
        width_tmp /= 2;
        height_tmp /= 2;
        scale *= 2;
    }

    // Decode with inSampleSize
    BitmapFactory.Options o2 = new BitmapFactory.Options();
    o2.inSampleSize = scale;
    bitmap = BitmapFactory.decodeFile(filePath, o2);

    //imgView.setImageBitmap(bitmap);

}

如有任何帮助,我们将不胜感激。

在 Android (KitKat and above) 的更高版本中,从图库选择器返回的 Uris 的格式已经改变,并不总是可以从中获取文件路径a Uri 没有很多麻烦,有时根本不可能。因此,最好直接使用 Uri 解码位图。

更改您的 decodeFile() 函数以接受 Uri 并使用 BitmapFactory.decodeStream() 解码图像,如下所示:

public void decodeFile(Uri fileUri)
{
    // Decode image size
    BitmapFactory.Options o = new BitmapFactory.Options();
    o.inJustDecodeBounds = true;
    BitmapFactory.decodeStream(getContentResolver().openInputStream(fileUri), null, o);

    // The new size we want to scale to
    final int REQUIRED_SIZE = 1024;

    // Find the correct scale value. It should be the power of 2.
    int width_tmp = o.outWidth, height_tmp = o.outHeight;
    int scale = 1;
    while (true)
    {
        if (width_tmp < REQUIRED_SIZE && height_tmp < REQUIRED_SIZE)
            break;
        width_tmp /= 2;
        height_tmp /= 2;
        scale *= 2;
    }

    // Decode with inSampleSize
    BitmapFactory.Options o2 = new BitmapFactory.Options();
    o2.inSampleSize = scale;
    bitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(fileUri), null, o2);

    //imgView.setImageBitmap(bitmap);

}

然后您可以将您的 onActivityResult() 代码简化为:

if(selectedImageUri != null)
{
    try
    {
        decodeFile(selectedImageUri);
    }
    catch (Exception e)
    {
        Toast.makeText(getApplicationContext(), "Internal error",
                Toast.LENGTH_LONG).show();
        Log.e(e.getClass().getName(), e.getMessage(), e);
    }
}

如果您在获取有效的 Uri 时遇到问题,请参阅 this question 的已接受答案,了解如何在 OnActivityResult() 中获取 Uri 以及对 KitKat 及更高版本的正确权限。

好吧,我为这件事选择了另一种方法。您无法区分是从图库还是从 Camera Intent 选择图片。

这是我的代码。

public class Chooser extends Activity {
    ImageView   imageView1;
    private Uri outputFileUri;

    @Override
    protected void onCreate (Bundle savedInstanceState) {

        super.onCreate (savedInstanceState);
        setContentView (R.layout.activity_main);

        imageView1 = (ImageView) this.findViewById (R.id.imageView1);
        Button frag1 = (Button) this.findViewById (R.id.frag1);
        frag1.setOnClickListener (new OnClickListener () {

            @Override
            public void onClick (View v) {

                choosePic (null);

            }
        });

    }

    public void choosePic (View view) {

        // Determine Uri of camera image to save.
        final File root = new File (Environment.getExternalStorageDirectory () + File.separator + "DCIM/Camera" + File.separator);
        root.mkdirs ();
        final String fname = "image_" + getRandomName () + ".jpeg";
        final File sdImageMainDirectory = new File (root, fname);
        outputFileUri = Uri.fromFile (sdImageMainDirectory);

        // Camera.
        final List<Intent> cameraIntents = new ArrayList<Intent> ();
        final Intent captureIntent = new Intent (android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
        captureIntent.putExtra (MediaStore.EXTRA_OUTPUT, Uri.fromFile (sdImageMainDirectory));
        final PackageManager packageManager = getPackageManager ();
        final List<ResolveInfo> listCam = packageManager.queryIntentActivities (captureIntent, 0);
        for (ResolveInfo res : listCam) {
            final String packageName = res.activityInfo.packageName;
            final Intent intent = new Intent (captureIntent);
            intent.setComponent (new ComponentName (res.activityInfo.packageName, res.activityInfo.name));
            intent.setPackage (packageName);
            intent.putExtra (MediaStore.EXTRA_OUTPUT, outputFileUri);
            cameraIntents.add (intent);
        }

        // Filesystem.
        final Intent galleryIntent = new Intent ();
        galleryIntent.setType ("image/*");
        galleryIntent.setAction (Intent.ACTION_GET_CONTENT);

        // Chooser of filesystem options.
        final Intent chooserIntent = Intent.createChooser (galleryIntent, "Select Source");

        // Add the camera options.
        chooserIntent.putExtra (Intent.EXTRA_INITIAL_INTENTS, cameraIntents.toArray (new Parcelable[] {}));

        startActivityForResult (chooserIntent, 1);
    }

    @Override
    protected void onActivityResult (int requestCode, int resultCode, Intent data) {

        super.onActivityResult (requestCode, resultCode, data);

        if (resultCode == RESULT_OK) {

            if (requestCode == 1) {
                final boolean isCamera;
                if (data == null) {
                    isCamera = true;
                }
                else {
                    final String action = data.getAction ();
                    if (action == null) {
                        isCamera = false;
                    }
                    else {
                        isCamera = action.equals (android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
                    }
                }

                Uri selectedImageUri;
                if (isCamera) {
                    selectedImageUri = outputFileUri;
                }
                else {
                    selectedImageUri = data == null ? null : data.getData ();
                }

                imageView1.setImageURI (selectedImageUri);
            }
        }
    }

    public String getRandomName () {

        Random r = new Random (); // just create one and keep it around
        String alphabet = "abcdefghijklmnopqrstuvwxyz1234567890";

        final int N = 10;
        StringBuilder sb = new StringBuilder ();
        for (int i = 0; i < N; i++) {
            sb.append (alphabet.charAt (r.nextInt (alphabet.length ())));
        }
        return sb.toString ();
    }