Explain Codes LogoExplain Codes Logo

How can I pass a Bitmap object from one activity to another?

java
image-handling
bitmap
android-development
Anton ShumikhinbyAnton Shumikhin·Dec 1, 2024
TLDR

Efficiently transfer a Bitmap between activities by writing it to internal storage and sharing the filename. Compress the Bitmap and write it to a file, which is private to the app. This allows large bitmaps to be transferred without exceeding Android's Intent size limits.

Compress & Write:

// 'bitmap' is your Bitmap object to be transferred String filename = "bitmap_to_go"; try (FileOutputStream fos = openFileOutput(filename, MODE_PRIVATE)) { bitmap.compress(Bitmap.CompressFormat.PNG, 100, fos); // Compress like your life depends on it! } // Cruuuuising to a new activity with the Bitmap safely stored Intent intent = new Intent(MainActivity.this, NextActivity.class); intent.putExtra("bitmap_filename", filename); startActivity(intent);

Read & Display:

// Getting cozy with the shared image String filename = getIntent().getStringExtra("bitmap_filename"); try (FileInputStream fis = openFileInput(filename)) { Bitmap bitmap = BitmapFactory.decodeStream(fis); // Bitmap's ready to take center stage! }

Use try-with-resources to handle any exceptions and ensure streams are closed to avoid memory leaks.

Handling large Bitmaps

Avoid passing large Bitmaps directly through an Intent to prevent the infamous "TransactionTooLargeException". Instead, convert the Bitmap to a byte array and write it to a private cache file. Yes, it's like squishing a marshmallow into a keyhole!

// Converting the Bitmap to a byte array and writing it to a privately accessible cache file ByteArrayOutputStream stream = new ByteArrayOutputStream(); bitmap.compress(Bitmap.CompressFormat.JPEG, 100, stream); // Shrink Ray, activate! byte[] byteArray = stream.toByteArray(); File outputFile = new File(getCacheDir(), "bitmapzilla_found_a_home.tmp"); try (FileOutputStream fos = new FileOutputStream(outputFile)) { fos.write(byteArray); // Take that, binder constraints! } // Next, initiate Intent with reference to the cache file Intent largeBitmapIntent = new Intent(MainActivity.this, LargeBitmapActivity.class); largeBitmapIntent.putExtra("large_bitmap", outputFile.getAbsolutePath()); startActivity(largeBitmapIntent); // Off we go again!

Keeping Bitmaps safe and sound

Always confirm that the Bitmap has been successfully created or decoded. Nobody likes a blank canvas!

// Converting back to Bitmap... check your seatbelts! Bitmap transferredBitmap = BitmapFactory.decodeByteArray(byteArray, 0, byteArray.length); if (transferredBitmap != null) { // Bitmap is valid, ready to hit the stage! } else { // Ay caramba! Bitmap failed to decode... }

Your app will be better than most by implementing null checks and error handling.

Power-up with advanced data handling techniques

Leverage the power of Kotlin Coroutines and LiveData to asynchronously handle Bitmap loading, both efficiently and smoothly. Let's make it snappy!

val bitmapLiveData = liveData(Dispatchers.IO) { val file = File(intent.getStringExtra("large_bitmap")) emit(BitmapFactory.decodeFile(file.absolutePath)) // Like a phoenix, rise from the ashes! } bitmapLiveData.observe(this, Observer { bitmap -> // Update the UI with the Bitmap. Voilà! })

Be mindful, prevent memory issues

Ensure happiness and positive karma for your app by avoiding static/global references when dealing with large amounts of data. It's like tidying your room - good practice for your code and avoids the wrath of any memory leaks lurking in the shadows.