Skip to content

Commit cb35a98

Browse files
committed
add android aar file and support for ble, rename muse athena
Signed-off-by: Andrey Parfenov <a1994ndrey@gmail.com>
1 parent 945fee8 commit cb35a98

37 files changed

Lines changed: 848 additions & 142 deletions

.github/workflows/run_android.yml

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,15 @@ jobs:
1414

1515
env:
1616
ANDROID_NDK_VERSION: 25.1.8937393
17+
ANDROID_API_LEVEL: android-31
1718

1819
steps:
1920
- name: Clone Repository
2021
uses: actions/checkout@v2
22+
- name: Setup Java
23+
uses: actions/setup-java@v1
24+
with:
25+
java-version: 11.0.3
2126
- name: Install Ninja
2227
run: |
2328
sudo -H apt-get update -y
@@ -30,7 +35,7 @@ jobs:
3035
cmakeVersion: '3.21.4'
3136
- name: Install NDK
3237
run: |
33-
echo "y" | sudo -H ${ANDROID_SDK_ROOT}/cmdline-tools/latest/bin/sdkmanager --install "ndk;${ANDROID_NDK_VERSION}" --sdk_root=${ANDROID_SDK_ROOT}
38+
echo "y" | sudo -H ${ANDROID_SDK_ROOT}/cmdline-tools/latest/bin/sdkmanager --install "ndk;${ANDROID_NDK_VERSION}" "platforms;${ANDROID_API_LEVEL}" --sdk_root=${ANDROID_SDK_ROOT}
3439
env:
3540
DEBIAN_FRONTEND: noninteractive
3641
# build for all ABIs
@@ -47,7 +52,7 @@ jobs:
4752
for ABI in arm64-v8a armeabi-v7a x86 x86_64; do
4853
mkdir $GITHUB_WORKSPACE/libftdi/build-$ABI
4954
cd $GITHUB_WORKSPACE/libftdi/build-$ABI
50-
cmake -G Ninja -DCMAKE_TOOLCHAIN_FILE=${ANDROID_HOME}/ndk/${ANDROID_NDK_VERSION}/build/cmake/android.toolchain.cmake -DANDROID_ABI=$ABI -DCMAKE_BUILD_TYPE=Release -DANDROID_NATIVE_API_LEVEL=android-24 -DEXAMPLES=OFF -DFTDI_EEPROM=OFF -DLIBUSB_LIBRARIES=$GITHUB_WORKSPACE/libusb/android/libs/$ABI/libusb1.0.so -DLIBUSB_INCLUDE_DIR=$GITHUB_WORKSPACE/libusb/libusb -DCMAKE_INSTALL_PREFIX=$GITHUB_WORKSPACE/install-$ABI ..
55+
cmake -G Ninja -DCMAKE_TOOLCHAIN_FILE=${ANDROID_HOME}/ndk/${ANDROID_NDK_VERSION}/build/cmake/android.toolchain.cmake -DANDROID_ABI=$ABI -DCMAKE_BUILD_TYPE=Release -DANDROID_NATIVE_API_LEVEL=${ANDROID_API_LEVEL} -DEXAMPLES=OFF -DFTDI_EEPROM=OFF -DLIBUSB_LIBRARIES=$GITHUB_WORKSPACE/libusb/android/libs/$ABI/libusb1.0.so -DLIBUSB_INCLUDE_DIR=$GITHUB_WORKSPACE/libusb/libusb -DCMAKE_INSTALL_PREFIX=$GITHUB_WORKSPACE/install-$ABI ..
5156
ninja
5257
ninja install
5358
done
@@ -56,20 +61,16 @@ jobs:
5661
for ABI in arm64-v8a armeabi-v7a x86 x86_64; do
5762
mkdir $GITHUB_WORKSPACE/build-$ABI
5863
cd $GITHUB_WORKSPACE/build-$ABI
59-
cmake -G Ninja -DCMAKE_TOOLCHAIN_FILE=${ANDROID_HOME}/ndk/${ANDROID_NDK_VERSION}/build/cmake/android.toolchain.cmake -DANDROID_ABI=$ABI -DCMAKE_BUILD_TYPE=Release -DANDROID_NATIVE_API_LEVEL=android-24 -DCMAKE_FIND_ROOT_PATH=$GITHUB_WORKSPACE/install-$ABI -DUSE_LIBFTDI=ON ..
64+
cmake -G Ninja -DCMAKE_TOOLCHAIN_FILE=${ANDROID_HOME}/ndk/${ANDROID_NDK_VERSION}/build/cmake/android.toolchain.cmake -DANDROID_ABI=$ABI -DCMAKE_BUILD_TYPE=Release -DANDROID_NATIVE_API_LEVEL=${ANDROID_API_LEVEL} -DCMAKE_FIND_ROOT_PATH=$GITHUB_WORKSPACE/install-$ABI -DUSE_LIBFTDI=ON ..
6065
ninja
6166
done
62-
- name: Prepare Zip
63-
run: |
64-
cd $GITHUB_WORKSPACE/tools
65-
zip -r jniLibs.zip jniLibs
67+
- name: Build Android AAR
68+
run: python3 $GITHUB_WORKSPACE/tools/build_android_aar.py --android-sdk-root ${ANDROID_SDK_ROOT} --android-api-level ${ANDROID_API_LEVEL} --output $GITHUB_WORKSPACE/tools/brainflow-android.aar
6669
- name: Install AWS CLI
6770
run: sudo -H python3 -m pip install awscli==1.35.24
6871
- name: Upload To AWS
6972
if: ${{ github.event_name == 'push' && github.repository == 'brainflow-dev/brainflow' }}
70-
run: |
71-
cd $GITHUB_WORKSPACE/tools
72-
aws s3 cp jniLibs.zip s3://brainflow/$GITHUB_SHA/
73+
run: aws s3 cp $GITHUB_WORKSPACE/tools/brainflow-android.aar s3://brainflow/$GITHUB_SHA/brainflow-android.aar
7374
env:
7475
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
7576
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}

