Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 11 additions & 10 deletions .github/workflows/run_android.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,15 @@ jobs:

env:
ANDROID_NDK_VERSION: 25.1.8937393
ANDROID_API_LEVEL: android-31

steps:
- name: Clone Repository
uses: actions/checkout@v2
- name: Setup Java
uses: actions/setup-java@v1
with:
java-version: 11.0.3
- name: Install Ninja
run: |
sudo -H apt-get update -y
Expand All @@ -30,7 +35,7 @@ jobs:
cmakeVersion: '3.21.4'
- name: Install NDK
run: |
echo "y" | sudo -H ${ANDROID_SDK_ROOT}/cmdline-tools/latest/bin/sdkmanager --install "ndk;${ANDROID_NDK_VERSION}" --sdk_root=${ANDROID_SDK_ROOT}
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}
env:
DEBIAN_FRONTEND: noninteractive
# build for all ABIs
Expand All @@ -47,7 +52,7 @@ jobs:
for ABI in arm64-v8a armeabi-v7a x86 x86_64; do
mkdir $GITHUB_WORKSPACE/libftdi/build-$ABI
cd $GITHUB_WORKSPACE/libftdi/build-$ABI
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 ..
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 ..
ninja
ninja install
done
Expand All @@ -56,20 +61,16 @@ jobs:
for ABI in arm64-v8a armeabi-v7a x86 x86_64; do
mkdir $GITHUB_WORKSPACE/build-$ABI
cd $GITHUB_WORKSPACE/build-$ABI
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 ..
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 ..
ninja
done
- name: Prepare Zip
run: |
cd $GITHUB_WORKSPACE/tools
zip -r jniLibs.zip jniLibs
- name: Build Android AAR
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
- name: Install AWS CLI
run: sudo -H python3 -m pip install awscli==1.35.24
- name: Upload To AWS
if: ${{ github.event_name == 'push' && github.repository == 'brainflow-dev/brainflow' }}
run: |
cd $GITHUB_WORKSPACE/tools
aws s3 cp jniLibs.zip s3://brainflow/$GITHUB_SHA/
run: aws s3 cp $GITHUB_WORKSPACE/tools/brainflow-android.aar s3://brainflow/$GITHUB_SHA/brainflow-android.aar
env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,11 @@ rust_package/brainflow/lib/
rust_package/brainflow/inc/
src/ml/train/data/
src/ml/train/data/*.onnx
tools/brainflow-android.aar
build_android_aar/
tools/simpleble-bridge.jar
tools/simpleble-bridge-classes/
tools/simpleble-bridge-sources.txt

# CMake & GNU Make
CMakeCache.txt
Expand Down
6 changes: 5 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ option (BUILD_ONNX "BUILD_ONNX" OFF)
option (BUILD_TESTS "BUILD_TESTS" OFF)
option (BUILD_PERIPHERY "BUILD_PERIPHERY" OFF)

if (ANDROID)
set (BUILD_BLE ON CACHE BOOL "BUILD_BLE" FORCE)
endif (ANDROID)

include (${CMAKE_CURRENT_SOURCE_DIR}/cmake/macros.cmake)
configure_msvc_runtime ()

Expand Down Expand Up @@ -76,4 +80,4 @@ install (
EXPORT ${TARGETS_EXPORT_NAME}
NAMESPACE brainflow::
DESTINATION ${CONFIG_INSTALL_DIR}
)
)
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using System.Runtime.InteropServices;
using System.Runtime.InteropServices;


namespace brainflow
Expand Down Expand Up @@ -123,7 +123,7 @@ public enum BoardIds
BIOLISTENER_BOARD = 64,
IRONBCI_32_BOARD = 65,
NEUROPAWN_KNIGHT_BOARD_IMU = 66,
MUSE_S_ANTHENA_BOARD = 67
MUSE_S_ATHENA_BOARD = 67
};


Expand Down
40 changes: 28 additions & 12 deletions docs/BuildBrainFlow.rst
Original file line number Diff line number Diff line change
Expand Up @@ -253,29 +253,38 @@ To check supported boards for Android visit :ref:`supported-boards-label`
Installation instructions
~~~~~~~~~~~~~~~~~~~~~~~~~~~

- Create Java project in Android Studio, Kotlin is not supported
- Download *jniLibs.zip* from `Release page <https://github.com/brainflow-dev/brainflow/releases>`_
- Unpack *jniLibs.zip* and copy it's content to *project/app/src/main/jniLibs*
- 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>`_
- Copy *brainflow-jar-with-dependencies.jar* to *project/app/libs folder*
- Create an Android project in Android Studio
- Download *brainflow-android.aar* from `Release page <https://github.com/brainflow-dev/brainflow/releases>`_
- Copy *brainflow-android.aar* to *project/app/libs*
- Add it to your app dependencies ::

dependencies {
implementation files('libs/brainflow-android.aar')
}

Now you can use BrainFlow SDK in your Android application!

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*

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

- Android NDK 25.1.8937393
- *-DANDROID_NATIVE_API_LEVEL=android-24*
- *-DANDROID_NATIVE_API_LEVEL=android-31*

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.

.. compound::

For some API calls you need to provide additional permissions via manifest file of your application ::
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 ::

<uses-permission android:name="android.permission.INTERNET"></uses-permission>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"></uses-permission>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"></uses-permission>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>
<uses-permission android:name="android.permission.BLUETOOTH" android:maxSdkVersion="30"></uses-permission>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" android:maxSdkVersion="30"></uses-permission>
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" android:usesPermissionFlags="neverForLocation"></uses-permission>
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT"></uses-permission>


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

.. compound::

Command line examples: ::

# to prepare project(choose ABIs which you need)
# for arm64-v8a
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 ..
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 ..
# for armeabi-v7a
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 ..
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 ..
# for x86_64
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 ..
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 ..
# for x86
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 ..
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 ..

# to build(should be run for each ABI from previous step**
cmake --build . --target install --config Release -j 2 --parallel 2

# build Java wrapper, SimpleBLE bridge jar, and package single Android artifact
python tools/build_android_aar.py

# or build native libraries and package a local AAR in one command
python tools/build_android_aar.py --build-native --abis arm64-v8a --allow-missing-abis
12 changes: 6 additions & 6 deletions docs/SupportedBoards.rst
Original file line number Diff line number Diff line change
Expand Up @@ -751,7 +751,7 @@ Supported platforms:
Muse
------

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.
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.


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


MuseS Anthena
MuseS Athena
~~~~~~~~~~~~~~

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

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

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

Initialization Example:

.. code-block:: python

params = BrainFlowInputParams()
params.other_info = "preset=p1041;low_latency=true"
board = BoardShim(BoardIds.MUSE_S_ANTHENA_BOARD, params)
board = BoardShim(BoardIds.MUSE_S_ATHENA_BOARD, params)

Supported platforms:

Expand Down Expand Up @@ -917,7 +917,7 @@ Available :ref:`presets-label`:

- :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.
- :code:`BrainFlowPresets.AUXILIARY_PRESET`, it contains Accelerometer and Gyro data, sampling rate is 52 Hz.
- :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.
- :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.


Muse 2
Expand Down
29 changes: 27 additions & 2 deletions java_package/brainflow/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@
<description>java binding for brainflow library</description>
<url>https://brainflow.org/</url>

<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
</properties>

<licenses>
<license>
<name>MIT</name>
Expand Down Expand Up @@ -101,8 +106,8 @@
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
<configuration>
<source>11</source>
<target>11</target>
<source>${maven.compiler.source}</source>
<target>${maven.compiler.target}</target>
</configuration>
</plugin>

Expand Down Expand Up @@ -145,6 +150,26 @@
</plugins>

</build>

<profiles>
<profile>
<id>android</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<excludes>
<exclude>module-info.java</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</profile>
</profiles>

<dependencies>
<dependency>
<groupId>net.java.dev.jna</groupId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ public enum BoardIds
BIOLISTENER_BOARD(64),
IRONBCI_32_BOARD(65),
NEUROPAWN_KNIGHT_BOARD_IMU(66),
MUSE_S_ANTHENA_BOARD(67);
MUSE_S_ATHENA_BOARD(67);

private final int board_id;
private static final Map<Integer, BoardIds> bi_map = new HashMap<Integer, BoardIds> ();
Expand Down
10 changes: 8 additions & 2 deletions java_package/brainflow/src/main/java/brainflow/BoardShim.java
Original file line number Diff line number Diff line change
Expand Up @@ -159,8 +159,14 @@ int get_current_board_data (int num_samples, int preset, double[] data_buf, int[

if (is_os_android)
{
// for android you need to put these files manually to jniLibs folder, unpacking
// doesnt work
// Android native libraries are loaded from the app or BrainFlow AAR.
try
{
System.loadLibrary ("simpleble-c");
} catch (UnsatisfiedLinkError e)
{
// Android packages built without BLE do not ship SimpleBLE.
}
lib_name = "BoardController"; // no lib prefix and no extension for android
} else
{
Expand Down
3 changes: 1 addition & 2 deletions java_package/brainflow/src/main/java/brainflow/MLModel.java
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,7 @@ private interface DllInterface extends Library

if (is_os_android)
{
// for android you need to put these files manually to jniLibs folder, unpacking
// doesnt work
// Android native libraries are loaded from the app or BrainFlow AAR.
lib_name = "MLModule"; // no lib prefix and no extension for android
} else
{
Expand Down
2 changes: 1 addition & 1 deletion julia_package/brainflow/src/board_shim.jl
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ export BrainFlowInputParams
BIOLISTENER_BOARD = 64
IRONBCI_32_BOARD = 65
NEUROPAWN_KNIGHT_BOARD_IMU = 66
MUSE_S_ANTHENA_BOARD = 67
MUSE_S_ATHENA_BOARD = 67

end

Expand Down
2 changes: 1 addition & 1 deletion matlab_package/brainflow/BoardIds.m
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,6 @@
BIOLISTENER_BOARD(64)
IRONBCI_32_BOARD(65)
NEUROPAWN_KNIGHT_BOARD_IMU(66)
MUSE_S_ANTHENA_BOARD(67)
MUSE_S_ATHENA_BOARD(67)
end
end
2 changes: 1 addition & 1 deletion nodejs_package/brainflow/brainflow.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ export enum BoardIds {
BIOLISTENER_BOARD = 64,
IRONBCI_32_BOARD = 65,
NEUROPAWN_KNIGHT_BOARD_IMU = 66,
MUSE_S_ANTHENA_BOARD = 67
MUSE_S_ATHENA_BOARD = 67
}

export enum IpProtocolTypes {
Expand Down
2 changes: 1 addition & 1 deletion python_package/brainflow/board_shim.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ class BoardIds(enum.IntEnum):
BIOLISTENER_BOARD = 64 #:
IRONBCI_32_BOARD = 65 #:
NEUROPAWN_KNIGHT_BOARD_IMU = 66 #:
MUSE_S_ANTHENA_BOARD = 67 #:
MUSE_S_ATHENA_BOARD = 67 #:


class IpProtocolTypes(enum.IntEnum):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ def save_spectrum_plot(freqs, power, spectrum_bpm, output_file):

def main():
parser = argparse.ArgumentParser()
parser.add_argument('--input-file', type=str, required=False, default='muse_anthena_optics_recording.csv')
parser.add_argument('--input-file', type=str, required=False, default='muse_athena_optics_recording.csv')
parser.add_argument('--output-prefix', type=str, required=False, default='')
parser.add_argument('--discard-seconds', type=float, required=False, default=5.0)
parser.add_argument('--low-cut', type=float, required=False, default=0.7)
Expand All @@ -212,7 +212,7 @@ def main():
args = parser.parse_args()

data = DataFilter.read_file(args.input_file)
board_id = BoardIds.MUSE_S_ANTHENA_BOARD.value
board_id = BoardIds.MUSE_S_ATHENA_BOARD.value
preset = BrainFlowPresets.ANCILLARY_PRESET
optical_channels = BoardShim.get_optical_channels(board_id, preset)
timestamp_channel = BoardShim.get_timestamp_channel(board_id, preset)
Expand Down
Loading
Loading