javac#androidxamarinvisual-studio-2022

'Bundle.GetParcelable(string?)' is obsolete: 'deprecated'


So I have this obsolescence issue using VS 2022 Xamarin and android api 33 (Triamisu), I don't want to use the [Obsolete] key word as although the app works fine on my Samsung S21 (Android v13) phone, eventually all support for earlier versions of android will drop off and I will have to update all my code anyway. So in the interest of getting ahead of this, I'm putting the question out there.

Currently my code is:

User MyUser = new User("", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "");
MyUser = bundlee.GetParcelable("MyUser") as User;

I move the user data from one activity to another so I don't have to make another call to the database, hopefully saving time. I read the article here and can't really figure out what syntax I need in order to correct the code. User is a class defined in my code and I populate an instance of the class with the user's data. I move the data from one activity to another like this:

Intent intent = new Intent(this, typeof(Menu));
Bundle bundlee = new Bundle();
bundlee.PutParcelable("MyUser", MyUser); // Persist user class to next activity
intent.PutExtra("TheBundle", bundlee);
StartActivity(intent);

Now apparently things are changing and I cannot figure out how to adapt my code to the change. There isn't a lot of information out there as this is a recent change, I've read the android developer documentation here but it wasn't much help. What class clazz do I use in this instance? I created the class I'm passing in c#, so it's not java. I'm very confused. Can anyone clear this up for me?


Solution

  • A quick look at the source code (available online) confirms what you are experiencing:

    /* @deprecated Use the type-safer {@link #getParcelable(String, Class)} starting from Android
    *      {@link Build.VERSION_CODES#TIRAMISU}.
    */
    @Deprecated
    @Nullable
    public <T extends Parcelable> T getParcelable(@Nullable String key) {
      //Implementation here
    }
    

    As you can see, the comment is recommending you use the other (type-safer) method instead:

    /**
     * Returns the value associated with the given key or {@code null} if:
     * <ul>
     *     <li>No mapping of the desired type exists for the given key.
     *     <li>A {@code null} value is explicitly associated with the key.
     *     <li>The object is not of type {@code clazz}.
     * </ul>
     *
     * <p><b>Note: </b> if the expected value is not a class provided by the Android platform,
     * you must call {@link #setClassLoader(ClassLoader)} with the proper {@link ClassLoader} first.
     * Otherwise, this method might throw an exception or return {@code null}.
     *
     * @param key a String, or {@code null}
     * @param clazz The type of the object expected
     * @return a Parcelable value, or {@code null}
     */
    @SuppressWarnings("unchecked")
    @Nullable
    public <T> T getParcelable(@Nullable String key, @NonNull Class<T> clazz) {
        // The reason for not using <T extends Parcelable> is because the caller could provide a
        // super class to restrict the children that doesn't implement Parcelable itself while the
        // children do, more details at b/210800751 (same reasoning applies here).
        return get(key, clazz);
    }
    

    The new method even has a comment as to why you want to use this instead.

    Notice this in particular:

    • @param clazz The type of the object expected

    So, to answer your question, it looks like you should be doing this to get the object:

    User MyUser = new User("", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "");
    MyUser = bundlee.GetParcelable("MyUser", Java.Lang.Class.FromType(typeof(User))) as User;
    

    Or:

    MyUser = bundlee.GetParcelable("MyUser", Java.Lang.Class.FromType(MyUser.GetType())) as User;