I released a version of my app to the Google Play and woke up this morning with a number of unhappy customers. The latest version of the app integrates support for a Bluetooth Low Energy (BTLE) heart rate monitor.
The app runs fine on Android 4.3 and 4.4 but crashes on 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 out and buying a 4.2 tablet so I can replicate the issue, I’ve come to the conclusion that it has to do with this new version of the app supporting Bluetooth LE, which is enabled in SDK 4.3 and later. If I delete all references to Bluetooth in MainActivity then the crash goes away on 4.2 and earlier devices.
My understanding from reading the documentation was that one could write an app that includes Bluetooth LE functionality and it would run on older devices, just so long as one was careful not to 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();
//etc.
Therefore my manifest.xml does not include the following as it would prevent download to older devices and I obviously want to maintain a single code base if possible ...
<uses-feature android:name="android.hardware.bluetooth_le" android:required="true" />
First question, is my assumption above being able to include BTLE code in SDKs prior to 4.3 correct? If not, do I really need to create two versions of the app... one for folks using 4.3 and later and one for everyone else?
There are many StackOverflow posts about java.lang.NoClassDefFoundError and I think I've read most of the relevant ones. Many suggest that I examine the Java Build Path to make sure that Android Private Libraries and Android Dependencies are checked. They are. Some suggest moving the gen folder before the src folder, but this doesn't seem to make a difference.
I'd post an image of the Eclipse Java Build Path but as this is my first post I don't have the 10 reputation points needed to insert an image, so here's another post that I followed... Android java.lang.NoClassDefFoundError
So, second question, any other thoughts about what could be wrong with the build path?
many thanks in advance.
Update... somehow by asking a question I got enough points to post images of the java build path. As @Ashoke points out I do think it has something to do with the wrong build path or support libraries.
android:required="false"
. I don't really think that's the root issue, but it's good to do anyway. – KobaridMainActivity
? – Rustyrut