.gitignore

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -367,6 +367,11 @@ rust_package/brainflow/lib/
367367
rust_package/brainflow/inc/
368368
src/ml/train/data/
369369
src/ml/train/data/*.onnx
370+
tools/brainflow-android.aar
371+
build_android_aar/
372+
tools/simpleble-bridge.jar
373+
tools/simpleble-bridge-classes/
374+
tools/simpleble-bridge-sources.txt
370375

371376
# CMake & GNU Make
372377
CMakeCache.txt

CMakeLists.txt

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,10 @@ option (BUILD_ONNX "BUILD_ONNX" OFF)
2828
option (BUILD_TESTS "BUILD_TESTS" OFF)
2929
option (BUILD_PERIPHERY "BUILD_PERIPHERY" OFF)
3030

31+
if (ANDROID)
32+
set (BUILD_BLE ON CACHE BOOL "BUILD_BLE" FORCE)
33+
endif (ANDROID)
34+
3135
include (${CMAKE_CURRENT_SOURCE_DIR}/cmake/macros.cmake)
3236
configure_msvc_runtime ()
3337

@@ -76,4 +80,4 @@ install (
7680
EXPORT ${TARGETS_EXPORT_NAME}
7781
NAMESPACE brainflow::
7882
DESTINATION ${CONFIG_INSTALL_DIR}
79-
)
83+
)

csharp_package/brainflow/brainflow/board_controller_library.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
using System.Runtime.InteropServices;
1+
using System.Runtime.InteropServices;
22

33

44
namespace brainflow
@@ -123,7 +123,7 @@ public enum BoardIds
123123
BIOLISTENER_BOARD = 64,
124124
IRONBCI_32_BOARD = 65,
125125
NEUROPAWN_KNIGHT_BOARD_IMU = 66,
126-
MUSE_S_ANTHENA_BOARD = 67
126+
MUSE_S_ATHENA_BOARD = 67
127127
};
128128

129129

docs/BuildBrainFlow.rst

Lines changed: 28 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -253,29 +253,38 @@ To check supported boards for Android visit :ref:`supported-boards-label`
253253
Installation instructions
254254
~~~~~~~~~~~~~~~~~~~~~~~~~~~
255255

256-
- Create Java project in Android Studio, Kotlin is not supported
257-
- Download *jniLibs.zip* from `Release page <https://github.com/brainflow-dev/brainflow/releases>`_
258-
- Unpack *jniLibs.zip* and copy it's content to *project/app/src/main/jniLibs*
259-
- Download *brainflow-jar-with-dependencies.jar* from `Release page <https://github.com/brainflow-dev/brainflow/releases>`_ or from `Github package <https://github.com/brainflow-dev/brainflow/packages/290893>`_
260-
- Copy *brainflow-jar-with-dependencies.jar* to *project/app/libs folder*
256+
- Create an Android project in Android Studio
257+
- Download *brainflow-android.aar* from `Release page <https://github.com/brainflow-dev/brainflow/releases>`_
258+
- Copy *brainflow-android.aar* to *project/app/libs*
259+
- Add it to your app dependencies ::
260+
261+
dependencies {
262+
implementation files('libs/brainflow-android.aar')
263+
}
261264

262265
Now you can use BrainFlow SDK in your Android application!
263266

264267
Note: Android Studio inline compiler may show red errors but it should be compiled fine with Gradle. To fix inline compiler you can use *File > Sync Project with Gradle Files* or click at *File > Invalidate Cache/Restart > Invalidate and Restart*
265268

266-
Prebuild libraries for *jniLibs.zip* are complied using:
269+
Prebuilt libraries inside *brainflow-android.aar* are compiled using:
267270

268271
- Android NDK 25.1.8937393
269-
- *-DANDROID_NATIVE_API_LEVEL=android-24*
272+
- *-DANDROID_NATIVE_API_LEVEL=android-31*
273+
274+
Prebuilt Android libraries require API 31 or newer. BLE support is always enabled for Android builds and the SimpleBLE bridge is packaged into the AAR.
270275

271276
.. compound::
272277

273-
For some API calls you need to provide additional permissions via manifest file of your application ::
278+
The AAR declares Bluetooth permissions via its manifest, but Android 12+ still requires runtime approval for :code:`BLUETOOTH_SCAN` and :code:`BLUETOOTH_CONNECT` before creating a BrainFlow BLE board. For network or storage boards, or if you do not use manifest merging, add the required permissions to your application manifest manually ::
274279

275280
<uses-permission android:name="android.permission.INTERNET"></uses-permission>
276281
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"></uses-permission>
277282
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"></uses-permission>
278283
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>
284+
<uses-permission android:name="android.permission.BLUETOOTH" android:maxSdkVersion="30"></uses-permission>
285+
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" android:maxSdkVersion="30"></uses-permission>
286+
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" android:usesPermissionFlags="neverForLocation"></uses-permission>
287+
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT"></uses-permission>
279288

280289

281290
Compilation using Android NDK
@@ -293,20 +302,27 @@ Compilation instructions:
293302
- You can also try *MinGW Makefiles* instead *Ninja*, but it's not tested and may not work
294303
- Build C++ code using cmake and *Ninja* for **all ABIs**
295304
- Compiled libraries will be in *tools/jniLibs* folder
305+
- Build the AAR using *tools/build_android_aar.py*
296306

297307
.. compound::
298308

299309
Command line examples: ::
300310

301311
# to prepare project(choose ABIs which you need)
302312
# for arm64-v8a
303-
cmake -G Ninja -DCMAKE_TOOLCHAIN_FILE=D:\workspace\android-ndk-r25b\build\cmake\android.toolchain.cmake -DANDROID_NATIVE_API_LEVEL=android-24 -DANDROID_ABI=arm64-v8a ..
313+
cmake -G Ninja -DCMAKE_TOOLCHAIN_FILE=D:\workspace\android-ndk-r25b\build\cmake\android.toolchain.cmake -DANDROID_NATIVE_API_LEVEL=android-31 -DANDROID_ABI=arm64-v8a ..
304314
# for armeabi-v7a
305-
cmake -G Ninja -DCMAKE_TOOLCHAIN_FILE=D:\workspace\android-ndk-r25b\build\cmake\android.toolchain.cmake -DANDROID_NATIVE_API_LEVEL=android-24 -DANDROID_ABI=armeabi-v7a ..
315+
cmake -G Ninja -DCMAKE_TOOLCHAIN_FILE=D:\workspace\android-ndk-r25b\build\cmake\android.toolchain.cmake -DANDROID_NATIVE_API_LEVEL=android-31 -DANDROID_ABI=armeabi-v7a ..
306316
# for x86_64
307-
cmake -G Ninja -DCMAKE_TOOLCHAIN_FILE=D:\workspace\android-ndk-r25b\build\cmake\android.toolchain.cmake -DANDROID_NATIVE_API_LEVEL=android-24 -DANDROID_ABI=x86_64 ..
317+
cmake -G Ninja -DCMAKE_TOOLCHAIN_FILE=D:\workspace\android-ndk-r25b\build\cmake\android.toolchain.cmake -DANDROID_NATIVE_API_LEVEL=android-31 -DANDROID_ABI=x86_64 ..
308318
# for x86
309-
cmake -G Ninja -DCMAKE_TOOLCHAIN_FILE=D:\workspace\android-ndk-r25b\build\cmake\android.toolchain.cmake -DANDROID_NATIVE_API_LEVEL=android-24 -DANDROID_ABI=x86 ..
319+
cmake -G Ninja -DCMAKE_TOOLCHAIN_FILE=D:\workspace\android-ndk-r25b\build\cmake\android.toolchain.cmake -DANDROID_NATIVE_API_LEVEL=android-31 -DANDROID_ABI=x86 ..
310320

311321
# to build(should be run for each ABI from previous step**
312322
cmake --build . --target install --config Release -j 2 --parallel 2
323+
324+
# build Java wrapper, SimpleBLE bridge jar, and package single Android artifact
325+
python tools/build_android_aar.py
326+
327+
# or build native libraries and package a local AAR in one command
328+
python tools/build_android_aar.py --build-native --abis arm64-v8a --allow-missing-abis

docs/SupportedBoards.rst

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -751,7 +751,7 @@ Supported platforms:
751751
Muse
752752
------
753753

754-
Muse startup commands can be selected with :code:`BrainFlowInputParams.other_info`. Use a shorthand such as :code:`p21` or a key-value form such as :code:`preset=p21`. If :code:`other_info` is empty, BrainFlow uses the default command listed in the device section. :code:`low_latency` is only supported for MuseS Anthena.
754+
Muse startup commands can be selected with :code:`BrainFlowInputParams.other_info`. Use a shorthand such as :code:`p21` or a key-value form such as :code:`preset=p21`. If :code:`other_info` is empty, BrainFlow uses the default command listed in the device section. :code:`low_latency` is only supported for MuseS Athena.
755755

756756

757757
Muse S
@@ -821,7 +821,7 @@ Available :ref:`presets-label`:
821821
- :code:`BrainFlowPresets.ANCILLARY_PRESET`, it contains PPG data, to enable it use :code:`board.config_board("p61")`
822822

823823

824-
MuseS Anthena
824+
MuseS Athena
825825
~~~~~~~~~~~~~~
826826

827827
.. image:: https://live.staticflickr.com/65535/55236436914_6e442f3192.jpg
@@ -840,18 +840,18 @@ MuseS Anthena
840840

841841
To create such board you need to specify the following board ID and fields of BrainFlowInputParams object:
842842

843-
- :code:`BoardIds.MUSE_S_ANTHENA_BOARD`
843+
- :code:`BoardIds.MUSE_S_ATHENA_BOARD`
844844
- *optional:* :code:`mac_address`, mac address of the device to connect
845845
- *optional:* :code:`serial_number`, device name, can be printed on the Muse device or discovered via mobile apps
846-
- *optional:* :code:`other_info`, MuseS Anthena startup options
846+
- *optional:* :code:`other_info`, MuseS Athena startup options
847847

848848
Initialization Example:
849849

850850
.. code-block:: python
851851
852852
params = BrainFlowInputParams()
853853
params.other_info = "preset=p1041;low_latency=true"
854-
board = BoardShim(BoardIds.MUSE_S_ANTHENA_BOARD, params)
854+
board = BoardShim(BoardIds.MUSE_S_ATHENA_BOARD, params)
855855
856856
Supported platforms:
857857

@@ -917,7 +917,7 @@ Available :ref:`presets-label`:
917917

918918
- :code:`BrainFlowPresets.DEFAULT_PRESET`, it contains EEG data, sampling rate is 256 Hz. For 4-channel Muse presets BrainFlow exposes :code:`TP9`, :code:`AF7`, :code:`AF8`, and :code:`TP10` as EEG channels. For 8-channel Muse presets the additional Muse EEG values are exposed as other channels.
919919
- :code:`BrainFlowPresets.AUXILIARY_PRESET`, it contains Accelerometer and Gyro data, sampling rate is 52 Hz.
920-
- :code:`BrainFlowPresets.ANCILLARY_PRESET`, it contains optics and battery data. Optics sampling rate is 64 Hz. MuseS Anthena uses optics data for PPG, and BrainFlow exposes this data as optical channels instead of PPG channels. Depending on selected Muse preset, the stream contains 4, 8, or 16 optical channels.
920+
- :code:`BrainFlowPresets.ANCILLARY_PRESET`, it contains optics and battery data. Optics sampling rate is 64 Hz. MuseS Athena uses optics data for PPG, and BrainFlow exposes this data as optical channels instead of PPG channels. Depending on selected Muse preset, the stream contains 4, 8, or 16 optical channels.
921921

922922

923923
Muse 2

java_package/brainflow/pom.xml

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,11 @@
77
<description>java binding for brainflow library</description>
88
<url>https://brainflow.org/</url>
99

10+
<properties>
11+
<maven.compiler.source>11</maven.compiler.source>
12+
<maven.compiler.target>11</maven.compiler.target>
13+
</properties>
14+
1015
<licenses>
1116
<license>
1217
<name>MIT</name>
@@ -101,8 +106,8 @@
101106
<artifactId>maven-compiler-plugin</artifactId>
102107
<version>3.8.0</version>
103108
<configuration>
104-
<source>11</source>
105-
<target>11</target>
109+
<source>${maven.compiler.source}</source>
110+
<target>${maven.compiler.target}</target>
106111
</configuration>
107112
</plugin>
108113

@@ -145,6 +150,26 @@
145150
</plugins>
146151

147152
</build>
153+
154+
<profiles>
155+
<profile>
156+
<id>android</id>
157+
<build>
158+
<plugins>
159+
<plugin>
160+
<groupId>org.apache.maven.plugins</groupId>
161+
<artifactId>maven-compiler-plugin</artifactId>
162+
<configuration>
163+
<excludes>
164+
<exclude>module-info.java</exclude>
165+
</excludes>
166+
</configuration>
167+
</plugin>
168+
</plugins>
169+
</build>
170+
</profile>
171+
</profiles>
172+
148173
<dependencies>
149174
<dependency>
150175
<groupId>net.java.dev.jna</groupId>

java_package/brainflow/src/main/java/brainflow/BoardIds.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ public enum BoardIds
7373
BIOLISTENER_BOARD(64),
7474
IRONBCI_32_BOARD(65),
7575
NEUROPAWN_KNIGHT_BOARD_IMU(66),
76-
MUSE_S_ANTHENA_BOARD(67);
76+
MUSE_S_ATHENA_BOARD(67);
7777

7878
private final int board_id;
7979
private static final Map<Integer, BoardIds> bi_map = new HashMap<Integer, BoardIds> ();

java_package/brainflow/src/main/java/brainflow/BoardShim.java

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -159,8 +159,14 @@ int get_current_board_data (int num_samples, int preset, double[] data_buf, int[
159159

160160
if (is_os_android)
161161
{
162-
// for android you need to put these files manually to jniLibs folder, unpacking
163-
// doesnt work
162+
// Android native libraries are loaded from the app or BrainFlow AAR.
163+
try
164+
{
165+
System.loadLibrary ("simpleble-c");
166+
} catch (UnsatisfiedLinkError e)
167+
{
168+
// Android packages built without BLE do not ship SimpleBLE.
169+
}
164170
lib_name = "BoardController"; // no lib prefix and no extension for android
165171
} else
166172
{

java_package/brainflow/src/main/java/brainflow/MLModel.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,8 +74,7 @@ private interface DllInterface extends Library
7474

7575
if (is_os_android)
7676
{
77-
// for android you need to put these files manually to jniLibs folder, unpacking
78-
// doesnt work
77+
// Android native libraries are loaded from the app or BrainFlow AAR.
7978
lib_name = "MLModule"; // no lib prefix and no extension for android
8079
} else
8180
{

0 commit comments

Comments
 (0)