Я довольно активно работаю над приложением Bluetooth (некоторые подробности здесь). Природа приложения заключается в том, что я в значительной степени поддерживаю BT всегда и ждут изменений в названиях BT от некоторых вещательных устройств. Использование питания не является проблемой, поскольку мое устройство постоянно заряжается.
Я обнаружил, что в определенное время мое приложение "теряет поток" и ничего не обнаруживает на BT, даже если BT включен, и есть устройства в радиусе действия. В ручном режиме я могу решить это, выключив и включив BT на устройстве - престо! Он работает снова. Поэтому я хотел сделать это в коде. У меня есть таймер таймаута, который отправляет сообщение обработчику:
bluetoothHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
if (!btAdapter.isDiscovering())
{
btAdapter.disable();
btAdapter.enable();
btAdapter.startDiscovery();
// some other stuff
}
Ну, этот код, по-видимому, иногда сбой с исключением с нулевым указателем на строке "disable"
Здесь информация ACRA:
"java.lang.NullPointerException
at android.os.Parcel.readException(Parcel.java:1328)
at android.os.Parcel.readException(Parcel.java:1276)
at android.bluetooth.IBluetooth$Stub$Proxy.disable(IBluetooth.java:604)
at android.bluetooth.BluetoothAdapter.disable(BluetoothAdapter.java:562)
at com.myapp.stuff.MainActivity$8.handleMessage(MainActivity.java:574)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:130)
at android.app.ActivityThread.main(ActivityThread.java:3687)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:507)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:842)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:600)
at dalvik.system.NativeStart.main(Native Method)
Как вы можете видеть, не имеет смысла, что btAdapter действительно имеет значение null, иначе мы бы разбились на строку раньше ("if") - и даже если код будет реентеративным, я никогда не удаляю btAdapter в мой код в любой момент - я установил его в OnCreate и оставил его навсегда, так как он становится равным нулю?
Я видел пару человек, которые сообщают, что они получили NullPointerException с кодом с включением/отключением - и предложения по использованию намерений для запуска/остановки Bluetooth - здесь это не вариант - нет вмешательства пользователя - пользователя (если они хотят этого скорее специализированное приложение для работы) требует, чтобы BT был запущен (и если он не был исправлен автоматически).
Я предполагаю, что я не могу поставить попытку/улов вокруг исключения NullPointerException (хотя это и подделка). Кто-нибудь знает достаточно о внутренних функциях Bluetooth, чтобы понять, почему отключается отключение?
Ну, я не совсем понимаю, что происходит не так, но мое исправление было довольно простым и глупым:
Вместо того, чтобы оставлять одно значение для btAdapter, я проверяю его каждый раз перед его использованием и try/catch для любого исключения (хотя я предполагаю, что это не приведет к отображению REAL null указателя)
Поэтому каждый раз, когда я cll disable (который рушился), я делаю это
btAdapter = BluetoothAdapter.getDefaultAdapter();
if (null == btAdapter)
{
Log.e(LOG_TAG,"Bluetooth adapter is NULL!!!");
return;
}
try {
btAdapter.disable();
}
catch (Exception e) {
//don't do anything
}
Я думаю, вы должны поставить утверждение как первую строку своей функции handleMessage, например assertNotNull (btAdapter). Вот документ для Assert. По крайней мере, вы точно знаете, что btAdapter действительно не является нулевым.
Это действительно не решает вашу проблему, но ваша проблема - напоминание о том, что утверждения могут быть полезными.
Это происходит внутри метода disable
. Может быть, чтение исходного кода на Android в файле BluetoothAdapter.java, строка 562 поможет вам понять, что может вызвать эту проблему.