All these resources, how can I stop Android Studio from adding them to the build? And where do they even come from?
I've recently downgraded my project because I intend to make an app for Honeycomb (I expect my audience to use relatively old phones). But after I did that, I got all these errors and I've no idea how to stop Gradle from adding them to the build.
how can I stop Android Studio from adding them to the build?
Technically speaking, you get rid of the code that is trying to add them.
Practically speaking, they are most likely serving a purpose for you, and that your problem is that you changed the compileSdkVersion to too low of a value.
And where do they even come from?
Libraries, most likely.
I've recently downgraded my project because I intend to make an app for Honeycomb
My guess is that you changed your compileSdkVersion. Change it back. Your minSdkVersion needs to be low enough to support your older devices; your compileSdkVersion needs to be high enough to support all of your code. Typically, compileSdkVersion is set to a recent version (e.g., 25 at the moment).
I intend to make an app for Honeycomb (I expect my audience to use relatively old phones)
Honeycomb (Android 3.x) was never used on phones.
Related
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.
I'm developing an application with a minSdkVersion of 9, a targetSdkVersion of 17. I am performing some Bitmap pixel manipulation, so at one point I call the function Bitmpap.setHasAlpha() to enable the alpha channel for the Bitmap so I can set certain (and only certain!) pixels to be transparent.
The problem is that Bitmap.setHasAlpha() was only added in API 12--and this is where the mystery comes in. Lint is not complaining about my usage of this call (well... as a general rule. Every once in a while Eclipse will complain about it, and then when I restart it everything goes back to normal), when I run my app on a couple of different Gingerbread (2.3.3 and 2.3.5) devices everything runs properly.
So... as strange as this question sounds, why isn't my app crashing?
http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/2.3.5_r1/android/graphics/Bitmap.java?av=f As you see mate the function existed before but not documented
minSdkVersion is a check designed to prevent download and installation of the app on older devices that do NOT have even framework corresponding to the minSdk.
targetSdkVersion is used to determine if any compatibility "workarounds" need to be enabled to ensure the behavior is as close to what is seen in targetSdk
By setting minSdkVersion=9 you signal that the gingerbread devices be allowed to download and install your app. By setting
targetSdkVersion=17 you signal that any workarounds be invoked to allow the device to retain as much functionality as possible from the later sdk.
Also as mentioned in Pulkits' answer the setHasAlpha() API seems to be present even in the 2.3.4 Android framework, albeit not officially documented at that time.
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
I'm new in the android developing.
I need to write some simple application - and i need to decide what will be the target version.
I don't know how to decide this - because i want to support the most newer version with all the new abilities - but i also want to support the maximum devices ( there are few devices that have old versions )
So, How to decide what will be the target version ?
In the Android Manifest.
http://developer.android.com/guide/topics/manifest/uses-sdk-element.html
Set your android:targetSdkVersion to whatever is the last Android SDK version.
Quote from Bruno Oliveira at Google IO:
targetSdkVersion does not affect the minimum SDK level required to run your application. It should always be the latest version that you are aware of.
The only reason you could have to use a lower version would be to detect incompatibilities, but that is not a good reason because Lint does this better.
BUT set your android:minSdkVersion to as low as your app will run on. That's the important one.
For instance, my app uses very new features, but I set android:minSdkVersion to 3 (which means Android 1.5). My code detects Android 1.5 devices, and uses less-shiny controls on them, but still runs correctly.
Detection code sample:
if (android.os.Build.VERSION.SDK_INT > 4) {
ActivityTransitionAnimation.slide(this, ActivityTransitionAnimation.UP);
}
So, here is my suggestion:
Set android:minSdkVersion to 3
Everytime you discover an API is not present at that level, ponder whether the loss of potential users associated with increasing this number is worse than spending the time to implement a workaround.
I would say just start off with the lowest possible target and then as you encounter stuff that you can only do with a higher target you will have to change the target to the higher one. Using APIs that only work on for example 2.3 will show errors if your target is lower (because the APIs won't exist there).
Also you should consider the current state of the "fragmentation" to se what targets are actually being used out there. Looking at this chart (from October 5) maybe it could be worth just starting with 2.1 and se if it is high enough for all the things you want to do:
http://cdn.devilsworkshop.org/files/2011/09/android-OS-fragmentation-report.jpg
When developing an Android app, let's say I want it to be compatible with 1.6 (API Level 4) devices, but still enabling 2.2 (API Level 8) features such as adding android:installLocation to enable moving app to SD card. Therefore I set Eclipse to compile against 2.2 SDK instead of 1.6 SDK.
Adding unknown attribute like android:installLocation doesn't crash the app when running in 1.6 device, but in case when coding I call some API that is unavailable in 1.6, such as android.util.Pair or Base64, the app will crash when running in 1.6.
Is it possible (e.g. via an Eclipse plugin) in build-time (not in run-time!) to check whether the project is still compatible with 1.6, in other words, check whether there is any API calls to any of the methods/classes requiring more than 1.6 (API Level 4)?
The best way to check if your app uses a non-existing API on older handsets is to change the target to the old version (starting from the minimal one you support) and seeing if you have any compilation errors... This will point you to non-compatible API calls.
At least that's the way I do it.
This is a tough problem to handle gracefully in code. I asked a very similar question here.
It seems to me that you may be asking the wrong question. Checking for calls to new API features is reasonable, but if you want to make your app work well over multiple versions, you will have to have code that makes calls to old and new API levels as appropriate. There are many ways to do this and it's considered a best practice.
In that case, you may want to downgrade your target version and check that all the errors that come up in Eclipse are handled well in your code (and of course try it in the right emulator versions).
I know this question is ancient, but there is a "holy grail" solution to this issue (at least from your users' point of view):
You can publish two versions of your app, one requiring API level 8 and another requiring API level 4. Then, use versionCode 100, 101, 102, 103, ... for your level 4 version and versionCode 200, 201, 202, 203, ... for your level 8 version.
That way, if a user has API level 8 available, they get offered only the level 8 version of your app as it has the higher versionCode. And users that only have API level 4 through 7 available, get offered only the other version as the other one is incompatible.
It's a little bit more of a pain to maintain, but it has the (potentially huge) advantage that you can customize the reduced-features version to still provide a complete experience (no grayed-out buttons, etc.), and you can even keep the APK size smaller for that version as you don't even need to ship the code or related resources for the unavailable features.
You can find more details in Android's Multiple APK Support documentation.