105void QBluetoothDeviceDiscoveryAgentPrivate::start(QBluetoothDeviceDiscoveryAgent::DiscoveryMethods methods)
107 requestedMethods = methods;
114 Q_Q(QBluetoothDeviceDiscoveryAgent);
116 if (!adapter.isValid()) {
117 qCWarning(QT_BT_ANDROID) <<
"Device does not support Bluetooth";
118 lastError = QBluetoothDeviceDiscoveryAgent::InputOutputError;
119 errorString = QBluetoothDeviceDiscoveryAgent::tr(
"Device does not support Bluetooth");
120 emit q->errorOccurred(lastError);
124 if (!adapterAddress.isNull()
125 && adapter.callMethod<jstring>(
"getAddress").toString()
126 != adapterAddress.toString()) {
127 qCWarning(QT_BT_ANDROID) <<
"Incorrect local adapter passed.";
128 lastError = QBluetoothDeviceDiscoveryAgent::InvalidBluetoothAdapterError;
129 errorString = QBluetoothDeviceDiscoveryAgent::tr(
"Passed address is not a local device.");
130 emit q->errorOccurred(lastError);
134 if (setErrorIfPowerOff())
137 if (!ensureAndroidPermission(QBluetoothPermission::Access)) {
138 qCWarning(QT_BT_ANDROID)
139 <<
"Search not possible due to missing QBluetoothPermission::Access permission";
140 errorString = QBluetoothDeviceDiscoveryAgent::tr(
141 "Failed to start device discovery due to missing permissions.");
142 lastError = QBluetoothDeviceDiscoveryAgent::MissingPermissionsError;
143 emit q->errorOccurred(lastError);
146 qCDebug(QT_BT_ANDROID) <<
"QBluetoothPermission::Access permission available";
148 const bool scanNeedsLocation = (
bool)QtJniTypes::QtBtUtility::callStaticMethod<jboolean>(
149 "bluetoothScanRequiresLocation", QNativeInterface::QAndroidApplication::context());
151 qCDebug(QT_BT_ANDROID) <<
"Is location service and location permission required for scan:"
152 << scanNeedsLocation;
154 if (scanNeedsLocation) {
158 QLocationPermission locationPermission;
159 locationPermission.setAccuracy(QLocationPermission::Accuracy::Precise);
161 if (qApp->checkPermission(locationPermission) != Qt::PermissionStatus::Granted) {
162 qCWarning(QT_BT_ANDROID) <<
"Search not possible due to missing location permissions";
163 lastError = QBluetoothDeviceDiscoveryAgent::LocationServiceTurnedOffError;
164 errorString = QBluetoothDeviceDiscoveryAgent::tr(
"Location permission not granted. Search is not possible.");
165 emit q->errorOccurred(lastError);
169 qCDebug(QT_BT_ANDROID) <<
"Location permission granted";
172 bool locationTurnedOn =
true;
173 const QJniObject locString = QJniObject::getStaticObjectField(
174 "android/content/Context",
"LOCATION_SERVICE",
"Ljava/lang/String;");
176 const QJniObject locService =
177 QJniObject(QNativeInterface::QAndroidApplication::context()).callMethod<jobject>(
179 locString.object<jstring>());
181 if (locService.isValid()) {
182 if (QNativeInterface::QAndroidApplication::sdkVersion() >= 28) {
183 locationTurnedOn =
bool(locService.callMethod<jboolean>(
"isLocationEnabled"));
186 QJniObject listOfEnabledProviders =
187 locService.callMethod<QtJniTypes::List>(
"getProviders",
true);
189 if (listOfEnabledProviders.isValid()) {
190 int size = listOfEnabledProviders.callMethod<jint>(
"size");
191 locationTurnedOn = size > 0;
192 qCDebug(QT_BT_ANDROID) << size <<
"enabled location providers detected.";
197 if (!locationTurnedOn) {
198 qCWarning(QT_BT_ANDROID) <<
"Search not possible due to turned off Location service";
199 lastError = QBluetoothDeviceDiscoveryAgent::LocationServiceTurnedOffError;
200 errorString = QBluetoothDeviceDiscoveryAgent::tr(
"Location service turned off. Search is not possible.");
201 emit q->errorOccurred(lastError);
205 qCDebug(QT_BT_ANDROID) <<
"Location turned on";
211 receiver =
new DeviceDiscoveryBroadcastReceiver();
212 qRegisterMetaType<QBluetoothDeviceInfo>();
213 QObject::connect(receiver, SIGNAL(deviceDiscovered(QBluetoothDeviceInfo,
bool)),
214 this, SLOT(processDiscoveredDevices(QBluetoothDeviceInfo,
bool)));
215 QObject::connect(receiver, SIGNAL(finished()),
this, SLOT(processSdpDiscoveryFinished()));
218 lastError = QBluetoothDeviceDiscoveryAgent::NoError;
220 discoveredDevices.clear();
223 if (requestedMethods & QBluetoothDeviceDiscoveryAgent::ClassicMethod) {
224 const bool success = adapter.callMethod<jboolean>(
"startDiscovery");
226 qCDebug(QT_BT_ANDROID) <<
"Classic Discovery cannot be started";
230 if (requestedMethods == QBluetoothDeviceDiscoveryAgent::ClassicMethod) {
231 classicDiscoveryStartFail();
235 m_active = SDPScanActive;
236 if (!deviceDiscoveryStartTimeout) {
243 deviceDiscoveryStartTimeout =
new QTimer(
this);
244 deviceDiscoveryStartTimeout->setInterval(deviceDiscoveryStartTimeLimit);
245 deviceDiscoveryStartTimeout->setSingleShot(
true);
246 QObject::connect(receiver, &DeviceDiscoveryBroadcastReceiver::discoveryStarted,
247 deviceDiscoveryStartTimeout, &QTimer::stop);
248 QObject::connect(deviceDiscoveryStartTimeout, &QTimer::timeout,
this, [
this]() {
249 deviceDiscoveryStartAttemptsLeft -= 1;
250 qCWarning(QT_BT_ANDROID) <<
"Discovery start not received, attempts left:"
251 << deviceDiscoveryStartAttemptsLeft;
253 if (setErrorIfPowerOff())
257 if (deviceDiscoveryStartAttemptsLeft <= 0) {
258 qCWarning(QT_BT_ANDROID) <<
"Classic device discovery failed to start";
259 (
void)adapter.callMethod<jboolean>(
"cancelDiscovery");
263 if (deviceDiscoveryStartAttemptsLeft > 0 &&
264 adapter.callMethod<jboolean>(
"startDiscovery"))
265 deviceDiscoveryStartTimeout->start();
266 else if (requestedMethods == QBluetoothDeviceDiscoveryAgent::ClassicMethod)
267 classicDiscoveryStartFail();
269 startLowEnergyScan();
272 deviceDiscoveryStartAttemptsLeft = deviceDiscoveryStartMaxAttempts;
273 deviceDiscoveryStartTimeout->start();
275 qCDebug(QT_BT_ANDROID)
276 <<
"QBluetoothDeviceDiscoveryAgentPrivate::start() - Classic search successfully started.";
281 if (requestedMethods & QBluetoothDeviceDiscoveryAgent::LowEnergyMethod) {
283 startLowEnergyScan();