Does Android app dynamically change its Target API Level

657 views Asked by At

I have a Xamarin.Forms app targeting Android API Level 30 (Android 11) which had Xamarin.Twilio.AudioSwitch v1.1.3 installed. The app is available in Play Store and was working fine till the time Android 12 was not released.

As soon as Android 12 became available, I got complaints from users using the BLE functionality of the app that they are not able to connect with BLE devices supported by the application.

The Android 12 users were getting the following exception:

java.lang.SecurityException:
at android.os.Parcel.createExceptionOrNull (Parcel.java:2437)
at android.os.Parcel.createException (Parcel.java:2421)
at android.os.Parcel.readException (Parcel.java:2404)
at android.os.Parcel.readException (Parcel.java:2346)
at android.bluetooth.IBluetooth$Stub$Proxy.getRemoteName (IBluetooth.java:5470)
at android.bluetooth.BluetoothDevice.getName (BluetoothDevice.java:1889)
at crc....Adapter_Api21BleScanCallback.n_onScanResult (Native Method)
at crc....Adapter_Api21BleScanCallback.onScanResult (Adapter_Api21BleScanCallback.java:38)
at android.bluetooth.le.BluetoothLeScanner$BleScanCallbackWrapper$1.run (BluetoothLeScanner.java:646)
at android.os.Handler.handleCallback (Handler.java:938)
at android.os.Handler.dispatchMessage (Handler.java:99)
at android.os.Looper.loopOnce (Looper.java:226)
at android.os.Looper.loop (Looper.java:313)
at android.app.ActivityThread.main (ActivityThread.java:8641)
at java.lang.reflect.Method.invoke (Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run (RuntimeInit.java:567)
at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:1133)

The above exception occurs due to the Android 12 Bluetooth permission changes. But this is required only if the app targets API Level 31. But since my app targets API level 30, I was not expecting these changes to be required in my app.

On investigating the issue, I found out that the issue is due to the native Audio Switch v1.1.3 targeting Android API Level 31 (Android 12) as mentioned here: Twilio Audio Switch v1.1.3 but the Xamarin.Twilio.AudioSwitch v1.1.3 binding library specifies MonoAndroid 9.0 (https://www.nuget.org/packages/Xamarin.Twilio.AudioSwitch/1.1.3) due to which I was able to install it for a project targeting API Level 30.

Does this mean that if the app has a package which targets an Android API Level higher than the app itself, the target API level would be dynamically change to higher API level?

Now the problem that I am facing is that I am not able to get this issue fixed for the users who already have the app installed.

I did a downgrade of Xamarin.Twilio.AudioSwitch to v1.1.2 as the native Audio Switch v1.1.2 library targets Android API Level 30 (Android 11) and found that the issue gets solved for new installations of the app. If a user already using a previous version of my app which had the Audio Switch v1.1.3 package and updates to the latest version of app which is using Audio Switch 1.1.2, the user still faces the above exception.

Is there any way that this can be fixed without making the app target Android API level 31 (Android 12) as that would require significant changes to the app?

Note: Asking the users to reinstall the app is not an option for me.

2

There are 2 answers

4
ToolmakerSteve On

--- This is only supposed to be needed if you target SDK 31 (but need legacy Bluetooth support), but its worth a try ---

  • Close solution.
  • In a text editor, edit file YourProject.Android/Properties/AndroidManifest.xml, with changes below.
  • Rebuild solution.

CHANGE 1:

Bluetooth permissions, point 4., recommends:

Add android:maxSdkVersion="30" to each declared Bluetooth-related permission. Example from doc's code snippet:

<!-- Request legacy Bluetooth permissions on older devices. -->
    <uses-permission android:name="android.permission.BLUETOOTH"
                     android:maxSdkVersion="30" />
    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"
                     android:maxSdkVersion="30" />

Perhaps this will clear whatever the OS is remembering re your app's Bluetooth access.

CHANGE 2 (experiments):

EITHER: REMOVE any Bluetooth permissions that were added in SDK 31. ONLY list permissions that existed in SDK 30.

OR: list the permissions app WOULD need if targeted SDK 31, but add android:maxSdkVersion="30", similar to above.

Also consider point 5.:

    <uses-permission android:name="android.permission.BLUETOOTH_SCAN"
                     android:usesPermissionFlags="neverForLocation" />

maybe as:

    <uses-permission android:name="android.permission.BLUETOOTH_SCAN"
                     android:maxSdkVersion="30"
                     android:usesPermissionFlags="neverForLocation" />

What we are doing here is not standard -- "should" simply be ignored on a "target SDK 30" app -- it is an attempt to get OS to clear something it is remembering related to this app.
Hypothesis is that during OS upgrade, OS noticed which apps were using Bluetooth in a way that required additional permissions [due to Twilio.AudioSwitch v1.1.3], and marked them as needing those additional permissions. But then failing when feature used, because permission not declared in manifest.

2
Harshit Gupta On

No, it can't be changed dynamically you have to change it from gradle by yourself.