- 
    Bug 
- 
    Resolution: Done
- 
    P1: Critical 
- 
    5.3.2
- 
    None
- 
    Android 4.0.3, HTC Sensation
In my code I simply wanted to get the Bluetooth name of the device using:
    QBluetoothLocalDevice btDev;
 However, on the HTC sensation phone the constructor of QBluetoothLocalDevice already crashes with the following message:
W/dalvikvm(14544): Invalid indirect reference 0x40e2ace8 in decodeIndirectRef
E/dalvikvm(14544): VM aborting
F/libc    (14544): Fatal signal 11 (SIGSEGV) at 0xdeadd00d (code=1)
To see where it really crashes, I copied the code from QBluetoothLocalDevicePrivate::initialize() into my app and added some debug output after each step.
So the code is this:
    QAndroidJniEnvironment env;
    qWarning() << "QT_XXXX 1";
    jclass btAdapterClass = env->FindClass("android/bluetooth/BluetoothAdapter");
    if (btAdapterClass == NULL) {
        qWarning() << "Native registration unable to find class android/bluetooth/BluetoothAdapter";
    }
    else
    {
      jmethodID getDefaultAdapterID = env->GetStaticMethodID(btAdapterClass, "getDefaultAdapter", "()Landroid/bluetooth/BluetoothAdapter;");
      qWarning() << "QT_XXXX 2";
      if (getDefaultAdapterID == NULL) {
          qWarning() << "Native registration unable to get method ID: getDefaultAdapter of android/bluetooth/BluetoothAdapter";
      }
      else
      {
        jobject btAdapterObject = env->CallStaticObjectMethod(btAdapterClass, getDefaultAdapterID);
        qWarning() << "QT_XXXX 3";
        if (btAdapterObject == NULL) {
            qWarning() <<  "Device does not support Bluetooth";
            env->DeleteLocalRef(btAdapterClass);
        }
        else
        {
          obj = QAndroidJniObject(btAdapterObject);
          qWarning() << "QT_XXXX 4";
          if (!obj.isValid()) {
          } else {
            QBluetoothAddress address;
            qWarning() << "QT_XXXX 5";
              if (!address.isNull()) {
                  const QString localAddress = obj.callObjectMethod("getAddress", "()Ljava/lang/String;").toString();
          qWarning() << "QT_XXXX 6";
                  //if (localAddress != address.toString()) {
                      //passed address not local one -> invalid
                  //}
              }
          }
          env->DeleteLocalRef(btAdapterObject);
          qWarning() << "QT_XXXX 7";
          env->DeleteLocalRef(btAdapterClass);
          qWarning() << "QT_XXXX 8";
        }
      }
    }
and the debug log on the device is mainly just printing 
W/Qt      (14544): ... QT_XXXX 1
W/Qt      (14544): ... QT_XXXX 2
W/Qt      (14544): ... QT_XXXX 3
W/dalvikvm(14544): Invalid indirect reference 0x40e2ace8 in decodeIndirectRef
Further testing shows, that the call to BluetoothAdapter.getDefaultAdapter();
throws an exception:
java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
When I call
obj = QAndroidJniObject::callStaticObjectMethod("android/bluetooth/BluetoothAdapter",
                                                    "getDefaultAdapter", "()Landroid/bluetooth/BluetoothAdapter;");
then the obj is not valid - but at least it does not crash.
So I think a modification of the QBluetoothLocalDevice ctor would be good to use the above code and does not crash.
| For Gerrit Dashboard: QTBUG-45066 | ||||||
|---|---|---|---|---|---|---|
| # | Subject | Branch | Project | Status | CR | V | 
| 108842,3 | Android: Fix crash in QBluetoothLocalDevice ctor due to Java exception | 5.4 | qt/qtconnectivity | Status: MERGED | +2 | 0 | 
| 175713,2 | Android: Fix crash in QBluetoothDeviceDiscoveryAgent ctor due to Java exception | 5.6 | qt/qtconnectivity | Status: MERGED | +2 | 0 |