96

I am passing Parcelable data into an Intent and getting it out on the other end using the getParcelableExtra(name:) method. However, getParcelableExtra(name:) seems to be deprecated. How do I fix the deprecation warning? Alternatively, are there any other options for doing this? I am using a compileSdkVersion value of 33.

Code snippet

var data = intent.getParcelableExtra("data")
2
  • Hi Dear @RabindraKhadka, you should consider adding more details like sample code to help us fully understand your issue. Commented Jul 18, 2022 at 8:15
  • Hi @GedFlod, I have added some code snippet. Commented Jul 18, 2022 at 8:23

6 Answers 6

208

Here are two extension methods that I use for Bundle & Intent:

inline fun <reified T : Parcelable> Intent.parcelable(key: String): T? = when {
  SDK_INT >= 33 -> getParcelableExtra(key, T::class.java)
  else -> @Suppress("DEPRECATION") getParcelableExtra(key) as? T
}

inline fun <reified T : Parcelable> Bundle.parcelable(key: String): T? = when {
  SDK_INT >= 33 -> getParcelable(key, T::class.java)
  else -> @Suppress("DEPRECATION") getParcelable(key) as? T
}

I also requested this to be added to the support library

And if you need the ArrayList support there is:

inline fun <reified T : Parcelable> Bundle.parcelableArrayList(key: String): ArrayList<T>? = when {
  SDK_INT >= 33 -> getParcelableArrayList(key, T::class.java)
  else -> @Suppress("DEPRECATION") getParcelableArrayList(key)
}

inline fun <reified T : Parcelable> Intent.parcelableArrayList(key: String): ArrayList<T>? = when {
  SDK_INT >= 33 -> getParcelableArrayListExtra(key, T::class.java)
  else -> @Suppress("DEPRECATION") getParcelableArrayListExtra(key)
}

Note: There are some issues on SDK 33 with the new methods, so you might only want to use it starting from SDK 34.

25
  • 1
    Good point. There already exists a question for that so I answered there: stackoverflow.com/a/73543350/1979703
    – Niklas
    Commented Aug 30, 2022 at 13:33
  • 1
    @androiddeveloper good call. Now it's updated :)
    – Niklas
    Commented Sep 7, 2022 at 22:10
  • 5
    It seems there is a bug on Android 13 related to this API. Google says they will fix it on the next version and provide something too. So, for now, I think it's better to use > VERSION_CODES.TIRAMISU instead of >= VERSION_CODES.TIRAMISU . Link: issuetracker.google.com/issues/240585930#comment6 Commented Oct 13, 2022 at 6:51
  • 1
    Agreed with @androiddeveloper to use > VERSION_CODES.TIRAMISU, I too encountered an NPE when attempting to access the parcelable on Android 13. Looking at the IntentCompat implementation for the core-ktx library, it looks like they're checking for "at least U", so it's also > VERSION_CODES.TIRAMISU. Kinda an egregious miss here to deprecate for Android 13 when they should've been deprecating for 14+. android.googlesource.com/platform/frameworks/support/+/…
    – Chee-Yi
    Commented May 30, 2023 at 10:39
  • 1
    Check out my latest edit, you probably should only use it on SDK >= 34
    – Niklas
    Commented Jun 23, 2023 at 10:11
63

androidx.core:core-ktx:1.10.0 provides two classes IntentCompat and BundleCompat with few helpful static methods

androidx.core.os.BundleCompat:

BundleCompat.getParcelable(Bundle, String, Class<T>)
BundleCompat.getParcelableArray(Bundle, String, Class<? extends Parcelable>): Parcelable[] 
BundleCompat.getParcelableArrayList(Bundle, String, Class<? extends T> clazz): ArrayList<T>
BundleCompat.getSparseParcelableArray(Bundle, String, Class<? extends T>): SparseArray<T>

androidx.core.content.IntentCompat

IntentCompat.getParcelableExtra(Intent, String, Class<T>)
IntentCompat.getParcelableArrayExtra(Intent, String, Class<? extends Parcelable>): Parcelable[]
IntentCompat.getParcelableArrayListExtra(Intent, String, Class<? extends T>): ArrayList<T>

Example for retrieving an object of android.bluetooth.BluetoothDevice:

IntentCompat.getParcelableExtra(intent, BluetoothDevice.EXTRA_DEVICE, BluetoothDevice::class.java) 

Simplified version of extensions proposed by @Niklas:

inline fun <reified T : Parcelable> Bundle.parcelable(key: String): T? =
    BundleCompat.getParcelable(this, key, T::class.java)

inline fun <reified T : Parcelable> Intent.parcelable(key: String): T? =
    IntentCompat.getParcelableExtra(this, key, T::class.java)

For ArrayList:

