summaryrefslogtreecommitdiffstats
path: root/src/android
diff options
context:
space:
mode:
authorAlex Blasche <alexander.blasche@qt.io>2016-08-04 12:54:48 +0200
committerAlex Blasche <alexander.blasche@qt.io>2017-01-23 07:15:40 +0000
commit72f7df5738a8ed168c9d10a0474a5c42999250e8 (patch)
tree3522515e42f657b43e7057e78bde4edc5e0129e2 /src/android
parent8a0d14f4933bcd933e1258731472479ec33ade6a (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.pri5
-rw-r--r--src/android/bluetooth/src/org/qtproject/qt5/android/bluetooth/QtBluetoothLEServer.java207
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);
+ }
+ };
+
+}