56

Suppose I have an activity to select an image from the gallery, and retrieve it as a BitMap, just like the example: here

Now, I want to pass this BitMap to be used in an ImageView for another activity. I am aware bundles can be passed between activities, but how would I store this BitMap into the bundle?

or is there another approach I should take?

Community
  • 1
  • 1
damonkashu
  • 1,723
  • 5
  • 17
  • 24

9 Answers9

55

I would highly recommend a different approach.

It's possible if you REALLY want to do it, but it costs a lot of memory and is also slow. It might not work if you have an older phone and a big bitmap. You could just pass it as an extra, for example intent.putExtra("data", bitmap). A Bitmap implements Parcelable, so you can put it in an extra. Likewise, a bundle has putParcelable.

If you want to pass it inbetween activities, I would store it in a file. That's more efficient, and less work for you. You can create private files in your data folder using MODE_PRIVATE that are not accessible to any other app.

EboMike
  • 72,990
  • 14
  • 152
  • 157
  • 5
    what if I just passed the path of the image to the other activity? – damonkashu Dec 04 '10 at 06:34
  • 2
    Absolutely, that's perfect! I thought the Bitmap was temporarily created by your activity, that's why you had to pass it along. (If you DID create it like that, you may want to save it to your local folder and then reload it). – EboMike Dec 04 '10 at 06:39
  • 2
    Btw, one more thing - in my rant about it being bad, I'm talking about full-size images. If you have smaller bitmaps, it's certainly okay to pass them as a Parcelable. – EboMike Dec 04 '10 at 06:40
  • I may end up doing that though since I want to replicate the contact image picker, select an image and crop it. but I'll post that in another question, thanks! – damonkashu Dec 04 '10 at 06:45
  • Please [help](http://stackoverflow.com/questions/33644614/failed-to-pass-image-to-another-class/33644701#33644701) me..thanks – Hoo Nov 11 '15 at 06:19
  • greatest answer – Ahmad Musa Oct 15 '19 at 12:10
  • Does this solution require android.permission.WRITE_EXTERNAL_STORAGE? – Alan Nelson Aug 18 '20 at 20:13
  • The official documentation https://developer.android.com/guide/components/activities/parcelables-and-bundles says "We recommend that you keep saved state to less than 50k of data". – JCvanDamme May 05 '21 at 15:50
44

If you pass it as a Parcelable, you're bound to get a JAVA BINDER FAILURE error. So, the solution is this: If the bitmap is small, like, say, a thumbnail, pass it as a byte array and build the bitmap for display in the next activity. For instance:

in your calling activity...

Intent i = new Intent(this, NextActivity.class);
Bitmap b; // your bitmap
ByteArrayOutputStream bs = new ByteArrayOutputStream();
b.compress(Bitmap.CompressFormat.PNG, 50, bs);
i.putExtra("byteArray", bs.toByteArray());
startActivity(i);

...and in your receiving activity

if(getIntent().hasExtra("byteArray")) {
    ImageView previewThumbnail = new ImageView(this);
    Bitmap b = BitmapFactory.decodeByteArray(
        getIntent().getByteArrayExtra("byteArray"),0,getIntent().getByteArrayExtra("byteArray").length);        
    previewThumbnail.setImageBitmap(b);
}
Harlo Holmes
  • 4,905
  • 1
  • 20
  • 19
24

As suggested by @EboMike I saved the bitmap in a file named myImage in the internal storage of my application not accessible my other apps. Here's the code of that part:

public String createImageFromBitmap(Bitmap bitmap) {
    String fileName = "myImage";//no .png or .jpg needed
    try {
        ByteArrayOutputStream bytes = new ByteArrayOutputStream();
        bitmap.compress(Bitmap.CompressFormat.JPEG, 100, bytes);
        FileOutputStream fo = openFileOutput(fileName, Context.MODE_PRIVATE);
        fo.write(bytes.toByteArray());
        // remember close file output
        fo.close();
    } catch (Exception e) {
        e.printStackTrace();
        fileName = null;
    }
    return fileName;
}

Then in the next activity you can decode this file myImage to a bitmap using following code:

Bitmap bitmap = BitmapFactory.decodeStream(context
                    .openFileInput("myImage"));//here context can be anything like getActivity() for fragment, this or MainActivity.this

Note A lot of checking for null and scaling bitmap's is ommited.

Illegal Argument
  • 9,249
  • 2
  • 38
  • 56
7

Activity

To pass a bitmap between Activites

Intent intent = new Intent(this, Activity.class);
intent.putExtra("bitmap", bitmap);

And in the Activity class

Bitmap bitmap = getIntent().getParcelableExtra("bitmap");

Fragment

To pass a bitmap between Fragments

SecondFragment fragment = new SecondFragment();
Bundle bundle = new Bundle();
bundle.putParcelable("bitmap", bitmap);
fragment.setArguments(bundle);

To receive inside the SecondFragment

Bitmap bitmap = getArguments().getParcelable("bitmap");

Transferring large bitmap (Compress bitmap)

If you are getting failed binder transaction, this means you are exceeding the binder transaction buffer by transferring large element from one activity to another activity.

So in that case you have to compress the bitmap as an byte's array and then uncompress it in another activity, like this

In the FirstActivity

Intent intent = new Intent(this, SecondActivity.class);

ByteArrayOutputStream stream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPG, 100, stream);
byte[] bytes = stream.toByteArray(); 
intent.putExtra("bitmapbytes",bytes);

