I am trying to use preprocessor like #ifdef in my Android project in Eclipse. I did some research on this topic and found this link: Java Preprocessing Using Eclipse, which could potentially let me use preprocessor in Android project.
However, after I tried to build the project, it claimed something like package android.* does not exist. So, none of the android APIs could be found.
So, how should I add those libraries in the build path? Actually, android.jar file is under the Java Build Path already. Why does Eclipse still claims that?
Is there any other way to let me use the preprocessor in Android Project built in Eclipse?
You are programming in Java, not C/C++. Android development does not require the use of a preprocessor.
Edit:
My problem is we developed an Android app with USB functionality which is supported only by Android 3.1+. So, some of the USB libraries are imported, what I want is those imported libraries could be commented out using #ifdef, if we could, when we build the project for Android 2.2 or 2.3, etc. Is there any other workaround for this?
To make use of the classes/methods you mentioned, you'll have to build your application against the Android SDK version 3.1 or higher. However, you must also ensure that devices running version 3.0 or lower don't make use of these classes/methods during runtime, since doing so will result in a ClassNotFound exception.
The key take-away here is that you need to perform these checks at run-time. Since your application is compiled only once for all devices, a preprocessor could do nothing to prevent such an event from occurring. Instead, you need to explicitly protect against this in your code. This is usually done with a basic if-else statement. For example,
if (Build.VERSION_CODES.HONEYCOMB_MR1 >= Build.VERSION.SDK_INT) {
// then you are on a device running android 3.1+ and it is
// safe to make use of the new classes/methods
} else {
// otherwise, you are running on a device running android 3.0
// or lower. you should not make use of the new classes/methods.
}
Edit #2:
In response to bill's comment, which read:
Thank you, Alex. I built my project agaist 3.1, deployed it on 2.2 and run it. One last thing I am not quite sure I understand is I could debug the part of the code referred by the Android 3.1 on the Android 2.2 OS. Here is my explanation: after being built against 3.1, Java code is converted to machine code and HONEYCOMB_MR1 is just an integer although HONEYCOMB_MR1 is not present in 2.2, when I debugged it, the debugger goes to the line of HONEYCOMB_MR1, fetches that integer and compares with SDK_INT. In this way, the code could still be debugged although HONEYCOMB_MR1 is only in 3.1 SDK. Is that correct? Thanks.
I think you are understanding correctly. The more exact reasoning is that HONEYCOMB_MR1 is marked static final. Since the variable is an immutable constant (i.e. its value will never change), the integer is hard-coded into the bytecode when you compile the .apk. In So when your 2.2 device reaches the if statement, it checks to see if 12 > 8, thus avoiding a (failed) runtime search for HONEYCOMB_MR1.
This sort of thing actually happens quite frequently when you develop your Android application. For instance, this behavior also explains why you can use MATCH_PARENT (introduced in 2.2) on devices that should "technically" only support FILL_PARENT. Both constants have value -1; thus, when you run an app that uses MATCH_PARENT on a pre-Froyo device, all works as expected.
Related
I have searched SO and tried all the solutions I came across but nothing seems to work. The things I tried are the solutions given here, here, here, here and here but nothing seems to work.
As described in some of those question I have a java library (lets say J) included in a android library (AL) that is included in a android app (AA). I have added the library to the libs of both (have also tried with adding it to just AA and including in AL, and vice-versa and just in AL and expecting android dependencies to take care of it) but that or anything else did not work.
I am using the latest tools(version 20.0.3).
The build android version for the android library and the app is 2.2 and min SDK is 5.
I can see the the java library in the android dependencies of the app but am getting a NoClassDefFoundException and run time.
How can I get this to work?
The android library must reference a jar, since that contains some encryption logic that I need to hide. The library is being created for distribution, the app is just something quite simple for testing the library.
There were 2 different but related problems causing this issue.
The Java library, J was compiled with compliance level 1.7 (default for my system). This needs to be at 1.5, the compliance level of Android. (compliance level may change in the future).
The J library was also compiling using the J2SE library. I had to replace that with the anroid.jar of the same api level as my app.
Then also things didn't work and for some reason it started working after I deleted the project and recreated in new directories.(IMP: take a code backup first).
Is it possible to use progressive enhancement when building Android apk's.
I'd like to build an app which can be used on SDK 8 + (gingerbread is the dominant android version) and when possible add features from newer version.
I know I can get the SDK version with SDK_INT to do something conditional, however when I use features introduced in later versions, eclipse won't let me build saying I need to increase the min SDK level.
Maybe my web development background is what's causing my thinking this to be possible, it may just be fundamentally impossible, do popular apps have different versions for different SDKS (like min8-max10,min11-max15)? Is progressive enhancement in Android Java code possible?
check if the build fails because of Lint errors, if so, and you're certain that a specific method won't be called on non-supported devices, add an annotation to that method with the min api level it can be called on as such:
#TargetApi(14)
public void useSomeNewApis() {
...
}
Or, if you're using eclipse, you can hover on the error line, and choose add #TargetApi(14) to useSomeNewApis
Something like:
<uses-sdk android:minSdkVersion="8" android:targetSdkVersion="15"/>
should be enough. But when program hit code from newer API than is on device then it will crash.
You need to make sure you are using the correct version of android. If you want to use a feature available in API 15 you have to build it in that API.
So if the feature you want to use requires API 15 make sure that in your project properties you have Project Build Target set to that API.
Right click on the your project and go to Properties. Select the Android section and make sure the correct API is checked.
I am developing an Android app in Eclipse. I would like to target a wide variety of devices and SDK versions (for example, I can optionally support multi-touch). I understand the recommended approach of isolating all the new functionality to a separate class and leveraging lazy loading to only load that class at run-time if the host device actually supports the feature.
The downside of this approach is that I have to compile all of my code with the SDK of the newest feature I want to use. Which means if some new feature leaks into my "version neutral" code, the compiler can no longer catch it.
I would like the ability, within Eclipse, to compile my project against an older Android SDK to make sure my "version neutral" code is fine. I'd like to avoid moving my build system out of Eclipse, if possible. I'm okay with this old-SDK build being a bit awkward to run.
I think this boils down to doing some conditional compliation (or conditional "linking") inside Eclipse? For example, in my project when building against SDK-1.6 I'd like to leave the "MultiTouchHandler.java" source out of the build. I'm not sure if its possible to express "build types" like this in Eclipse, though.
The hacky solution seem to be just manually changing the project's SDK version, rebuilding, and looking through the errors, and ignore 'expected' errors. The overkill solution seems to be writing my own ant/maven/make build scripts.
Related Questions
This question:
Versioning and common code-bases with Eclipse
covers similar ground, but would involve moving all of the version-specific classes into separate "libraries". (And I would still have the problem of multiple build types in Eclipse, I think.)
This question:
Build multiple project configurations with eclipse implies that I should move to an external build system (like ant or maven), but that's a lot more work than just trying a build with an old SDK from time to time.
The February 2012 (v17) updates to the Lint Tool in the ADT should help address this without requiring multiple builds. When an app targets an old minimum SDK, but is compiled against the newest SDK (as is the recommended practice), the lint tool will notice if calls to the newer SDK are invoked. If you're confident the call is okay (Because you've hidden it behind a run-time SDK_INT check, or whatever), you can Quick-Fix an annotation to prevent the warning.
For example, in my code I have a call to View.setSystemUiVisibility, which was introduced in API 11, but I'm targetting API 8. Running Lint shows:
Call requires API level 11 (current min is 8): android.view.View#setSystemuiVisibility
The QuickFix suggests two kinds of fixes, either adding an annotation that suppresses the warning or adding an annotation that declares a chunk of code as working at API 11.
More details here: http://tools.android.com/recent/lintapicheck
A somewhat less clean/less performant method would be to use reflection to access the newer apis that you need, rather than trying to reference them directly with lazy loading. This should allow you to compile against a lower sdk level.
I am just learning about android app development and have created my first app which is a relatively simple app with a link to a gallery of images and some text pages. I created this using the 1.5 platform as it seemed sensible to make it backwards compatible. I've been testing it on 3.0 and it comes up tiny on the screen and I have since learnt I need to use supports-screens and other related commands to allow variable screen support which from what i read is only available in 1.6 and above. As a result I need to change the app platform to 1.6 or above and my questions are as follows:
1) Am I able to just go to project properties and change the platform version tickbox to a newer one (in this case 1.6)? As I tried this with the project but the supports-screens tag still gives an error (which it doesn't when I create a brand new project)?
2) What version should I be creating it in these days for ideal backwards compatibility but able to use most desirable features? I understand 1.6 includes a lot of the newer functionality but according to http://developer.android.com/resources/dashboard/platform-versions.html only about 4% of people are using less than 2.1 so is it better to just code using 2.1 (assuming I want to target mobiles and tablets)?
Thanks so much for your help as ever,
Dave
Take a look at this. It explains how you can go about changing your AndroidManifest.xml to specify which version of the SDK to use. You may also need to update default.properties to point the target to the proper api value.
This really depends on what you want to do. If you require something from 2.1 or 3.0, then I think you need to go with that. But if you can get by using just 1.6 and still have all the functionality that you need/want, then I would definitely recommend using 1.6.
As I am very pissed off of using the emulator to develop any Java class, I thought of setting up a project in Eclipse and instead of the usual JRE I linked to the Android.jar (version 2.1) that usually the Android projects link to. I don't mean to use this to develop Layouts or other specific platform things, I was just trying to create a class that uses HttpClient. It miserably crashes like this.
Exception in thread "main"
java.lang.RuntimeException: Stub! at
org.apache.http.impl.client.AbstractHttpClient.(AbstractHttpClient.java:5)
at
org.apache.http.impl.client.DefaultHttpClient.(DefaultHttpClient.java:7)
at
AdsCatcher.(AdsCatcher.java:26)
at TestAll.main(TestAll.java:10)
Stub! I mean I'd like to develop libraries (and test them) so that when I go to the emulator I don't have to deal with them. Is there a good way to do this? This seems not to work for some reason.
This will not work, sorry. The android.jar file, as the error message indicates, contains only stubs of the Android API. This makes sense, since that API cannot work outside of Android -- the android.jar file is just there for compilation.
For class libraries you are working on that have no dependencies on Android, you are welcome to create a standard JRE Eclipse project that generates a JAR that you then use in your Android project.
In your case, you may be able to create a class library using the JRE that uses HttpClient. The latest version from Apache may differ slightly from the version in Android, though, so while probably you will be OK, there's a chance you will run into runtime errors due to changes in method signatures and such (VerifyError).