inline fun <reified T : Parcelable> Bundle.parcelableList(key: String): List<T>? =
    BundleCompat.getParcelableArrayList(this, key, T::class.java)

inline fun <reified T : Parcelable> Intent.parcelableList(key: String): List<T>? =
    IntentCompat.getParcelableArrayListExtra(this, key, T::class.java)
3
  • 4
    Using the compat classes seems like the right answer here. Commented Apr 12, 2023 at 15:59
  • 6
    For bundle: BundleCompat.getParcelable
    – dees91
    Commented Jun 9, 2023 at 12:03
  • in addition to @dees91 , for a list of object BundleCompat.getParcelableArrayList(requireArguments(),"key",YourObjectClassName::class.java) Commented Jan 8 at 5:49
49

Now we need to use getParcelableExtra() with the type-safer class added to API 33

SAMPLE CODE For kotlin

val userData = if (VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
  intent.getParcelableExtra("DATA", User::class.java)
} else {
  intent.getParcelableExtra<User>("DATA")
}

SAMPLE CODE For JAVA

if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
  user = getIntent().getParcelableExtra("data", User.class);
} else {
  user = getIntent().getParcelableExtra("data");
}
3
  • I cannot make this work in Java... Could you please indicate to me what should I put instead of User::class.java? My code is mediaButtonEvent.getParcelableExtra(Intent.EXTRA_KEY_EVENT); Commented Sep 10, 2022 at 16:13
  • 1
    @LuisA.Florit i have updated my answer please check
    – AskNilesh
    Commented Sep 10, 2022 at 16:34
  • Thanks @AskNilesh. In the second one you meant "SAMPLE CODE For Java". In my case, it would be KeyEvent.class instead of User.class. Commented Sep 10, 2022 at 17:23
8

For example UsbDevice.class:

UsbDevice device;
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.S_V2) { // TIRAMISU onwards
    device = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE, UsbDevice.class);
} else {
    device = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
}

Also NFC Tag.class:

Tag tag;
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.S_V2) { // TIRAMISU onwards
    tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG, Tag.class);
} else {
    tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
}

This still requires @SuppressWarnings({"deprecation", "RedundantSuppression"}).

4
  • It must be TIRAMISU (33) instead of S_V2 (32)
    – MBH
    Commented Oct 8, 2022 at 14:56
  • 2
    @MBH no. Above code is correct. It can be SDK_INT > S_V2 (greater than 32) or SDK_INT >= TIRAMISU (greater than or equal to 33).
    – Boken
    Commented Oct 22, 2022 at 15:14
  • 1
    The operator > suffices, because equal values are irrelevant anyway. Haven't benchmarked on JVM, but there may also be a small performance implication with the choice of operator (it doesn't matter with one iteration only): stackoverflow.com/a/11763604/549372 Commented Oct 22, 2022 at 15:45
  • @Boken yeah you are right! my fault :) I always prefer putting the related sdk instead of the previous one
    – MBH
    Commented Oct 23, 2022 at 8:02
7

As described in the official documentation, getParcelableExtra was deprecated in API level 33.

So check if the API LEVEL is >= 33 or change the method,

...

if (Build.VERSION.SDK_INT >= 33) { // TIRAMISU
    data = intent.getParcelableExtra (String name, Class<T> clazz)
}else{
    data = intent.getParcelableExtra("")
}

Here is an example using android.bluetooth.BluetoothDevice

...
val device = if (Build.VERSION.SDK_INT >= 33){ // TIRAMISU
    intent.getParcelableArrayExtra(
        BluetoothDevice.EXTRA_NAME,
        BluetoothDevice::class.java
    )
}else{
    intent.getParcelableExtra(BluetoothDevice.EXTRA_NAME)
}
3
  • 4
    I don't understand what did you mean here. getParcelableExtra (String name, Class<T> clazz) makes no sense. Commented Sep 9, 2022 at 20:33
  • See the sample code I added. Commented Apr 18, 2023 at 11:06
  • 1
    Yes, thanks, I did something like that: KeyEvent event = (Build.VERSION.SDK_INT < 33) ? mediaButtonEvent.getParcelableExtra(Intent.EXTRA_KEY_EVENT) : mediaButtonEvent.getParcelableExtra(Intent.EXTRA_KEY_EVENT, KeyEvent.class); Commented Apr 18, 2023 at 20:16
0
    val movie: Movie? = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
        intent?.getParcelableExtra(DownloadExtras.MOVIE, Movie::class.java)
    } else {
        @Suppress("DEPRECATION")
        intent?.getParcelableExtra(DownloadExtras.MOVIE)
    }
1
  • Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.
    – Community Bot
    Commented Oct 1 at 14:06

Not the answer you're looking for? Browse other questions tagged or ask your own question.