And in the SecondActivity

byte[] bytes = getIntent().getByteArrayExtra("bitmapbytes");
Bitmap bmp = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
capt.swag
  • 8,997
  • 1
  • 33
  • 35
  • where in firstactivity should the above code be used. Should it be in init or as a seperate method ( and call this method in secondactivity ?? – nish Mar 20 '16 at 07:02
2

in first.java

Intent i = new Intent(this, second.class);
                    i.putExtra("uri",uri);
                    startActivity(i);

in second.java

Bundle bd = getIntent().getExtras();
        Uri uri = bd.getParcelable("uri");
        Log.e("URI", uri.toString());
        try {
            Bitmap bitmap = Media.getBitmap(this.getContentResolver(), uri);
            imageView.setImageBitmap(bitmap);

        } 
        catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
TheLittleNaruto
  • 7,996
  • 4
  • 47
  • 66
Jahh
  • 25
  • 3
2

Bitmap is Parcelable so you can add using [putExtra(String,Parcelable)][2] method, But not sure it is a best practice, If it is large size data it is better to store in a single place and use from both activities.

[2]: http://developer.android.com/reference/android/content/Intent.html#putExtra(java.lang.String, android.os.Parcelable)

Sudar Nimalan
  • 3,842
  • 2
  • 17
  • 27
1

I had to rescale the bitmap a bit to not exceed the 1mb limit of the transaction binder. You can adapt the 400 the your screen or make it dinamic it's just meant to be an example. It works fine and the quality is nice. Its also a lot faster then saving the image and loading it after but you have the size limitation.

public void loadNextActivity(){
    Intent confirmBMP = new Intent(this,ConfirmBMPActivity.class);

    ByteArrayOutputStream stream = new ByteArrayOutputStream();
    Bitmap bmp = returnScaledBMP();
    bmp.compress(Bitmap.CompressFormat.JPEG, 100, stream);

    confirmBMP.putExtra("Bitmap",bmp);
    startActivity(confirmBMP);
    finish();

}
public Bitmap returnScaledBMP(){
    Bitmap bmp=null;
    bmp = tempBitmap;
    bmp = createScaledBitmapKeepingAspectRatio(bmp,400);
    return bmp;

}

After you recover the bmp in your nextActivity with the following code:

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_confirmBMP);
    Intent intent = getIntent();
    Bitmap bitmap = (Bitmap) intent.getParcelableExtra("Bitmap");

}

I hope my answer was somehow helpfull. Greetings

Jan Ziesse
  • 459
  • 6
  • 9
1

Write this code from where you want to Intent into next activity.

    yourimageView.setDrawingCacheEnabled(true); 
    Drawable drawable = ((ImageView)view).getDrawable(); 
    Bitmap bitmap = imageView.getDrawingCache();
    Intent intent = new Intent(getBaseContext(), NextActivity.class);
    intent.putExtra("Image", imageBitmap);

In onCreate Function of NextActivity.class

Bitmap hotel_image;
Intent intent = getIntent();
hotel_image= intent.getParcelableExtra("Image");
Wajid khan
  • 657
  • 6
  • 18
1

You can pass image in short without using bundle like this This is the code of sender .class file

Bitmap bitmap = BitmapFactory.decodeResource(getResources(),R.drawable.ic_launcher;
Intent intent = new Intent();
Intent.setClass(<Sender_Activity>.this, <Receiver_Activity.class);
Intent.putExtra("Bitmap", bitmap);
startActivity(intent);

and this is receiver class file code.

Bitmap bitmap = (Bitmap)this.getIntent().getParcelableExtra("Bitmap");
ImageView viewBitmap = (ImageView)findViewById(R.id.bitmapview);
viewBitmap.setImageBitmap(bitmap);

No need to compress. that's it

Abdul Qadir
  • 113
  • 8