diff options
author | Alex Blasche <alexander.blasche@qt.io> | 2016-08-04 12:54:48 +0200 |
---|---|---|
committer | Alex Blasche <alexander.blasche@qt.io> | 2017-01-23 07:15:40 +0000 |
commit | 72f7df5738a8ed168c9d10a0474a5c42999250e8 (patch) | |
tree | 3522515e42f657b43e7057e78bde4edc5e0129e2 /src/android | |
parent | 8a0d14f4933bcd933e1258731472479ec33ade6a (diff) |
Android: Beginnings of Android Bluetooth Peripheral support
Focus is on the Java side of things. The Gatt server & LE advertiser
can be started and stopped.
This patch builds the foundation for future changes. The C++ side is only
very rudimentary and a lot of debugging helper are left inside the
new code sections.
Change-Id: Ic56da3ec6471ccb438fc2088fbf5eeb3053d5cf1
Reviewed-by: Timur Pocheptsov <timur.pocheptsov@qt.io>
Reviewed-by: Alex Blasche <alexander.blasche@qt.io>
Diffstat (limited to 'src/android')
-rw-r--r-- | src/android/bluetooth/bluetooth.pri | 5 | ||||
-rw-r--r-- | src/android/bluetooth/src/org/qtproject/qt5/android/bluetooth/QtBluetoothLEServer.java | 207 |
2 files changed, 210 insertions, 2 deletions
diff --git a/src/android/bluetooth/bluetooth.pri b/src/android/bluetooth/bluetooth.pri index 16d3b612..fa811ac1 100644 --- a/src/android/bluetooth/bluetooth.pri +++ b/src/android/bluetooth/bluetooth.pri @@ -1,6 +1,6 @@ CONFIG += java DESTDIR = $$[QT_INSTALL_PREFIX/get]/jar -API_VERSION = android-18 +API_VERSION = android-21 PATHPREFIX = $$PWD/src/org/qtproject/qt5/android/bluetooth @@ -9,7 +9,8 @@ JAVASOURCES += \ $$PATHPREFIX/QtBluetoothBroadcastReceiver.java \ $$PATHPREFIX/QtBluetoothSocketServer.java \ $$PATHPREFIX/QtBluetoothInputStreamThread.java \ - $$PATHPREFIX/QtBluetoothLE.java + $$PATHPREFIX/QtBluetoothLE.java \ + $$PATHPREFIX/QtBluetoothLEServer.java # install target.path = $$[QT_INSTALL_PREFIX]/jar diff --git a/src/android/bluetooth/src/org/qtproject/qt5/android/bluetooth/QtBluetoothLEServer.java b/src/android/bluetooth/src/org/qtproject/qt5/android/bluetooth/QtBluetoothLEServer.java new file mode 100644 index 00000000..343ab552 --- /dev/null +++ b/src/android/bluetooth/src/org/qtproject/qt5/android/bluetooth/QtBluetoothLEServer.java @@ -0,0 +1,207 @@ +/**************************************************************************** + ** + ** Copyright (C) 2016 The Qt Company Ltd. + ** Contact: https://www.qt.io/licensing/ + ** + ** This file is part of the QtBluetooth module of the Qt Toolkit. + ** + ** $QT_BEGIN_LICENSE:LGPL$ + ** Commercial License Usage + ** Licensees holding valid commercial Qt licenses may use this file in + ** accordance with the commercial license agreement provided with the + ** Software or, alternatively, in accordance with the terms contained in + ** a written agreement between you and The Qt Company. For licensing terms + ** and conditions see https://www.qt.io/terms-conditions. For further + ** information use the contact form at https://www.qt.io/contact-us. + ** + ** GNU Lesser General Public License Usage + ** Alternatively, this file may be used under the terms of the GNU Lesser + ** General Public License version 3 as published by the Free Software + ** Foundation and appearing in the file LICENSE.LGPL3 included in the + ** packaging of this file. Please review the following information to + ** ensure the GNU Lesser General Public License version 3 requirements + ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. + ** + ** GNU General Public License Usage + ** Alternatively, this file may be used under the terms of the GNU + ** General Public License version 2.0 or (at your option) the GNU General + ** Public license version 3 or any later version approved by the KDE Free + ** Qt Foundation. The licenses are as published by the Free Software + ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 + ** included in the packaging of this file. Please review the following + ** information to ensure the GNU General Public License requirements will + ** be met: https://www.gnu.org/licenses/gpl-2.0.html and + ** https://www.gnu.org/licenses/gpl-3.0.html. + ** + ** $QT_END_LICENSE$ + ** + ****************************************************************************/ + +package org.qtproject.qt5.android.bluetooth; + +import android.bluetooth.BluetoothDevice; +import android.bluetooth.BluetoothGattCharacteristic; +import android.bluetooth.BluetoothGattDescriptor; +import android.bluetooth.BluetoothGattService; +import android.content.Context; +import android.bluetooth.BluetoothAdapter; +import android.bluetooth.BluetoothGattServer; +import android.bluetooth.BluetoothGattServerCallback; +import android.bluetooth.BluetoothManager; +import android.bluetooth.le.AdvertiseCallback; +import android.bluetooth.le.AdvertiseData; +import android.bluetooth.le.AdvertiseData.Builder; +import android.bluetooth.le.AdvertiseSettings; +import android.bluetooth.le.BluetoothLeAdvertiser; +import android.os.ParcelUuid; +import android.util.Log; + +import java.util.UUID; + +public class QtBluetoothLEServer { + private static final String TAG = "QtBluetoothGattServer"; + + /* Pointer to the Qt object that "owns" the Java object */ + @SuppressWarnings({"CanBeFinal", "WeakerAccess"}) + long qtObject = 0; + @SuppressWarnings("WeakerAccess") + + private Context qtContext = null; + + // Bluetooth members + private final BluetoothAdapter mBluetoothAdapter; + private BluetoothGattServer mGattServer = null; + private BluetoothLeAdvertiser mLeAdvertiser = null; + + public QtBluetoothLEServer(Context context) + { + qtContext = context; + mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); + + if (mBluetoothAdapter == null || qtContext == null) { + Log.w(TAG, "Missing Bluetooth adapter or Qt context. Peripheral role disabled."); + return; + } + + BluetoothManager manager = (BluetoothManager) qtContext.getSystemService(Context.BLUETOOTH_SERVICE); + if (manager == null) { + Log.w(TAG, "Bluetooth service not available."); + return; + } + + mGattServer = manager.openGattServer(qtContext, mGattServerListener); + mLeAdvertiser = mBluetoothAdapter.getBluetoothLeAdvertiser(); + + if (!mBluetoothAdapter.isMultipleAdvertisementSupported()) + Log.w(TAG, "Device does not support Bluetooth Low Energy advertisement."); + else + Log.w(TAG, "Let's do BTLE Peripheral."); + } + + /* + * Call back handler for the Gatt Server. + */ + private BluetoothGattServerCallback mGattServerListener = new BluetoothGattServerCallback() + { + @Override + public void onConnectionStateChange(BluetoothDevice device, int status, int newState) { + super.onConnectionStateChange(device, status, newState); + } + + @Override + public void onServiceAdded(int status, BluetoothGattService service) { + super.onServiceAdded(status, service); + } + + @Override + public void onCharacteristicReadRequest(BluetoothDevice device, int requestId, int offset, BluetoothGattCharacteristic characteristic) { + super.onCharacteristicReadRequest(device, requestId, offset, characteristic); + } + + @Override + public void onCharacteristicWriteRequest(BluetoothDevice device, int requestId, BluetoothGattCharacteristic characteristic, boolean preparedWrite, boolean responseNeeded, int offset, byte[] value) { + super.onCharacteristicWriteRequest(device, requestId, characteristic, preparedWrite, responseNeeded, offset, value); + } + + @Override + public void onDescriptorReadRequest(BluetoothDevice device, int requestId, int offset, BluetoothGattDescriptor descriptor) { + super.onDescriptorReadRequest(device, requestId, offset, descriptor); + } + + @Override + public void onDescriptorWriteRequest(BluetoothDevice device, int requestId, BluetoothGattDescriptor descriptor, boolean preparedWrite, boolean responseNeeded, int offset, byte[] value) { + super.onDescriptorWriteRequest(device, requestId, descriptor, preparedWrite, responseNeeded, offset, value); + } + + @Override + public void onExecuteWrite(BluetoothDevice device, int requestId, boolean execute) { + super.onExecuteWrite(device, requestId, execute); + } + + @Override + public void onNotificationSent(BluetoothDevice device, int status) { + super.onNotificationSent(device, status); + } + + // MTU change disabled since it requires API level 22. Right now we only enforce lvl 21 +// @Override +// public void onMtuChanged(BluetoothDevice device, int mtu) { +// super.onMtuChanged(device, mtu); +// } + }; + + public void disconnect() + { + if (mGattServer == null) + return; + + mGattServer.close(); + } + + public void startAdvertising() + { + if (mLeAdvertiser == null) + return; + + // TODO for now everything hardcoded to get basic working frame + AdvertiseData.Builder dataBuilder = new AdvertiseData.Builder(); + dataBuilder.setIncludeDeviceName(true); + dataBuilder.setIncludeTxPowerLevel(false); + + // randomly chosen UUID below + dataBuilder.addServiceUuid(ParcelUuid.fromString("e8e10f95-1a70-4b27-9ccf-02010264e9c8")); + + AdvertiseSettings.Builder settingsBuilder = new AdvertiseSettings.Builder(); + settingsBuilder.setAdvertiseMode(AdvertiseSettings.ADVERTISE_MODE_BALANCED); + settingsBuilder.setConnectable(true); // prevents beacon mode + settingsBuilder.setTimeout(0); + settingsBuilder.setTxPowerLevel(AdvertiseSettings.ADVERTISE_TX_POWER_MEDIUM); + + mLeAdvertiser.startAdvertising(settingsBuilder.build(), dataBuilder.build(), mAdvertiseListener); + } + + public void stopAdvertising() + { + if (mLeAdvertiser == null) + return; + + mLeAdvertiser.stopAdvertising(mAdvertiseListener); + } + + /* + * Call back handler for Advertisement requests. + */ + private AdvertiseCallback mAdvertiseListener = new AdvertiseCallback() + { + @Override + public void onStartSuccess(AdvertiseSettings settingsInEffect) { + super.onStartSuccess(settingsInEffect); + } + + @Override + public void onStartFailure(int errorCode) { + super.onStartFailure(errorCode); + } + }; + +} |