Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android set image from URI on ImageView

Tags:

android

UPDATED with more code

I am trying to grab a picture that was just taken and set it to an ImageView programmatically.

The picture button is pressed,

picture_button.setOnClickListener(new View.OnClickListener() {
    public void onClick(View v) {
        takePhoto(mTextureView);
    }
});

it runs the takePhoto method:

public void takePhoto(View view) {
    try {
        mImageFile = createImageFile();
        final ImageView latest_picture = (ImageView) findViewById(R.id.latest_picture);
        final RelativeLayout latest_picture_container = (RelativeLayout) findViewById(R.id.latest_picture_container);
        final String mImageFileLocationNew = mImageFileLocation.replaceFirst("^/", "");
        Toast.makeText(getApplicationContext(), "" + mImageFile, Toast.LENGTH_SHORT).show();
        Uri uri = Uri.fromFile(mImageFile);
        Toast.makeText(getApplicationContext(), ""+uri, Toast.LENGTH_LONG).show();
        latest_picture.setImageURI(uri);
        latest_picture_container.setVisibility(View.VISIBLE);
    } catch (IOException e){
        e.printStackTrace();
    }
    lockFocus();
    captureStillImage();
}

which runs createImageFile() and captureStillImage()

private void captureStillImage() {
    try {
        CaptureRequest.Builder captureStillBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
        captureStillBuilder.addTarget(mImageReader.getSurface());
        int rotation = getWindowManager().getDefaultDisplay().getRotation();
        captureStillBuilder.set(CaptureRequest.JPEG_ORIENTATION, ORIENTATIONS.get(rotation));
        CameraCaptureSession.CaptureCallback captureCallback = new CameraCaptureSession.CaptureCallback() {
            @Override
            public void onCaptureCompleted(CameraCaptureSession session, CaptureRequest request, TotalCaptureResult result) {
                super.onCaptureCompleted(session, request, result);
                //Toast.makeText(getApplicationContext(), "Image Taken", Toast.LENGTH_SHORT).show();
                unLockFocus();
            }
        };
        mCameraCaptureSession.capture(captureStillBuilder.build(), captureCallback, null);
    } catch (CameraAccessException e) {
        e.printStackTrace();
    }
}

File createImageFile() throws IOException {
    String timestamp = new SimpleDateFormat("yyyyMMdd").format(new Date());
    String subFolder = "";
    if(pref_session_unique_gallery.equals("yes")){
        if(event_name != null){
            subFolder = event_name;
        } else {
            subFolder = timestamp;
        }
    } else {
        subFolder = "_GEN";
    }
    if(event_name == null){
        event_name = "";
    } else {
        event_name = event_name + "_";
    }
    String imageFileName = "CPB_"+event_name+timestamp+"_";
    File storageDirectory = new File(Environment.getExternalStorageDirectory() + File.separator + "CPB" + File.separator + subFolder);
    storageDirectory.mkdir();
    File image = File.createTempFile(imageFileName, ".jpg", storageDirectory);
    mImageFileLocation = image.getAbsolutePath();
    return image;
}

and image is saved here:

