After Update to Android 14: "This app isn't compatible with latest version of Android."

Hi,
My app suddenly throws this warning when started on a test device (Samsung Galaxy Tab A8) after updating this device to Android 14.

“This app isn’t compatible with the latest version of Android. Check for an update or contact the app’s Developer.”

It seams to work nonetheless after pressing ok, but obviously this is not ideal.

I’ve searched online and the only solution I found was to switch the scripting backend from mono to il2cpp and enable ARM64 in the target architecture.

See:

The argument was that mono doesn’t support ARM64 and just builds for ARMv7 and this is what causes this warning, since it is now mandatory [?] to have an ARM64 app (I guess when the device has ARM64 Architecture)

Build Target is set to API Level 34. Minimum API Level is 28

It is true that this warning disappears when switching to IL2Cpp scripting backend, but sadly it’s not really an option for me, since a lot of my code depends on dynamic types and reflection which is not possible with the IL2Cpp backend.

My Question now: Is this true so far?
So Unity Projects with Mono Scripting Backend are not compatible anymore with Android 14 devices? Does anyone maybe have an Solution to this?

Refactoring the Code to get rid of all dynamic types will be quiet the hassle.

I’ve tested this also with an empty project with both 2021.3.27f1 and 2022.3.37f1.

i don’t need my app to be release in the app store as of right now, since it is an Control app for a separate device which is shipped with a pre-commissioned tablet, but the warning gives me a headache and I need to prevent this app to be incompatible in the future.

Could you explain what you mean by “dynamic types”? What are the features that don’t work with il2cpp?

Hi,
What I mean is the code uses the dynamic keyword and at runtime it is decided what it is and what needs to be done with it.

I’ll try to give you some do

So for example I have a lot of UI-Elements (Text, Dropdowns, Inputfield, etc) and one script handles connecting this elements to data in the backend.

This is realized with one script for all those elements attached to every UI Element which needs connection to the data.
I can assign in the editor to what kind of property I want this UI assigned to and if it should write and/or read those property.

The UI-Element is defined as a dynamic:

dynamic UIElement;

This dynamic object is then initialized with something like this:

if (GetComponent<Text>() != null)
        {
            UIElement = GetComponent<Text>();
        }
        else if (GetComponent<TMP_Text>() != null)
        {
            UIElement = GetComponent<TMP_Text>();
        }
        else if (GetComponent<InputField>() != null)
        {
            UIElement = GetComponent<InputField>();
            GetComponent<InputField>().onValueChanged.AddListener(obj => OnChangedListener(obj));
        }

Since the properties or data those ui elements need to be assigned to can also be of various types (string, int, float, enum, DateTime…) those values are also handled with dynamics.

For example writing data to the UI-Elements looks like this:

private void WriteToUI(dynamic settings, dynamic variable, dynamic value = null)
    {
        if (value == null)
        {
            value = settings.type.GetType().GetField(settings.option).GetValue(variable);
        }

        if (UIElement is InputField || UIElement is Text || UIElement is TMP_InputField || UIElement is TMP_Text)
        {
            UIElement.text = value.ToString();
        }
        else if (UIElement is Slider)
        {
            UIElement.value = value;
        }
        else if (UIElement is Toggle)
        {
            UIElement.isOn = value;
        }
        else if (UIElement is Dropdown || UIElement is TMP_Dropdown)
        {
            dynamic possibleEnum = value;

            if (possibleEnum.GetType().IsEnum)
            {
                UIElement.value = (int)value;
            }
            else
            {
                UIElement.value = 0;
            }
        }      

    }

In combination with a custom editor script for this whole data connection script it is quiet neatly possible to just drag the script on to an UI object, select from the dropdown what property I want to connect to and set it to write/read.

The code samples are obviously only snippets and there is a whole bunch of code to make sure you can only connect the UI Element to data that it can handle. For example dropdowns only accept enums, etc. Also the UI-Element events are integrated to write to the properties.

As you can see, a lot of dynamic objects are used and in my understanding this is not possible with IL2CPP, because this only works with JIT compilation, like with the mono backend and not with AOT compilation like IL2CPP. Because at compile time the compiler doesn’t know what the dynamic objects become at runtime.

The pitfall is, that this doesn’t throw any errors when building, it just doesn’t work when compiled. So my app starts, but all UI Elements are not updating or writing to the backend.

Please don’t ask me why this is handled in this way, this is some legacy codebase I need to maintain. I’m in the middle of rewriting this to have everything statically typed, so I can switch to IL2Cpp

It’s frustrating when an app becomes incompatible after updating to Android 14. This highlights the importance of developers keeping their apps updated with the latest OS versions. Hopefully, a fix or update is released soon to restore functionality and improve the user experience for everyone affected. GB Whatsapp Apk