I've built an app that successfully runs on all sorts of Android devices. It was compiled for Android 8, but the device it's running on is Android 9.
Every time I open it on this Huawei P20 Pro, I get a crash. The only sensible error I can see is:
No implementation found for android.content.Context md5c497ac42f3138c67aed930c79af470d4.MainApplication.n_getApplicationContext() (tried Java_md5c497ac42f3138c67aed930c79af470d4_MainApplication_n_1getApplicationContext and Java_md5c497ac42f3138c67aed930c79af470d4_MainApplication_n_1getApplicationContext__)
I never call the get Application Context at any point, so I'm really not sure what is going on here.
Any helpful tips on debugging an issue like this?
If you compiled it with SDK 27 as max API (version 8) why would you run it on SDK 28, Compile with max version available 28 or 29 and then try running
In manifest make it android:targetSdkVersion="28" and compile using latest
First of all, I believe that the issue lacks enough details to make any assumptions about the possible causes. One of the possible causes is setting the target SDK version incorrectly. You can attempt to set to a correct one for the app as Ross Vernal suggested. It may can solve your problem.
Based on what I read from the official Android documents about the targetSdkVersion property, setting the version lower than the API level of a mobile device means that some additional compatibility behavior may be required when the app runs.
But this does not mean that the app cannot run on the devices with higher API levels. Whether the compatibility behavior is required depends on the app itself.
Therefore, it's possible that a feature or something else that you have decided to use in your app caused the issue on the device.
Additionally, I tested these conditions on my Huawei device that runs on Android 9 (SDK 28) with a sample Xamarin.Forms app under a target SDK of 27.
The app launched successfully. This supports the possibility mentioned above.
Related
I am using Delphi 10.4 (but my question is general enough to be relevant to any development environment - including ADS Jetpack Compose, React Native, etc.) which comes with installed Android SDK 29/NDK 21. From the one side, there is no way to ask Delphi 10.4 to use higher SDK (Trying to install Android SDK 31 and NDK 25 for Delphi 10.4 - what to provide in Delphi SDK manager wizards? is the description of my unsuccessful attempt). From the other side Google Play required all apps to target SDK 31 as of 2022.12.
So, I have the option (and some Delphi developers are constantly suggesting it) to manually edit AndroidManifest.xml and false state that app targets API 31 and at the same time I can continue compile it with SDK 29. My question is - can I falsely state higher target SDK API level and what could go wrong if I do this?
I did research what target SDK means exactly and https://proandroiddev.com/compilesdkversion-and-targetsdkversion-what-is-the-difference-b4227c663ba8 is the very fine explanation. Let me extract, summarize and adapt this article here.
So - there are 2 kind of features of Android apps. One kind of features target specific Android API versions. That means: if my app has min-SDK and target-SDK settings, then compilation includes all the SDK-specific implementations of this feature starting from the min-SDK and up to target-SDK. If compile-SDK < target-SDK (which is not advised, compile-SDK > target-SDK is advised), then the final apk includes the implementations for the interval [min-SDK, compile-SDK] only, compiler have no knwoledge about implementations (compile-SDK, target-SDK]. During the execution time the device OS determine the actual SDK of the device and the device OS can extract form the APK those version of the feature, that is the most closest to the actual device SDK.
Another kind of features have no such SDK-dependent implementations.
So - essentially. If I have the following values:
min-SDK: 23
compile-SDK: 29
target-SDK: 31
Then there can be feature X which have SDK-dependent implementations v23, v24, ..., v29, v30, v31. And compile-SDK-29 can compile only v23-v29 implementations in the final APK.
So - my question essentially boils down to the question how Android OS will handle the APK that states target-SDK=31, but which has implementations v23-v29 only?
I can imagine that Android OS has consistent protocol (all the targeted features) how to handle such situation and there can be 2 options only (assuming that actual device SDK is 30 or 31):
Android OS tries to read v30/v31 implementation of the feature and if it can not find the v30/v31 implementation of the feature then Android OS immediately reports the error about unsupported feature.
Android OS tries to read v30/v31 implementation of the feature and if it can not find the v30/v31 implementation of the feature then Android OS tries to read v29, v28, ..., min-SDK implementation of the feature and, of course, it finds some older implementation version and uses it. Android OS can report warning in logcat, uses sees the outdated behavior, of course, but otherwise the app is working and there is no any error message of interruption.
So, which scenario is true? I guess that 2nd scenario is true, because I have never seen any incompatibility messages during runtime, if app installs on the phone or tablet, then it certainly runs.
I can not find the reference, but it seems to me that I have seen one article which stated that there are well maintained code bases that uses compile-SDK < target-SDK, if the app vendor consciously decides to continue to use the behavior and functionality of the features as implemented for the previous SDK API versions. And such vendors set higher target-SDK just to get their apps accepted in Google Play.
, if app installs on the phone or tablet, then it certainly runs.
that's very not true. I have several cases where I have apps compiling with 32bit libs causing the app to instantly crash unless I specifically tell adb to install the app as 64bit.
What I assume is that it might not even compile if you have target SDK higher than compile SDK but even if it does compile, I think the app will simply crash on devices that runs SDK which has no definitions for the required functions. That's why when you write code you can check the SDK running on the device and apply the needed functions / functionality required for that SDK and if you fail to do that the app will crash. As in, say you have minSDK - 10 and targetSDK 30. If I'll run a function that has API X for SDK 10~20 but that API was changed to API Y from SDK 20~30 the app will compile and will be installed on all the devices. If I'll use API X only (that is, only for SDK 10~20) on a SDK 25 device, the app will simply crash when it will try to use that function.
I read that berlin is compatible with marshmallow, but i see that by default in the AndroidManifest.template.xml we have :
<uses-sdk android:minSdkVersion="%minSdkVersion%" android:targetSdkVersion="%targetSdkVersion%" />
i don't know where delphi took the variable to update %targetSdkVersion% but it's seam to be all the time 14 and i don't see any way to configure it
i would like to replace %targetSdkVersion% by 23 (marshmallow api level, to support the app permissions), but is it safe to do so or it's will introduce many other bug ?
FireMonkey was developed to work against a certain range of Android functionality. As you can see from the RAD Studio Platform Status page FireMonkey apps built with Delphi 10.1 Berlin have a lowest supported Android version of 4.0.3, which corresponds to Android API Level 15.
The minSdkVersion field is supposed to be set to the earliest Android version your apps will work with so in truth this should probably be set to 15 but actually is set to 14 (Android 4.0-4.0.2).
If you look back at an Android manifest file generated by Delphi XE7, which supported Android 2.3.3 (API Level 10) it specifies a min SDK version of 9 (Android 2.3-2.3.2), which is the version of Android that introduced the NativeActivity type underlying every Delphi FireMonkey Android app. Again, this seems a little bit out of kilter with what is documented as lowest supported version.
Anyway, minSdkVersion can be used by Google Play store to filter your app out of the listings for someone running a lower version of Android. It is also checked when you install an app on a device; Android won't let you install on a lower version of Android.
targetSdkVersion, on the other hand, indicates what version of Android your app has been tested with and works sensibly with. It can often be higher than minSdkVersion if your your app needs to use features introduced in Android versions later than minSdkVersion.
If you want to use a feature from API Level 23 then sure, you'll need to update that manifest part. Just remove the %targetSdkVersion% template from the Android manifest template file and replace it with the required version.
Problems that you might run into:
You'll either need to check the Android version and, if lower than your targetSdkVersion, not use those features that aren't available or set minSdkVersion to a suitably higher version to ensure the app can only run on devices that have the features you wish to use.
FireMonkey code not aware of differing behaviour in API Levels may
function adversely. In your case you may get issues because of the
different runtime permissions behaviour enabled in API Level 23.
Actually I can't currently think of any more issues, though a good amount of testing is recommended. You might have more to think about in a regular Android app using visual activities and so on, when different API levels may affect the theming or other UI elements. You can see the various things that change when you target target SDK versions on this Android documentation page.
By the way, the use of the SDK Manager in the Tools. Options... dialog is entirely irrelevant to the question of how to update the value in the generated manifest file. The only evident way to change it is to manually edit the Android manifest template file as per the documentation, and mentioned in a comment.
The only relevance of the SDK Manager is that the default Android SDK installation for Delphi 10.1 Berlin installs the Platform libraries for API Level 22. If you want to use a feature from API Level 23 you might think that updating those platform libraries might be necessary, but of course if you're doing the coding in Delphi then you're (presumably) actually just compiling against import definitions of the features in that higher API level, and so whether or not those features are contained in the android.jar file is of no consequence.**
** I'm happy to be proved wrong on this count, but I have never observed a connection between the manifest and what the SDK Manager is set up against.
While creating a project using eclipse i have Minimum SDK required as Android 2.2(Froyo) and Target SDK as Android 4.2(Jelly Bean) compile with Android 4.3. I have used sqlitebrowser v2.ob1 for creating database. My app runs without any errors (few lines in red in logcat though) and meets my requirements when i run it in an emulator. I tried 3 different emulators and it works fine. But when i tried this app in a mobile device it shows force close whenever there is something to do with database. I mean to say that it shows force close when it has to retrieve from database or connect to database. By searching i learned that just the .apk file is enough for the app to run even if externally created database is used in it (copying to assets folder and then to the default location). My questions are
Shouldn't my app work fine in any device ranging from Android 2.2 to 4.2 ?
Should i try compiling the app with Android 4.2 instead?
Am not sure about the version of the device i tried it in but am sure its within 2.2 and 4.2 . (Probably gingerbread). Other than plugging the device to PC via USB and seeing logcat (bcoz i dont own an android mobile phone) what can i do to solve this?
How is the app's version, emulator and version of mobile or any other device related?
My app can run on what versions of devices?
This is my first android app so any help is appreciated. Thanks in advace
It's possible that you are using a feature in your application that isn't supported by a lower version of the SDK. It's difficult to tell you exactly what that might be without any source code or stacktrace, but I can clear up your understanding of minSdkVersion and targetSdkVersion.
Consider that with each new version of the Android SDK, additional features and APIs are introduced that did not exist in previous versions. Obviously, the older versions of Android don't support those features.
When you specify a targetSdkVersion you are specifying that you are using features that were introduced in that particular version of Android. You are also implying that you have tested your application at that particular API level, and that it works as it should.
When you specify a minSdkVersion that is lower than your targetSdkVersion, you are implying that your application will work properly on a lower API level because you have manually programmed tests or checks in your code to ensure that the current API level is compatible with a feature before running it.
For example, if I wanted to run a feature introduced in Jelly Bean but I want to retain support for a lower API level (e.g. Gingerbread), I might add the following check before I run the feature (see other version codes here):
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
// run some code specific to API level 16
}
The Android SDK can automatically deal with code introduced in a lower API level, but it can't automatically deal with code specific to a higher API level.
So with that in mind, to answer your questions:
No, it's only guaranteed that your application will work properly on Android 4.2. It's up to you to ensure that it remains backwards compatible for earlier versions that you wish to support.
It shouldn't matter. Instead, you should first determine if your application runs on a device/emulator that is running the same API level as you are targeting (Android 4.2, API level 17), then run it on a device/emulator running a lower version and try to isolate the code that is causing it to crash (logcat will be helpful).
You can check the Android version of a device by going into Settings > About phone > Android version. If it is running Gingerbread, keep in mind that a lot of new features have been introduced since then and your application might be using some of those features. For the emulator, you can specify an API level when you create an emulator (you can download other versions to use from the SDK Manager).
I think my answer so far has made this relationship clear.
To reiterate, your application WILL run on any device running Android 2.2 or later, but it can crash if you are using features from a higher API level than the device is running.
If this is still not clear, you should read more about supporting multiple platform versions in the Android documentation: here.
I began the process of making one of my apps Honeycomb-friendly.
I started by changing the project's target build to version 11, and edited to AndroidManifest.xml to use:
<uses-sdk android:minSdkVersion="5" android:targetSdkVersion="11" />
These are the only changes I made so far. I am able to test it perfectly on my Honeycomb tablet device.
However, I cannot get Eclipse to launch this app in an older emulator (e.g. version 9). Technically speaking, the app should run in older android versions, so what can I do to test this app for older devices?
Or am I doing something else wrong?
I'm by no means an expert on this front but setting the minSdkVersion different from the targetSdkVersion doesn't make the app automatically use a different API level based on the device. See this:
Android Min SDK Version vs. Target SDK Version
and this:
http://android-developers.blogspot.com/2010/07/how-to-have-your-cupcake-and-eat-it-too.html
I suspect that because your application is using level 11 apis it won't run on a device that is of a previous API level.
This seems to be some sort of bug. When my 3.1 device is plugged into my PC, Eclipse/Android won't let me launch a new emulator that's < 3.0.
I worked around this by launching the emulator before I plug in my device, and then it has no problems deploying the app to both of the running devices.
I'd like to support Android 2.1 devices, but also would like to enable users to move my app to the SD card if they have Android 2.2+
The attribute for that is android:installLocation="auto"
How can I still support 2.1 while enable this attribute for 2.2+?
EDIT: I've set it with build 2.1 and I get a compilation error and I cannot launch my app. The reason I don't want to increase the build target to 2.2 is because if I do that and the app gets installed on 2.1, a bunch of exceptions are thrown and it crashes. I want to make sure that the app works perfectly on 2.1. For an example of what I mean, please see NoSuchMethodError: String.isEmpty
An exact solution for you is in Android Manual.
It can be done, set your minimum API level to 7 and your target API level to 8, more details are in the Dev Guide.