I released a version of my application on Google Play and woke up this morning with a number of dissatisfied customers. The latest version of the app integrates support for the Bluetooth Low Energy (BTLE) heart rate monitor.
The application works fine on Android 4.3 and 4.4, but crashes in 4.0, 4.1 and 4.2 with the following error.
FATAL EXCEPTION: main java.lang.NoClassDefFoundError: com.eiref.boatcoach.MainActivity at com.eiref.boatcoach.WhatToDo.onClick(WhatToDo.java:274) at android.view.View.performClick(View.java:4204) at android.view.View$PerformClick.run(View.java:17355) at android.os.Handler.handleCallback(Handler.java:725) at android.os.Handler.dispatchMessage(Handler.java:92) at android.os.Looper.loop(Looper.java:152) at android.app.ActivityThread.main(ActivityThread.java:5132) at java.lang.reflect.Method.invokeNative(Native Method) at java.lang.reflect.Method.invoke(Method.java:511) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560) at dalvik.system.NativeStart.main(Native Method)
The error occurs when creating an Intent in a simple Onclick, similar to the following ...
public void onClick(View v) { Intent i = new Intent(this, MainActivity.class); startActivity(i); }
After rushing and buying a 4.2 tablet, I can replicate the problem, Ive come to the conclusion that this is due to this new version of the Bluetooth LE-enabled application, which is included in the SDK 4.3 and later. If I delete all Bluetooth links in MainActivity, then the crash will disappear on 4.2 and earlier devices.
My understanding of reading the documentation was that you could write an application that includes Bluetooth LE features, and it will work on older devices only if you don't execute BTLE code using something like the following ...
if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) return; BluetoothManager manager = (BluetoothManager) getSystemService(BLUETOOTH_SERVICE); mBluetoothAdapter = manager.getAdapter();
Therefore, my manifest.xml does not include the following, as this will prevent old devices from loading, and I obviously want to maintain a single code base ...
<uses-feature android:name="android.hardware.bluetooth_le" android:required="true" />
The first question is, is my assumption higher than the ability to include BTLE code in the SDK before 4.3? If not, do I really need to create two versions of the application ... for people using 4.3 and later, and for everyone else?
There are many StackOverflow posts about java.lang.NoClassDefFoundError, and I think I read most of the relevant ones. Many people suggest that I study the Java Build Path to make sure that Android Private Libraries and Android Dependencies are checked. They are. Some suggest moving the gen folder in front of the src folder, but that doesn't seem to make any difference.
I would post an Eclipse Java Build Path image, but since this is my first post, I don't have 10 reputation points needed to insert the image, so here is another post that I followed ... Android java.lang.NoClassDefFoundError
So the second question, any other thoughts on what might be wrong in the build path?
Thank you very much in advance.
Refresh ... somehow, asking a question, I got enough points to place images of the java build path. As @Ashoke notes, I really think it has something to do with the wrong build path or with support libraries.

