1

While selecting an image from a gallery in my application it doesn't crash but instead its unable to decode the stream of the path. Taking the picture directly from the camera is working fine but from the gallery its not here is my code in my activity result .

//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);

}

any help would be appreciated.

Mostafa Addam
  • 6,956
  • 4
  • 20
  • 38

2 Answers2

4

In later versions of Android (KitKat and above), the format of Uris returned from the gallery picker has changed, and it's not always possible to get a file path from a Uri without a lot of hassle, and sometimes it's not possible at all. So, it's better just to decode the bitmap using the Uri directly.

Change your decodeFile() function to accept a Uri and decode the image using BitmapFactory.decodeStream(), like this:

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);

}

Then you can simplify your onActivityResult() code to this:

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);
    }
}

If you have problems obtaining a valid Uri, see the accepted answer for this question for how to obtain a Uri inside OnActivityResult() with correct permissions on KitKat and above.

Community
  • 1
  • 1
samgak
  • 23,944
  • 4
  • 60
  • 82
0

Well I choose another approach for this thing. You cannot diffrentiate between you chose a picture from gallery or from a Camera Intent.

Here is my code.

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 ();
    }
Murtaza Khursheed Hussain
  • 15,176
  • 7
  • 58
  • 83