Skip to content

Commit

Permalink
Merge branch 'release/v0.0.10'
Browse files Browse the repository at this point in the history
  • Loading branch information
kshoji committed Jul 1, 2021
2 parents b3a0c04 + 1509bd2 commit 73f9ca7
Show file tree
Hide file tree
Showing 80 changed files with 1,248 additions and 221 deletions.
10 changes: 6 additions & 4 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
language: android
jdk: oraclejdk7
dist: trusty
jdk: openjdk8
android:
components:
- build-tools-22.0.1
- android-22
- build-tools-30.0.2
- android-29
- extra-android-m2repository
- extra-google-m2repository
licenses:
- '.+'
before_install:
- chmod +x gradlew
- chmod +x gradlew
- yes | sdkmanager "build-tools;30.0.2"
script:
- ./gradlew check

File renamed without changes.
17 changes: 8 additions & 9 deletions library/build.gradle → BLE-MIDI-library/build.gradle
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
apply plugin: 'com.android.library'

android {
compileSdkVersion 22
buildToolsVersion "22.0.1"
compileSdkVersion 29

defaultConfig {
minSdkVersion 18
Expand All @@ -23,24 +22,24 @@ android {

repositories {
maven {
url 'https://github.com/kshoji/javax.sound.midi-for-Android/raw/master/javax.sound.midi/repository'
url 'https://github.com/kshoji/javax.sound.midi-for-Android/raw/develop/javax.sound.midi/repository'
}
mavenCentral()
}

dependencies {
compile 'jp.kshoji:javax-sound-midi:0.0.3:@aar'
//noinspection GradleDependency
compile 'com.android.support:support-annotations:22.2.1'
compile fileTree(dir: 'libs', include: ['*.jar'])
api 'jp.kshoji:javax-sound-midi:0.0.4:@aar'
api 'com.android.support:support-annotations:28.0.0'
compileOnly project(':UnityPlayerMock')
api fileTree(dir: 'libs', include: ['*.jar'])
}

apply plugin: 'maven'
group = 'jp.kshoji'
uploadArchives {
repositories.mavenDeployer {
repository url: 'file://' + file('repository').absolutePath
pom.version = '0.0.9'
repository url: 'file://' + file('../library/repository').absolutePath
pom.version = '0.0.10'
pom.artifactId = 'ble-midi'
}
}
Expand Down
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="jp.kshoji.blemidi">

<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />

<uses-feature android:name="android.hardware.bluetooth_le" android:required="true" />

</manifest>
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@
public final class BleMidiCallback extends BluetoothGattCallback {
private final Map<String, Set<MidiInputDevice>> midiInputDevicesMap = new HashMap<>();
private final Map<String, Set<MidiOutputDevice>> midiOutputDevicesMap = new HashMap<>();
private final Map<String, BluetoothGatt> deviceAddressGattMap = new HashMap<>();
private final Map<String, List<BluetoothGatt>> deviceAddressGattMap = new HashMap<>();
private final Context context;

private OnMidiDeviceAttachedListener midiDeviceAttachedListener;
Expand Down Expand Up @@ -77,44 +77,63 @@ boolean isConnected(@NonNull BluetoothDevice device) {
}
}

private volatile static Object gattDiscoverServicesLock = null;
@Override
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
super.onConnectionStateChange(gatt, status, newState);
// In this method, the `status` parameter shall be ignored.
// so, look `newState` parameter only.

if (newState == BluetoothProfile.STATE_CONNECTED) {
if (!deviceAddressGattMap.containsKey(gatt.getDevice().getAddress())) {
if (gatt.discoverServices()) {
// successfully started discovering
} else {
// already disconnected
disconnectByDeviceAddress(gatt.getDevice().getAddress());
if (deviceAddressGattMap.containsKey(gatt.getDevice().getAddress())) {
return;
}
// process a device for the same time
while (gattDiscoverServicesLock != null) {
try {
Thread.sleep(10);
} catch (InterruptedException ignored) {
}
}
if (deviceAddressGattMap.containsKey(gatt.getDevice().getAddress())) {
// same device has already registered
return;
}
gattDiscoverServicesLock = gatt;
if (gatt.discoverServices()) {
// successfully started discovering
} else {
// already disconnected
disconnectByDeviceAddress(gatt.getDevice().getAddress());
gattDiscoverServicesLock = null;
}
} else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
disconnectByDeviceAddress(gatt.getDevice().getAddress());
gattDiscoverServicesLock = null;
}
}

@SuppressLint("NewApi")
@SuppressLint({"NewApi", "MissingPermission"})
@Override
public void onServicesDiscovered(final BluetoothGatt gatt, int status) {
super.onServicesDiscovered(gatt, status);

if (status != BluetoothGatt.GATT_SUCCESS) {
gattDiscoverServicesLock = null;
return;
}

final String gattDeviceAddress = gatt.getDevice().getAddress();

// find MIDI Input device
if (midiInputDevicesMap.containsKey(gattDeviceAddress)) {
synchronized (midiInputDevicesMap) {
synchronized (midiInputDevicesMap) {
if (midiInputDevicesMap.containsKey(gattDeviceAddress)) {
Set<MidiInputDevice> midiInputDevices = midiInputDevicesMap.get(gattDeviceAddress);
for (MidiInputDevice midiInputDevice : midiInputDevices) {
((InternalMidiInputDevice) midiInputDevice).stop();
midiInputDevice.setOnMidiInputEventListener(null);
if (midiInputDevices != null) {
for (MidiInputDevice midiInputDevice : midiInputDevices) {
((InternalMidiInputDevice) midiInputDevice).stop();
midiInputDevice.setOnMidiInputEventListener(null);
}
}
midiInputDevicesMap.remove(gattDeviceAddress);
}
Expand All @@ -138,18 +157,17 @@ public void onServicesDiscovered(final BluetoothGatt gatt, int status) {
}

// don't notify if the same device already connected
if (!deviceAddressGattMap.containsKey(gattDeviceAddress)) {
if (!deviceAddressGattMap.containsKey(gattDeviceAddress))
{
if (midiDeviceAttachedListener != null) {
midiDeviceAttachedListener.onMidiInputDeviceAttached(midiInputDevice);
}
}
}

// find MIDI Output device
if (midiOutputDevicesMap.containsKey(gattDeviceAddress)) {
synchronized (midiOutputDevicesMap) {
midiOutputDevicesMap.remove(gattDeviceAddress);
}
synchronized (midiOutputDevicesMap) {
midiOutputDevicesMap.remove(gattDeviceAddress);
}

MidiOutputDevice midiOutputDevice = null;
Expand Down Expand Up @@ -179,15 +197,25 @@ public void onServicesDiscovered(final BluetoothGatt gatt, int status) {

if (midiInputDevice != null || midiOutputDevice != null) {
synchronized (deviceAddressGattMap) {
deviceAddressGattMap.put(gattDeviceAddress, gatt);
List<BluetoothGatt> bluetoothGatts = deviceAddressGattMap.get(gattDeviceAddress);
if (bluetoothGatts == null) {
bluetoothGatts = new ArrayList<>();
deviceAddressGattMap.put(gattDeviceAddress, bluetoothGatts);
}
bluetoothGatts.add(gatt);
}

if (needsBonding && Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
// Create bond and configure Gatt, if this is BLE MIDI device
BluetoothDevice bluetoothDevice = gatt.getDevice();
if (bluetoothDevice.getBondState() != BluetoothDevice.BOND_BONDED) {
bluetoothDevice.createBond();
bluetoothDevice.setPairingConfirmation(true);
try {
bluetoothDevice.setPairingConfirmation(true);
} catch (Throwable t) {
// SecurityException if android.permission.BLUETOOTH_PRIVILEGED not available
Log.d(Constants.TAG, t.getMessage());
}

if (bondingBroadcastReceiver != null) {
context.unregisterReceiver(bondingBroadcastReceiver);
Expand All @@ -214,25 +242,19 @@ public void onServicesDiscovered(final BluetoothGatt gatt, int status) {
gatt.requestConnectionPriority(BluetoothGatt.CONNECTION_PRIORITY_HIGH);
}
}

// all finished
gattDiscoverServicesLock = null;
}

@Override
public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
super.onCharacteristicChanged(gatt, characteristic);

Set<MidiInputDevice> midiInputDevices = midiInputDevicesMap.get(gatt.getDevice().getAddress());
for (MidiInputDevice midiInputDevice : midiInputDevices) {
((InternalMidiInputDevice)midiInputDevice).incomingData(characteristic.getValue());
}
}

@Override
public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {
super.onDescriptorWrite(gatt, descriptor, status);

if (descriptor != null) {
if (Arrays.equals(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE, descriptor.getValue())) {
gatt.setCharacteristicNotification(descriptor.getCharacteristic(), true);
if (midiInputDevices != null) {
for (MidiInputDevice midiInputDevice : midiInputDevices) {
((InternalMidiInputDevice)midiInputDevice).incomingData(characteristic.getValue());
}
}
}
Expand Down Expand Up @@ -270,11 +292,13 @@ void disconnectDevice(@NonNull MidiOutputDevice midiOutputDevice) {
*/
private void disconnectByDeviceAddress(@NonNull String deviceAddress) {
synchronized (deviceAddressGattMap) {
BluetoothGatt bluetoothGatt = deviceAddressGattMap.get(deviceAddress);
List<BluetoothGatt> bluetoothGatts = deviceAddressGattMap.get(deviceAddress);

if (bluetoothGatt != null) {
bluetoothGatt.disconnect();
bluetoothGatt.close();
if (bluetoothGatts != null) {
for (BluetoothGatt bluetoothGatt : bluetoothGatts) {
bluetoothGatt.disconnect();
bluetoothGatt.close();
}

deviceAddressGattMap.remove(deviceAddress);
}
Expand Down Expand Up @@ -318,9 +342,13 @@ private void disconnectByDeviceAddress(@NonNull String deviceAddress) {
*/
public void terminate() {
synchronized (deviceAddressGattMap) {
for (BluetoothGatt bluetoothGatt : deviceAddressGattMap.values()) {
bluetoothGatt.disconnect();
bluetoothGatt.close();
for (List<BluetoothGatt> bluetoothGatts : deviceAddressGattMap.values()) {
if (bluetoothGatts != null) {
for (BluetoothGatt bluetoothGatt : bluetoothGatts) {
bluetoothGatt.disconnect();
bluetoothGatt.close();
}
}
}
deviceAddressGattMap.clear();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothManager;
Expand Down Expand Up @@ -46,11 +47,30 @@ public final class BleMidiCentralProvider {
private final BluetoothAdapter.LeScanCallback leScanCallback = new BluetoothAdapter.LeScanCallback() {
@Override
public void onLeScan(final BluetoothDevice bluetoothDevice, int rssi, byte[] scanRecord) {

if (bluetoothDevice.getType() != BluetoothDevice.DEVICE_TYPE_LE && bluetoothDevice.getType() != BluetoothDevice.DEVICE_TYPE_DUAL) {
return;
}

bluetoothDevice.connectGatt(context, true, midiCallback);
if (context instanceof Activity) {
((Activity) context).runOnUiThread(new Runnable() {
@Override
public void run() {
bluetoothDevice.connectGatt(context, true, midiCallback);
}
});
} else {
if (Thread.currentThread() == context.getMainLooper().getThread()) {
bluetoothDevice.connectGatt(context, true, midiCallback);
} else {
handler.post(new Runnable() {
@Override
public void run() {
bluetoothDevice.connectGatt(context, true, midiCallback);
}
});
}
}
}
};

Expand Down Expand Up @@ -98,7 +118,25 @@ public void onScanResult(int callbackType, ScanResult result) {
}

if (!midiCallback.isConnected(bluetoothDevice)) {
bluetoothDevice.connectGatt(BleMidiCentralProvider.this.context, true, midiCallback);
if (context instanceof Activity) {
((Activity) context).runOnUiThread(new Runnable() {
@Override
public void run() {
bluetoothDevice.connectGatt(BleMidiCentralProvider.this.context, true, midiCallback);
}
});
} else {
if (Thread.currentThread() == context.getMainLooper().getThread()) {
bluetoothDevice.connectGatt(BleMidiCentralProvider.this.context, true, midiCallback);
} else {
handler.post(new Runnable() {
@Override
public void run() {
bluetoothDevice.connectGatt(BleMidiCentralProvider.this.context, true, midiCallback);
}
});
}
}
}
}
}
Expand Down Expand Up @@ -175,7 +213,9 @@ public void run() {
public void stopScanDevice() {
try {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
bluetoothAdapter.getBluetoothLeScanner().stopScan(scanCallback);
final BluetoothLeScanner bluetoothLeScanner = bluetoothAdapter.getBluetoothLeScanner();
bluetoothLeScanner.flushPendingScanResults(scanCallback);
bluetoothLeScanner.stopScan(scanCallback);
} else {
bluetoothAdapter.stopLeScan(leScanCallback);
}
Expand Down Expand Up @@ -265,7 +305,7 @@ public void setOnMidiDeviceDetachedListener(@Nullable OnMidiDeviceDetachedListen
* Terminates provider
*/
public void terminate() {
stopScanDevice();
midiCallback.terminate();
stopScanDevice();
}
}
Loading

0 comments on commit 73f9ca7

Please sign in to comment.