I've got a quote from a developer to build a couple of Android apps. For both the contract states: "App will be compatible with Android OS 4.0.x and 4.1".
Can anyone please tell whether this poses any problems for people wanting to run the apps on newer versions of Android's OS? Not sure if I should be worried or not.
Many thanks
Drew
Mostly, newer Android API fully support older API. That means anything that works on 4.1 should work on 4.3, 4.4, etc
Still, not everything that can run on 4.1 can run on 2.2, for example. Backwards compactibility is a huge problem sometimes
Targeting a minimum of 4.0 won't stop the apps from working on the current versions of android. The only major difference that I can think of is the default color accents being changed in 4.4 (The current highest release). This can be addressed by your developer if your desired styling overrides the defaults anyways, otherwise know that in 4.0 youll see lots of blues, but in 4.4+ youll see a more subtle grey accent.
That isn't to say that this will always be the case though. At any point the OS can take a right turn like they did with the HOLO changes that were introduced between 2.3 and 3.0, which would make your "legacy" app not function as it use to. At this point, you would either have to have the app redone, or accept the flaws in this completely hypothetical future state.
Unless the API is depecrated, they will always work on newer versions. The problem usually is older versions unable to support newer API, not the other way round.
Related
Google Play recently issued a heads up to Android developers to update their apps with three new changes : https://android-developers.googleblog.com/2017/12/improving-app-security-and-performance.html
I have a question regarding updating the targeted SDK to version 26. When I made this change for one of my apps, the Developer console showed me a warning saying that this new APK would not support an x number of devices, since it does not fall into some SDK version criteria. Since the app did not have too many active installs, I went ahead with it.
Now I need to do this for another app of mine which has quite a good number of active users. Would making this change of targeted SDK version have any impact on user having low end Android OS or older device models?
Could somebody please explain what might be the problems one might face while making such a change, from perspective of existing and new users?
Would love some clarification from anyone who has some info, but particularly from android app developers who have already made these changes.
From a user perspective: no problems, because changing the target SDK does not mean changing the minSDK.
For you as a developer: depending on the gap between current and future target SDK, there may be quite a lot of work to do because the runtime will handle things differently under the hood depending on the target SDK (e.g. permission handling, use of certain libraries, rendering of UI components).
Quoting from documentation for <uses-sdk>
As Android evolves with each new version, some behaviors and even appearances might change. However, if the API level of the platform is higher than the version declared by your app's targetSdkVersion, the system may enable compatibility behaviors to ensure that your app continues to work the way you expect. You can disable such compatibility behaviors by specifying targetSdkVersion to match the API level of the platform on which it's running. For example, setting this value to "11" or higher allows the system to apply a new default theme (Holo) to your app when running on Android 3.0 or higher and also disables screen compatibility mode when running on larger screens (because support for API level 11 implicitly supports larger screens).
There are many compatibility behaviors that the system may enable based on the value you set for this attribute. Several of these behaviors are described by the corresponding platform versions in the Build.VERSION_CODES reference.
My app is set to run on minSdk = 5, but the vast majority of users are using SDK 8 (FroYo) and higher. I want to be able to use the android:configChanges="uiMode" for my main activity, but I can't do it because that mode wasn't introduced until SDK level 8. So, I was hoping that I could do it at runtime -- check which SDK level is running on the device, and then use reflection to add that parameter.
Is that possible?
EDIT:
The problem is that whenever a user's phone is connected to the dock, my app gets terminated, and then re-created. I'm trying to avoid that by including the android:configChanges="uiMode".
After much poring through the Android Reference, there is very little you can change from the manifest at runtime. This is due to security because through the PackageManager, one can gain very specific information about any application on the device. While it is easy to enable/disable a given Component, in most other circumstances, you can only read manifest information... not write it.
Alternatives
You could potentially make a separate APK with API Level 8 support.
You could manually check for configuration state and run your code when it changes. The object reference for configuration is here.
Edit: (new info)
While you cannot change the configChanges, I found this question that is closely related to yours. It turns out that you might not have to. It implies that you can use Android's backward compatibility mode when supporting new configChanges. In case the link above is broken, here is the URL: https://stackoverflow.com/a/7893148/501932
To put this to use for you, it suggests setting a new targetSdk while maintaining your original minimumSdk. It also requires that you have the updated SDK, itself. Apparently, this was a huge deal for users that utilized that AdMob API.
App Configuration for forward compatibility
The answer I provided is a simple what to do, but not much or the why, this should update the answer as well as act as apology to the SO community for sparring with the poster, which was pointless and added nothing to the conversation.
I think it’s an important point to expand upon this issue since these kind of questions come up a lot and developers in a hurry (aren’t we all) and we have a tendency to cut/copy/paste and worry about the why of it later which mostly works out but occasionally just adds to the problems.
If you understand how the android runtime actually works you can often solve these types of problems by applying a simple pattern of best practices by using the block in your manifest, and making good use of the Build Target when compiling your app, followed by some simple testing at the compile and run time levels.
Manifest
minSdkVersion =
Pretty straight forward it’s the lowest build target you will support on a specific device. If you don’t set this it defaults to 1.
The only caveat here is that if your Build Target is higher than your minSdkVersion than you can potentially call API’s that don’t exist on the device, more on that under Build Target.
This will filter you app from on the various market/play repositories for devices that have lower OS support.
How you make this determination is up to you, if you must have your app run on every device ok, but take a look at Platform Distribution to make an informed decision.
If you are willing to bypass 0.9% of the market then target 2.1 which seems reasonable but that’s a decision for a developer/company to make, if you can bypass 25% of the market then go with 2.3 which has significant advantages but is a bit hard to swallow for most general purpose app’s.
The linked chart is updated from time to time.
targetSdk =
If you don’t apply this value then it defaults to whatever minSdkVersion you set. This means that when you run on a device with higher OS support certain new looks and or behaviors that are implemented will be bypassed in favor of the older way of doing things.
For instance if you apply 10 to the minSdkVersion and then your app runs on a device with gingerbread (11) it will not attempt to use the holo theme, or disable screen compatibility mode. In general this might give your app a “Dated” look and feel.
If on the other hand you set this to something higher, like 11, then the system will use the native look and feel of the OS up to that value you set. Best practices is to set this as high as possible and then to test on the higher level device in the emulator to make sure this is acceptable.
Some of the changes that effect compatibility behavior between OS jumps are documented here Differences between OS's
This will not stop you from running on earlier devices, or effect those earlier devices look or feel (see ActionBarSherlock and the Android Support Library if that’s your goal)
maxSdkVersion =
In general this does just what it says it does, it restricts availability and deployment of your application on devices that have a higher OS level from Google market/play.
On android 2.0- it will also refuse to install the apk, and will even remove your app if a device is updated to a level higher than this setting, 2.0.1+ removed the second part of this behavior but the markets will still filter based on it.
In general there is no reason to usually set this value, so leave it blank.
Build Target
When you set a build target in eclipse (or otherwise) you are telling the complier which API’s, constants, etc. should be VISIBLE to your application.
In general it adds a jar file that has all of these definitions/declarations but of course not the actual classes/methods so that you can compile your application for any target OS you desire.
When your app runs on a device it links to the actual android OS/support jar file(s) (or blows chunks if they are not there)
If you select a build target higher than you are willing to support then bad things can of course happen when you try and call method that does not exist, or even a class that does not exist on the Older OS.
If on the other hand you are willing to carefully manage and test this then you can obtain forward compatibility in the sense that you can use the new API’s on newer devices so long as you don’t attempt to do so on earlier devices.
Best Practices – Short Version
This is what the poster is trying to accomplish and if best practices are followed it works out well, these are in general
minSdkVersion = lowest general API you will support
targetSdkVersion = highest behavioral model you are willing to allow
maxSdkVersion = leave it blank
Build Target = generally as high as is currently supported
The real caveat is that you have to avoid API mismatches between older and newer versions, and make sure your app looks and acts ok on the higher version.
In general methods/classes that are higher than your minimum targeted OS should be used sparingly and tested at both the compile and runtime level since it requires some effort to use them safely.
Here is how I go about it
minSdkVersion = 7 ( I can live with a 0.9% clip again your choice )
targetSdkVersion =15 ( highest as of this writing )
maxSdkVersion = ( blank )
Build Target = 15
When developing I never use an API not available on 7 unless I have a real need to do that, in the posters question he could have used a broadcast received to get similar functionality back to 6/7 (2.0/2.1) but he states he needs API 3 support so he has to support forward compatibility.
One tool you can use, and most don’t just to keep things straight is to set the API level on the developer.android.com website to your minimum SDK level, this gives you a heads up when developing that you will have to support forward compatibility.
It will still show the other API calls but it will gray them out telling you that extra effort will be needed to support them
If you do need to use a newer API you will need to do an if then else so that they are only called on the newer device, this will allow you to support the new functionality without getting a force close on older devices.
So in general if you support higher API levels those calls should be wrapped with something like this (note the .SDK_INT is a since API 4 test)
If ( Build.VERSION.SDK_INT >= API11_SUPPORT ) {
switch(newConfig.uiMode) {
case ...
}
Testing – manual method (CI integration methods are left up to the reader ;-)
Compile with the build target set to the minSdkVersion – this will give you compile errors on any newer API’s that you are using, check them out and if you handled them great, if not now is the time.
For every issue I see at step 1 I add two items to the code (manifests/xml )
// TODO Compatibility xxx
if (DEBUG) Log.i(“MyApp”,” Compatibility xxx”);
I can then use the eclipse TODO pane to check off compatibility issues before ship and test them against the lowest/highest and any significant in between OS versions
Test on minSDKVersion device/emulator, this is a bit tricky if you are not doing comprehensive testing, in general use step 1 above to make sure I exercise those blocks of code
Test on Build Target device/emulator to make sure look and feel work as expected
If you think it’s a bit of work it is, but when you need it you should do it right and make sure your app does not break.
Hopefully this is useful to someone trying to figure out similar situations, below was my second response to the poster, Cheers.
UPDATE:
I still have no idea what the author is asking, but if he is asking if there is a way to detect the configuration changes in regard to uiMode (docking stuff) on 7 and below using the onConfigurationChanged handler then no since that was only introduced in API 8.
There is a broadcast event sent in API 2.0+ systems, but apparently that has some issues and does not seem to be completely reliable
If he is asking if there is a way to support it on devices that are API 8 and above via the onConfigurationChanged handler by setting the flag in manifest for the activity then of course there is
Of course he may be asking about something totally different, it's hard to tell exactly what he is looking to do given his post none the less in the spirit of cooperation:
Select an API from project properties that is >= 8, best practices is to use the highest API available when you create your app for just this reason BUT care must be taken not to call any API's that are not available on the device.
Then in the manifest use (duh)
<activity
android:name=".myActivity"
android:configChanges="uiMode|orientation|keyboardHidden"
This compiles fine (and that is really the only issue and why you need to set a higher api in the eclipse project properties) this will run fine on 7 and below it just wont trigger any events because of course API 7 and below devices won't recognize the uiMode flag (duh)
API 8 and above of course will recognize it and send the proper event so on api 7 the log will be written, on api 8+ it will (if docked etc) of course the calls that are made if it does happen will most likely be 8+ related so you would need a OS check block before calling them.
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
Log.i("myActivity","uiMode="+newConfig.uiMode);
}
If you compile and run on a 7 API emulator and fire a dock broadcast nothing happens, change to a 8 API emulator and it does
adb shell am broadcast -a android.intent.action.DOCK_EVENT --ei android.intent.extra.DOCK_STATE 2
Made an app targeting API8 and it's running fine
on all emulator images all the way up to API15.
I cannot test the app on other higher apis so I'm not
setting the android:targetSdkVersion.
What about this deprecated warnings:
android.view.Display.getHeight()
This method is deprecated.
Use getSize(Point) instead.
Can I ignore this and just keep on using Display.getHeight()?
I read about reflection or programmatically testing what Android version the device is using.
Why do people do that when it's working for me?
I cannot test the app on other higher apis so im not
setting the android:targetSdkVersion.
If you are testing "on all emulator images all the way up to API15", then you are "test[ing] the app on other higher apis".
Can i ignore this and just keep on using Display.getHeight()?
In Android, "deprecated" usually means "we have a better solution that you should consider using, but we will keep the deprecated one working as long as we can". Sometime after you drop support for API Level 12 and down, you might wish to move to getSize(). For now, getHeight() should work fine on all Android API levels.
Why do people do that when it's working for me?
They do not do that for deprecated APIs. They use version checks and the like for accessing things that simply do not exist in older versions of Android, so they do not try referring to non-existent APIs on older devices.
Title says it mostly...
While it would be nice to be able to cover 90%+ of devices in use now, if it starts to complicate things, I think, focusing on devices being released now and soon clearly has priority.
Bonus points, on guidelines to set project settings and emulator to be in sync and without warnings.
See the Android Dashboard for stats on API usage and trends: http://developer.android.com/resources/dashboard/platform-versions.html
(As of May 2011, it looks like targeting 2.1 and 2.2 covers about 90%, but obviously this will change.)
I'm just about to launch my first Android app, and it runs on the Android 1.1 platform, API Level 2, but is this what I should officially sign and launch the app as? Does it affect performance at all or is it simply for Android to know which devices it works on?
The only problem I see is that I can't specify <supports-screens> in the Manifest, which I would like to do, but it appears I'd have to launch at 1.6 at least for this to work.
Would I be missing a huge number of phones by launching at 1.6 instead of 1.1?
Thank you!
Removing out of date info and info that I'm sure will be out of date in the near future. Just go here to see what versions you should care about:
http://developer.android.com/resources/dashboard/platform-versions.html
I'd say 1.5 is a good choice for now. Have a look at the chart here: http://android-developers.blogspot.com/2009/12/knowing-is-half-battle.html
Recent update of the Android fragmentation from Android Tapp:
Android fragmentation http://www.androidtapp.com/wp-content/uploads/2010/05/Finally-More-Users-on-Android-2.1-but-Android-Still-Fragmented-Chart.jpg
As far as I am concerned, I start developing targeting 1.5. When half finished, I would switch to 2.1 and when finished, I would try all versions in-between. I do not regard it necessary to mind any version lower 1.5 ... you cannot be downward compatible to the beginning of the universe ;-)
Strategies for Legacy Applications
http://developer.android.com/guide/practices/screens_support.html#strategies