8

Я выпустил версию своего приложения в Google Play и проснулся сегодня утром с рядом недовольных клиентов. Последняя версия приложения объединяет поддержку монитора частоты сердечных сокращений Bluetooth Low Energy (BTLE).java.lang.NoClassDefFoundError для старых версий SDK для Android

Приложение отлично работает на Android 4.3 и 4.4, но выходит из строя на 4.0, 4.1 и 4.2 со следующей ошибкой.

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) 

Ошибка возникает при создании Intent в простом OnClick, подобное следующему ...

public void onClick(View v) { 
     Intent i = new Intent(this, MainActivity.class); 
     startActivity(i); 
} 

После выпускающих и покупки 4.2 таблетки, так что я могу повторить вопрос, я пришел к вывод о том, что он связан с этой новой версией приложения, поддерживающей Bluetooth LE, который включен в SDK 4.3 и более поздних версиях. Если я удалю все ссылки на Bluetooth в MainActivity, тогда сбой исчезнет на 4.2 и более ранних устройствах.

Мое понимание, прочитав документацию, состояло в том, что можно было написать приложение, которое включает функции Bluetooth LE, и оно будет работать на старых устройствах, только если вы не выполняете BTLE-код, используя что-то вроде следующего ...

if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) return; 
    BluetoothManager manager = (BluetoothManager) getSystemService(BLUETOOTH_SERVICE); 
    mBluetoothAdapter = manager.getAdapter(); 
//etc. 

Поэтому мой manifest.xml делает не включают в себя следующее, как было бы предотвратить загрузку для старых устройств, и я, очевидно, хотят, чтобы поддерживать единую базу кода, если это возможно ...

<uses-feature android:name="android.hardware.bluetooth_le" android:required="true" />  

Первый вопрос, является ли мое предположение выше возможности включить код BTLE в SDK до 4.3? Если нет, мне действительно нужно создать две версии приложения ... один для людей, использующих 4.3 и более поздние версии, и один для всех остальных?

Существует много сообщений StackOverflow о java.lang.NoClassDefFoundError, и я думаю, что прочитал большинство соответствующих. Многие полагают, что я изучаю Java Build Path, чтобы убедиться, что Android Private Libraries и Android Dependencies отмечены. Они есть. Некоторые предлагают перемещать папку gen перед папкой src, но это, похоже, не имеет особого значения.

Я бы разместил изображение Eclipse Java Build Path, но поскольку это мой первый пост, у меня нет 10 точек репутации, необходимых для вставки изображения, поэтому вот еще одно сообщение, которое я последовал ... Android java.lang.NoClassDefFoundError

Итак, второй вопрос, любые другие мысли о том, что может быть неправильным в пути построения?

большое спасибо заранее.


Обновление ... как-то задавая вопрос, у меня было достаточно очков, чтобы размещать изображения пути сборки java. Как отмечает @Ashoke, я думаю, что это связано с неправильным способом построения или поддержкой библиотек.

Eclipse Order and Export

Eclipse Libraries

+0

тот же код внутри OnClick Работает ли на> = 4.3 или есть другой путь кода в зависимости от Android версии? –

+0

Вам определенно не нужны две версии приложения. Что касается тега uses-feature, я бы рекомендовал вам * включить * включить его, но установить 'android: required =" false "'. Я действительно не думаю, что это коренная проблема, но все равно хорошо. – kcoppock

+0

@MichaelKrause - это точно такой же код для разных версий Android. –

ответ

0

Это нормально, чтобы получить это исключение на < 4,3 устройств, поскольку BLE не существует, поэтому ваш скомпилированный код не может найти соответствующие классы в ОС. Ничего плохого в пути сборки.

Лучшим решением является защита вашего кода BLE в предложении if, тестирование возможностей BLE во время выполнения. Вы должны также выбирать версию операционной системы в случае как:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {...} 

Вы должны объявить android:required="false" для этой функции, то это означает, что приложение предпочитает использовать функцию, если на устройстве, но он предназначен для работы без указанной функции, если необходимо.

<uses-feature android:name="android.hardware.bluetooth_le" android:required="false" /> 
+0

Спасибо за отзыв. Однако проблема заключается в том, что MainActivity.class (с моим кодом Bluetooth) не может быть найден в версиях Android <4.3 (вызывая исключение), поэтому мы даже не доходим до предложения if. –

+0

Я думаю, вы также должны добавить проверку ОС, которая обеспечит, чтобы этот код не был достигнут для версий с низкой ОС во время компиляции (я обновил ответ). – Murphy

0

теперь, когда вы используете API-интерфейсы, которые не могут быть доступны в более ранних версиях Android, убедитесь, что вы упаковываются приложение с соответствующей библиотекой поддержки.

Например, см. Это android sample BluetoothLeGattSample. Он использует ниже lib.

dependencies { 
     // Add the support lib that is appropriate for SDK 18 
     compile "com.android.support:support-v13:19.0.+" 
    } 

see android docs for eclipse instructions for support library setup

+0

Ashoke - Спасибо за ваш совет. Я пробовал поддержку android-support-v13.jar для пути сборки Eclipse, но без радости. –

2

Попробуйте получить все связанные Ble кода в отдельный класс, который вы только экземпляр вообще, если на устройстве с необходимыми уровнями API. Я думаю, что без этого обратные вызовы могут привести к вашим проблемам.

1

Я обнаружил, что определение статического ответа le статически в действии вызывает ошибку, но включение его в функцию с проверкой api не приведет к той же ошибке.

вместо:

@TargetApi(Build.VERSION_CODES.LOLLIPOP){ 
    public class RouteMapActivity extends ActionBarActivity 

    private BluetoothAdapter.LeScanCallback mScanCallback = new ScanCallback() {...} 

Я использовал:

private void setUpLeCallbacks(){ 


    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { 
     settings = new ScanSettings.Builder() 
       .setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY) 
       .build(); 

     for (BTDeviceName device : mTestPointsToRead) { 
      ScanFilter filter = new ScanFilter.Builder().setDeviceAddress(device.le_serial).build(); 
      filters.add(filter); 
     } 

     mScanCallback = new ScanCallback() { 
      @Override 
      public void onScanResult(int callbackType, ScanResult result) { 
       super.onScanResult(callbackType, result); 
      } 

      @Override 
      public void onScanFailed(int errorCode) { 
       super.onScanFailed(errorCode); 
      } 
     }; 
    }else { 
     mLeScanCallback= new BluetoothAdapter.LeScanCallback() { 

      @Override 
      public void onLeScan(final BluetoothDevice device, int rssi, byte[] scanRecord) { 

      } 
     }; 

    } 
} 
+0

Как вы добавили глобальные переменные без получения предупреждений VFY от dalivk? –

+1

@TargetApi (Build.VERSION_CODES.LOLLIPOP) отменяет ошибки lint. – TacoEater

 Смежные вопросы

  • Нет связанных вопросов^_^