private static class ImageSaver implements Runnable {
    private final Image mImage;
    private ImageSaver(Image image) {
        mImage = image;
    }
    @Override
    public void run() {
        ByteBuffer byteBuffer = mImage.getPlanes()[0].getBuffer();
        byte[] bytes = new byte[byteBuffer.remaining()];
        byteBuffer.get(bytes);

        FileOutputStream fileOutputStream = null;

        try {
            fileOutputStream = new FileOutputStream(mImageFile);
            fileOutputStream.write(bytes);

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            mImage.close();
            if(fileOutputStream != null){
                try {
                    fileOutputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }

            }
        }

I am getting the correct path to the image after createImageFile() and toasting it to show what it is every time. But not even the setVisibility on latest_picture_container is working... If I comment out the InputStream, Bitmap and setImageBitmap, then the latest_picture_container shows up as normal. Not sure why this is wrong.

For some reason, the URI is coming back with three slashes after file,

file:///storage/0/...
like image 787
ntgCleaner Avatar asked Jan 16 '16 04:01

ntgCleaner


People also ask

What is Uri image in Android?

URI or Uniform Resource Identifier is a compact sequence of characters that identifies an abstract or physical resource. It can be further classified as a locator, a name, or both. Basically URI (in some cases URL or URN) will point to the image location, or will be the name of the image (why not both?).

What is ImageView in android?

Displays image resources, for example Bitmap or Drawable resources. ImageView is also commonly used to apply tints to an image and handle image scaling.


3 Answers

The AssetManager#open() method only works for your app's assets; i.e., the files in your project's /assets folder. Since you're trying to open an external file, you should instead use a FileInputStream on a File object created from the path. Additionally, the takePhoto() method is setting the image on the ImageView before anything has been written to the file, which will result in an empty ImageView.

Since your app is using the camera directly, we can decode the image from the same byte array being written to the image file, and save ourselves an unnecessary storage read. Furthermore, in the example your code follows, the file write is happening on a separate thread, so we might as well take advantage of that in performing the image decode, as it will minimize the impact on the UI thread.

First we'll create an interface through which ImageSaver can pass the image back to the Activity to display in the ImageView.

public interface OnImageDecodedListener {
    public void onImageDecoded(Bitmap b);
}

Then we'll need to alter the ImageSaver class a bit to take an Activity parameter in the constructor. I've also added a File parameter, so the Activity's corresponding field need not be static.

private static class ImageSaver implements Runnable {
    private final Activity mActivity;
    private final Image mImage;
    private final File mImageFile;

    public ImageSaver(Activity activity, Image image, File imageFile) {
        mActivity = activity;
        mImage = image;
        mImageFile = imageFile;
    }

    @Override
    public void run() {
        ByteBuffer byteBuffer = mImage.getPlanes()[0].getBuffer();
        byte[] bytes = new byte[byteBuffer.remaining()];
        byteBuffer.get(bytes);

        final Bitmap b = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
        mActivity.runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    ((OnImageDecodedListener) mActivity).onImageDecoded(b);
                }
            }
        );

        FileOutputStream fileOutputStream = null;
        ...
    }
}

As soon as we get the image data in the byte array, we decode it and pass it back to the Activity, so it doesn't have to wait on the file write, which can proceed quietly in the background. We need to invoke the interface method on the UI thread, since we're "touching" Views there.

The Activity will need to implement the interface, and we can move the View-related stuff from takePhoto() to the onImageDecoded() method.

public class MainActivity extends Activity
    implements ImageSaver.OnImageDecodedListener {
    ...

    @Override
    public void onImageDecoded(Bitmap b) {
        final ImageView latest_picture =
            (ImageView) findViewById(R.id.latest_picture);
        final RelativeLayout latest_picture_container =
            (RelativeLayout) findViewById(R.id.latest_picture_container);

        latest_picture.setImageBitmap(b);
        latest_picture_container.setVisibility(View.VISIBLE);
    }

    public void takePhoto(View view) {
        try {
            mImageFile = createImageFile();
            captureStillImage();
            lockFocus();
        }
        catch (IOException e) {
            e.printStackTrace();
        }
    }
    ...
}

Finally, we need to actually execute the ImageSaver in the ImageReader's onImageAvailable() method. Again following the example, it would be something like this.

private final ImageReader.OnImageAvailableListener mOnImageAvailableListener = 
    new ImageReader.OnImageAvailableListener() {
    @Override
    public void onImageAvailable(ImageReader reader) {
        mBackgroundHandler.post(new ImageSaver(MainActivity.this,
                                               reader.acquireNextImage(),
                                               mImageFile)
        );
    }
};
like image 184
Mike M. Avatar answered Sep 27 '22 19:09

Mike M.


What I usually do is use the Picasso library

Add the dependency to build.gradle

compile 'com.squareup.picasso:picasso:2.5.2'

Since you are getting the file path, set the path to a File object, and then let Picasso grab the image from the phone, and set it to the required ImageView

File fileLocation = new File(uri) //file path, which can be String, or Uri

Picasso.with(this).load(fileLocation).into(imageView);

I do recommend using Picasso for any kind of Image activity on your app, whether it's online or offline. Picasso is made by Square, and is the best when it comes to image loading, caching...

like image 25
capt.swag Avatar answered Sep 27 '22 18:09

capt.swag


try this simple code

ImageView imgView = view.findViewById(R.id.lw_foto);

imgView.setImageURI(mListaContactos.get(i).foto);
like image 38
julio manzano Avatar answered Sep 27 '22 19:09

julio manzano