diff --git a/.travis.yml b/.travis.yml index c996c20..8f013db 100644 --- a/.travis.yml +++ b/.travis.yml @@ -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 diff --git a/library/.gitignore b/BLE-MIDI-library/.gitignore similarity index 100% rename from library/.gitignore rename to BLE-MIDI-library/.gitignore diff --git a/library/build.gradle b/BLE-MIDI-library/build.gradle similarity index 64% rename from library/build.gradle rename to BLE-MIDI-library/build.gradle index 35b48ee..ff1d46b 100644 --- a/library/build.gradle +++ b/BLE-MIDI-library/build.gradle @@ -1,8 +1,7 @@ apply plugin: 'com.android.library' android { - compileSdkVersion 22 - buildToolsVersion "22.0.1" + compileSdkVersion 29 defaultConfig { minSdkVersion 18 @@ -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' } } diff --git a/library/lint.xml b/BLE-MIDI-library/lint.xml similarity index 100% rename from library/lint.xml rename to BLE-MIDI-library/lint.xml diff --git a/library/proguard-rules.pro b/BLE-MIDI-library/proguard-rules.pro similarity index 100% rename from library/proguard-rules.pro rename to BLE-MIDI-library/proguard-rules.pro diff --git a/library/src/main/AndroidManifest.xml b/BLE-MIDI-library/src/main/AndroidManifest.xml similarity index 73% rename from library/src/main/AndroidManifest.xml rename to BLE-MIDI-library/src/main/AndroidManifest.xml index 2b8194e..a56a8aa 100644 --- a/library/src/main/AndroidManifest.xml +++ b/BLE-MIDI-library/src/main/AndroidManifest.xml @@ -1,5 +1,9 @@ + + + + diff --git a/library/src/main/java/jp/kshoji/blemidi/central/BleMidiCallback.java b/BLE-MIDI-library/src/main/java/jp/kshoji/blemidi/central/BleMidiCallback.java similarity index 86% rename from library/src/main/java/jp/kshoji/blemidi/central/BleMidiCallback.java rename to BLE-MIDI-library/src/main/java/jp/kshoji/blemidi/central/BleMidiCallback.java index a9db260..18b57e0 100644 --- a/library/src/main/java/jp/kshoji/blemidi/central/BleMidiCallback.java +++ b/BLE-MIDI-library/src/main/java/jp/kshoji/blemidi/central/BleMidiCallback.java @@ -47,7 +47,7 @@ public final class BleMidiCallback extends BluetoothGattCallback { private final Map> midiInputDevicesMap = new HashMap<>(); private final Map> midiOutputDevicesMap = new HashMap<>(); - private final Map deviceAddressGattMap = new HashMap<>(); + private final Map> deviceAddressGattMap = new HashMap<>(); private final Context context; private OnMidiDeviceAttachedListener midiDeviceAttachedListener; @@ -77,6 +77,7 @@ 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); @@ -84,37 +85,55 @@ public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState // 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 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); } @@ -138,7 +157,8 @@ 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); } @@ -146,10 +166,8 @@ public void onServicesDiscovered(final BluetoothGatt gatt, int status) { } // find MIDI Output device - if (midiOutputDevicesMap.containsKey(gattDeviceAddress)) { - synchronized (midiOutputDevicesMap) { - midiOutputDevicesMap.remove(gattDeviceAddress); - } + synchronized (midiOutputDevicesMap) { + midiOutputDevicesMap.remove(gattDeviceAddress); } MidiOutputDevice midiOutputDevice = null; @@ -179,7 +197,12 @@ public void onServicesDiscovered(final BluetoothGatt gatt, int status) { if (midiInputDevice != null || midiOutputDevice != null) { synchronized (deviceAddressGattMap) { - deviceAddressGattMap.put(gattDeviceAddress, gatt); + List 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) { @@ -187,7 +210,12 @@ public void onServicesDiscovered(final BluetoothGatt gatt, int status) { 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); @@ -214,6 +242,9 @@ public void onServicesDiscovered(final BluetoothGatt gatt, int status) { gatt.requestConnectionPriority(BluetoothGatt.CONNECTION_PRIORITY_HIGH); } } + + // all finished + gattDiscoverServicesLock = null; } @Override @@ -221,18 +252,9 @@ public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteris super.onCharacteristicChanged(gatt, characteristic); Set 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()); } } } @@ -270,11 +292,13 @@ void disconnectDevice(@NonNull MidiOutputDevice midiOutputDevice) { */ private void disconnectByDeviceAddress(@NonNull String deviceAddress) { synchronized (deviceAddressGattMap) { - BluetoothGatt bluetoothGatt = deviceAddressGattMap.get(deviceAddress); + List 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); } @@ -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 bluetoothGatts : deviceAddressGattMap.values()) { + if (bluetoothGatts != null) { + for (BluetoothGatt bluetoothGatt : bluetoothGatts) { + bluetoothGatt.disconnect(); + bluetoothGatt.close(); + } + } } deviceAddressGattMap.clear(); } diff --git a/library/src/main/java/jp/kshoji/blemidi/central/BleMidiCentralProvider.java b/BLE-MIDI-library/src/main/java/jp/kshoji/blemidi/central/BleMidiCentralProvider.java similarity index 80% rename from library/src/main/java/jp/kshoji/blemidi/central/BleMidiCentralProvider.java rename to BLE-MIDI-library/src/main/java/jp/kshoji/blemidi/central/BleMidiCentralProvider.java index ea4e147..66179b8 100644 --- a/library/src/main/java/jp/kshoji/blemidi/central/BleMidiCentralProvider.java +++ b/BLE-MIDI-library/src/main/java/jp/kshoji/blemidi/central/BleMidiCentralProvider.java @@ -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; @@ -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); + } + }); + } + } } }; @@ -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); + } + }); + } + } } } } @@ -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); } @@ -265,7 +305,7 @@ public void setOnMidiDeviceDetachedListener(@Nullable OnMidiDeviceDetachedListen * Terminates provider */ public void terminate() { - stopScanDevice(); midiCallback.terminate(); + stopScanDevice(); } } diff --git a/library/src/main/java/jp/kshoji/blemidi/device/MidiInputDevice.java b/BLE-MIDI-library/src/main/java/jp/kshoji/blemidi/device/MidiInputDevice.java similarity index 100% rename from library/src/main/java/jp/kshoji/blemidi/device/MidiInputDevice.java rename to BLE-MIDI-library/src/main/java/jp/kshoji/blemidi/device/MidiInputDevice.java diff --git a/library/src/main/java/jp/kshoji/blemidi/device/MidiOutputDevice.java b/BLE-MIDI-library/src/main/java/jp/kshoji/blemidi/device/MidiOutputDevice.java similarity index 100% rename from library/src/main/java/jp/kshoji/blemidi/device/MidiOutputDevice.java rename to BLE-MIDI-library/src/main/java/jp/kshoji/blemidi/device/MidiOutputDevice.java diff --git a/library/src/main/java/jp/kshoji/blemidi/listener/OnMidiDeviceAttachedListener.java b/BLE-MIDI-library/src/main/java/jp/kshoji/blemidi/listener/OnMidiDeviceAttachedListener.java similarity index 100% rename from library/src/main/java/jp/kshoji/blemidi/listener/OnMidiDeviceAttachedListener.java rename to BLE-MIDI-library/src/main/java/jp/kshoji/blemidi/listener/OnMidiDeviceAttachedListener.java diff --git a/library/src/main/java/jp/kshoji/blemidi/listener/OnMidiDeviceDetachedListener.java b/BLE-MIDI-library/src/main/java/jp/kshoji/blemidi/listener/OnMidiDeviceDetachedListener.java similarity index 100% rename from library/src/main/java/jp/kshoji/blemidi/listener/OnMidiDeviceDetachedListener.java rename to BLE-MIDI-library/src/main/java/jp/kshoji/blemidi/listener/OnMidiDeviceDetachedListener.java diff --git a/library/src/main/java/jp/kshoji/blemidi/listener/OnMidiInputEventListener.java b/BLE-MIDI-library/src/main/java/jp/kshoji/blemidi/listener/OnMidiInputEventListener.java similarity index 100% rename from library/src/main/java/jp/kshoji/blemidi/listener/OnMidiInputEventListener.java rename to BLE-MIDI-library/src/main/java/jp/kshoji/blemidi/listener/OnMidiInputEventListener.java diff --git a/library/src/main/java/jp/kshoji/blemidi/listener/OnMidiScanStatusListener.java b/BLE-MIDI-library/src/main/java/jp/kshoji/blemidi/listener/OnMidiScanStatusListener.java similarity index 100% rename from library/src/main/java/jp/kshoji/blemidi/listener/OnMidiScanStatusListener.java rename to BLE-MIDI-library/src/main/java/jp/kshoji/blemidi/listener/OnMidiScanStatusListener.java diff --git a/library/src/main/java/jp/kshoji/blemidi/peripheral/BleMidiPeripheralProvider.java b/BLE-MIDI-library/src/main/java/jp/kshoji/blemidi/peripheral/BleMidiPeripheralProvider.java similarity index 86% rename from library/src/main/java/jp/kshoji/blemidi/peripheral/BleMidiPeripheralProvider.java rename to BLE-MIDI-library/src/main/java/jp/kshoji/blemidi/peripheral/BleMidiPeripheralProvider.java index 56b5e18..d164d21 100644 --- a/library/src/main/java/jp/kshoji/blemidi/peripheral/BleMidiPeripheralProvider.java +++ b/BLE-MIDI-library/src/main/java/jp/kshoji/blemidi/peripheral/BleMidiPeripheralProvider.java @@ -4,6 +4,7 @@ import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothGatt; +import android.bluetooth.BluetoothGattCallback; import android.bluetooth.BluetoothGattCharacteristic; import android.bluetooth.BluetoothGattDescriptor; import android.bluetooth.BluetoothGattServer; @@ -15,10 +16,7 @@ import android.bluetooth.le.AdvertiseData; import android.bluetooth.le.AdvertiseSettings; import android.bluetooth.le.BluetoothLeAdvertiser; -import android.content.BroadcastReceiver; import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; import android.os.Build; import android.os.ParcelUuid; import android.support.annotation.NonNull; @@ -81,6 +79,7 @@ public final class BleMidiPeripheralProvider { private final BluetoothGattService midiGattService; private final BluetoothGattCharacteristic midiCharacteristic; private BluetoothGattServer gattServer; + private boolean gattServiceInitialized = false; private final Map midiInputDevicesMap = new HashMap<>(); private final Map midiOutputDevicesMap = new HashMap<>(); @@ -154,13 +153,24 @@ public void startAdvertising() { } // these service will be listened. - // FIXME these didn't used for service discovery - boolean serviceInitialized = false; - while (!serviceInitialized) { + while (!gattServiceInitialized) { + gattServer.clearServices(); try { gattServer.addService(informationGattService); + while (gattServer.getService(informationGattService.getUuid()) == null) { + try { + Thread.sleep(10); + } catch (InterruptedException ignored) { + } + } gattServer.addService(midiGattService);// NullPointerException, DeadObjectException thrown here - serviceInitialized = true; + while (gattServer.getService(midiGattService.getUuid()) == null) { + try { + Thread.sleep(10); + } catch (InterruptedException ignored) { + } + } + gattServiceInitialized = true; } catch (Exception e) { Log.d(Constants.TAG, "Adding Service failed, retrying.."); @@ -208,26 +218,6 @@ public void stopAdvertising() { } catch (IllegalStateException ignored) { // BT Adapter is not turned ON } - - if (gattServer != null) { - try { - gattServer.clearServices(); - } catch (Throwable ignored) { - // android.os.DeadObjectException - gattServer = null; - } - } - } - - private boolean requireBonding = false; - - /** - * Set if the Bluetooth LE device need `Pairing` - * - * @param needsPairing if true, request paring with the connecting device - */ - public void setRequestPairing(boolean needsPairing) { - this.requireBonding = needsPairing; } /** @@ -262,6 +252,21 @@ public void disconnectDevice(@NonNull MidiOutputDevice midiOutputDevice) { disconnectByDeviceAddress(midiOutputDevice.getDeviceAddress()); } + /** + * callback for disconnecting a bluetooth device + */ + private final BluetoothGattCallback disconnectCallback = new BluetoothGattCallback() { + @Override + public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) { + super.onConnectionStateChange(gatt, status, newState); + Log.d(Constants.TAG, "onConnectionStateChange status: " + status + ", newState: " + newState); + // disconnect the device + if (gatt != null) { + gatt.disconnect(); + } + } + }; + /** * Disconnects the device by its address * @@ -272,33 +277,7 @@ private void disconnectByDeviceAddress(@NonNull String deviceAddress) { BluetoothDevice bluetoothDevice = bluetoothDevicesMap.get(deviceAddress); if (bluetoothDevice != null) { gattServer.cancelConnection(bluetoothDevice); - } - - bluetoothDevicesMap.remove(deviceAddress); - } - - synchronized (midiInputDevicesMap) { - MidiInputDevice midiInputDevice = midiInputDevicesMap.get(deviceAddress); - if (midiInputDevice != null) { - midiInputDevicesMap.remove(deviceAddress); - - ((InternalMidiInputDevice) midiInputDevice).stop(); - midiInputDevice.setOnMidiInputEventListener(null); - - if (midiDeviceDetachedListener != null) { - midiDeviceDetachedListener.onMidiInputDeviceDetached(midiInputDevice); - } - } - } - - synchronized (midiOutputDevicesMap) { - MidiOutputDevice midiOutputDevice = midiOutputDevicesMap.get(deviceAddress); - if (midiOutputDevice != null) { - midiOutputDevicesMap.remove(deviceAddress); - - if (midiDeviceDetachedListener != null) { - midiDeviceDetachedListener.onMidiOutputDeviceDetached(midiOutputDevice); - } + bluetoothDevice.connectGatt(context, true, disconnectCallback); } } } @@ -311,15 +290,24 @@ public void terminate() { synchronized (bluetoothDevicesMap) { for (BluetoothDevice bluetoothDevice : bluetoothDevicesMap.values()) { - if (gattServer != null) { - gattServer.cancelConnection(bluetoothDevice); - } + gattServer.cancelConnection(bluetoothDevice); + bluetoothDevice.connectGatt(context, true, disconnectCallback); } bluetoothDevicesMap.clear(); } if (gattServer != null) { - gattServer.close(); + try { + gattServer.clearServices(); + gattServiceInitialized = false; + } catch (Throwable ignored) { + // android.os.DeadObjectException + } + try { + gattServer.close(); + } catch (Throwable ignored) { + // android.os.DeadObjectException + } gattServer = null; } @@ -347,37 +335,7 @@ public void onConnectionStateChange(BluetoothDevice device, int status, int newS switch (newState) { case BluetoothProfile.STATE_CONNECTED: - // check bond status - if (requireBonding && device.getBondState() == BluetoothDevice.BOND_NONE) { - // create bond - device.createBond(); - device.setPairingConfirmation(true); - - IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_BOND_STATE_CHANGED); - context.registerReceiver(new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - final String action = intent.getAction(); - - if (BluetoothDevice.ACTION_BOND_STATE_CHANGED.equals(action)) { - final int state = intent.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE, BluetoothDevice.ERROR); - - if (state == BluetoothDevice.BOND_BONDED) { - BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); - - // successfully bonded - context.unregisterReceiver(this); - - // connecting to the device - connectMidiDevice(device); - } - } - } - }, filter); - } else { - // connecting to the device - connectMidiDevice(device); - } + connectMidiDevice(device); break; case BluetoothProfile.STATE_DISCONNECTED: @@ -461,8 +419,32 @@ public void onCharacteristicWriteRequest(BluetoothDevice device, int requestId, 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); + byte[] descriptorValue = descriptor.getValue(); + try { + System.arraycopy(value, 0, descriptorValue, offset, value.length); + descriptor.setValue(descriptorValue); + } catch (IndexOutOfBoundsException ignored) { + } + gattServer.sendResponse(device, requestId, BluetoothGatt.GATT_SUCCESS, 0, new byte[] {}); } + + @Override + public void onDescriptorReadRequest(BluetoothDevice device, int requestId, int offset, BluetoothGattDescriptor descriptor) { + super.onDescriptorReadRequest(device, requestId, offset, descriptor); + + if (offset == 0) { + gattServer.sendResponse(device, requestId, BluetoothGatt.GATT_SUCCESS, 0, descriptor.getValue()); + } else { + final byte[] value = descriptor.getValue(); + byte[] result = new byte[value.length - offset]; + try { + System.arraycopy(value, offset, result, 0, result.length); + } catch (IndexOutOfBoundsException ignored) { + } + gattServer.sendResponse(device, requestId, BluetoothGatt.GATT_SUCCESS, offset, result); + } + } }; /** @@ -501,8 +483,7 @@ private void connectMidiDevice(@NonNull BluetoothDevice device) { */ @NonNull public Set getMidiInputDevices() { - Set result = new HashSet<>(); - result.addAll(midiInputDevicesMap.values()); + Set result = new HashSet<>(midiInputDevicesMap.values()); return Collections.unmodifiableSet(result); } @@ -513,8 +494,7 @@ public Set getMidiInputDevices() { */ @NonNull public Set getMidiOutputDevices() { - Set result = new HashSet<>(); - result.addAll(midiOutputDevicesMap.values()); + Set result = new HashSet<>(midiOutputDevicesMap.values()); return Collections.unmodifiableSet(result); } diff --git a/library/src/main/java/jp/kshoji/blemidi/service/AbstractBleMidiService.java b/BLE-MIDI-library/src/main/java/jp/kshoji/blemidi/service/AbstractBleMidiService.java similarity index 100% rename from library/src/main/java/jp/kshoji/blemidi/service/AbstractBleMidiService.java rename to BLE-MIDI-library/src/main/java/jp/kshoji/blemidi/service/AbstractBleMidiService.java diff --git a/library/src/main/java/jp/kshoji/blemidi/service/BleMidiCentralService.java b/BLE-MIDI-library/src/main/java/jp/kshoji/blemidi/service/BleMidiCentralService.java similarity index 100% rename from library/src/main/java/jp/kshoji/blemidi/service/BleMidiCentralService.java rename to BLE-MIDI-library/src/main/java/jp/kshoji/blemidi/service/BleMidiCentralService.java diff --git a/library/src/main/java/jp/kshoji/blemidi/service/BleMidiPeripheralService.java b/BLE-MIDI-library/src/main/java/jp/kshoji/blemidi/service/BleMidiPeripheralService.java similarity index 100% rename from library/src/main/java/jp/kshoji/blemidi/service/BleMidiPeripheralService.java rename to BLE-MIDI-library/src/main/java/jp/kshoji/blemidi/service/BleMidiPeripheralService.java diff --git a/library/src/main/java/jp/kshoji/blemidi/util/BleMidiDeviceUtils.java b/BLE-MIDI-library/src/main/java/jp/kshoji/blemidi/util/BleMidiDeviceUtils.java similarity index 100% rename from library/src/main/java/jp/kshoji/blemidi/util/BleMidiDeviceUtils.java rename to BLE-MIDI-library/src/main/java/jp/kshoji/blemidi/util/BleMidiDeviceUtils.java diff --git a/library/src/main/java/jp/kshoji/blemidi/util/BleMidiParser.java b/BLE-MIDI-library/src/main/java/jp/kshoji/blemidi/util/BleMidiParser.java similarity index 97% rename from library/src/main/java/jp/kshoji/blemidi/util/BleMidiParser.java rename to BLE-MIDI-library/src/main/java/jp/kshoji/blemidi/util/BleMidiParser.java index ef594e9..a10c5c0 100644 --- a/library/src/main/java/jp/kshoji/blemidi/util/BleMidiParser.java +++ b/BLE-MIDI-library/src/main/java/jp/kshoji/blemidi/util/BleMidiParser.java @@ -61,7 +61,7 @@ public final class BleMidiParser { // for Timestamp private static final int MAX_TIMESTAMP = 8192; - private static final int BUFFER_LENGTH_MILLIS = 30; + private static final int BUFFER_LENGTH_MILLIS = 50; private int timestamp = 0; private int lastTimestamp; private long lastTimestampRecorded = 0; @@ -164,12 +164,17 @@ private long calculateEventFireTime(final int timestamp) { return currentTimeMillis; } - int adjustedTimestamp = timestamp; - if (timestamp + MAX_TIMESTAMP / 2 < lastTimestamp) { - adjustedTimestamp += MAX_TIMESTAMP; + final long elapsedRealtime = currentTimeMillis - lastTimestampRecorded; + // realTimestampPeriod: how many times MAX_TIMESTAMP passed + long realTimestampPeriod = (lastTimestamp + elapsedRealtime) / MAX_TIMESTAMP; + if (realTimestampPeriod > 0 && timestamp > 7000) { + realTimestampPeriod--; } - - final long result = BUFFER_LENGTH_MILLIS + adjustedTimestamp - lastTimestamp + lastTimestampRecorded; + final long lastTimestampStarted = lastTimestampRecorded - lastTimestamp; + // result: time to wait + final long result = BUFFER_LENGTH_MILLIS // buffer + + lastTimestampStarted + realTimestampPeriod * MAX_TIMESTAMP + timestamp // time to fire event + - currentTimeMillis; // current time lastTimestamp = timestamp; lastTimestampRecorded = currentTimeMillis; @@ -764,7 +769,7 @@ public void run() { * * @param data incoming data */ - public void parse(@NonNull byte[] data) { + public synchronized void parse(@NonNull byte[] data) { if (data.length > 1) { int header = data[0] & 0xff; for (int i = 1; i < data.length; i++) { diff --git a/library/src/main/java/jp/kshoji/blemidi/util/BleUtils.java b/BLE-MIDI-library/src/main/java/jp/kshoji/blemidi/util/BleUtils.java similarity index 83% rename from library/src/main/java/jp/kshoji/blemidi/util/BleUtils.java rename to BLE-MIDI-library/src/main/java/jp/kshoji/blemidi/util/BleUtils.java index 503f3b5..125a8e0 100644 --- a/library/src/main/java/jp/kshoji/blemidi/util/BleUtils.java +++ b/BLE-MIDI-library/src/main/java/jp/kshoji/blemidi/util/BleUtils.java @@ -23,13 +23,13 @@ public class BleUtils { * @param context the context * @return true if supported */ - public static boolean isBleSupported(@NonNull Context context) { + public static boolean isBleSupported(@NonNull final Context context) { try { if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE) == false) { return false; } - BluetoothManager bluetoothManager = (BluetoothManager) context.getSystemService(Context.BLUETOOTH_SERVICE); + final BluetoothManager bluetoothManager = (BluetoothManager) context.getSystemService(Context.BLUETOOTH_SERVICE); final BluetoothAdapter bluetoothAdapter; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) { @@ -41,7 +41,7 @@ public static boolean isBleSupported(@NonNull Context context) { if (bluetoothAdapter != null) { return true; } - } catch (Throwable t) { + } catch (final Throwable ignored) { // ignore exception } return false; @@ -54,7 +54,7 @@ public static boolean isBleSupported(@NonNull Context context) { * @return true if supported */ @SuppressLint("NewApi") - public static boolean isBlePeripheralSupported(@NonNull Context context) { + public static boolean isBlePeripheralSupported(@NonNull final Context context) { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) { return false; } @@ -74,8 +74,8 @@ public static boolean isBlePeripheralSupported(@NonNull Context context) { * @param context the context * @return true if bluetooth enabled */ - public static boolean isBluetoothEnabled(@NonNull Context context) { - BluetoothManager bluetoothManager = (BluetoothManager) context.getSystemService(Context.BLUETOOTH_SERVICE); + public static boolean isBluetoothEnabled(@NonNull final Context context) { + final BluetoothManager bluetoothManager = (BluetoothManager) context.getSystemService(Context.BLUETOOTH_SERVICE); if (bluetoothManager == null) { return false; @@ -106,7 +106,7 @@ public static boolean isBluetoothEnabled(@NonNull Context context) { * * @param activity the activity */ - public static void enableBluetooth(@NonNull Activity activity) { + public static void enableBluetooth(@NonNull final Activity activity) { activity.startActivityForResult(new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE), REQUEST_CODE_BLUETOOTH_ENABLE); } } diff --git a/library/src/main/java/jp/kshoji/blemidi/util/BleUuidUtils.java b/BLE-MIDI-library/src/main/java/jp/kshoji/blemidi/util/BleUuidUtils.java similarity index 100% rename from library/src/main/java/jp/kshoji/blemidi/util/BleUuidUtils.java rename to BLE-MIDI-library/src/main/java/jp/kshoji/blemidi/util/BleUuidUtils.java diff --git a/library/src/main/java/jp/kshoji/blemidi/util/Constants.java b/BLE-MIDI-library/src/main/java/jp/kshoji/blemidi/util/Constants.java similarity index 100% rename from library/src/main/java/jp/kshoji/blemidi/util/Constants.java rename to BLE-MIDI-library/src/main/java/jp/kshoji/blemidi/util/Constants.java diff --git a/library/src/main/java/jp/kshoji/blemidi/util/ReusableByteArrayOutputStream.java b/BLE-MIDI-library/src/main/java/jp/kshoji/blemidi/util/ReusableByteArrayOutputStream.java similarity index 100% rename from library/src/main/java/jp/kshoji/blemidi/util/ReusableByteArrayOutputStream.java rename to BLE-MIDI-library/src/main/java/jp/kshoji/blemidi/util/ReusableByteArrayOutputStream.java diff --git a/library/src/main/java/jp/kshoji/javax/sound/midi/BleMidiSystem.java b/BLE-MIDI-library/src/main/java/jp/kshoji/javax/sound/midi/BleMidiSystem.java similarity index 56% rename from library/src/main/java/jp/kshoji/javax/sound/midi/BleMidiSystem.java rename to BLE-MIDI-library/src/main/java/jp/kshoji/javax/sound/midi/BleMidiSystem.java index 6ed552e..98bcb7c 100644 --- a/library/src/main/java/jp/kshoji/javax/sound/midi/BleMidiSystem.java +++ b/BLE-MIDI-library/src/main/java/jp/kshoji/javax/sound/midi/BleMidiSystem.java @@ -14,6 +14,7 @@ import jp.kshoji.blemidi.peripheral.BleMidiPeripheralProvider; import jp.kshoji.blemidi.util.BleUtils; import jp.kshoji.javax.sound.midi.ble.BleMidiDevice; +import jp.kshoji.javax.sound.midi.ble.BleMidiSynthesizer; /** * {@link jp.kshoji.javax.sound.midi.MidiSystem} initializer for BLE MIDI @@ -24,7 +25,8 @@ public final class BleMidiSystem implements OnMidiDeviceAttachedListener, OnMidi private static BleMidiPeripheralProvider peripheralProvider; private static BleMidiCentralProvider centralProvider; - private static final Map midiDeviceMap = new HashMap<>(); + private final Map midiDeviceMap = new HashMap<>(); + private final Map midiSynthesizerMap = new HashMap<>(); private final Context context; /** @@ -32,7 +34,7 @@ public final class BleMidiSystem implements OnMidiDeviceAttachedListener, OnMidi * * @param context the context */ - public BleMidiSystem(@NonNull Context context) { + public BleMidiSystem(@NonNull final Context context) { this.context = context.getApplicationContext(); } @@ -70,7 +72,7 @@ public void terminate() { } synchronized (midiDeviceMap) { - for (BleMidiDevice bleMidiDevice : midiDeviceMap.values()) { + for (final BleMidiDevice bleMidiDevice : midiDeviceMap.values()) { bleMidiDevice.close(); } @@ -115,64 +117,111 @@ public void stopAdvertising() { } @Override - public void onMidiInputDeviceAttached(@NonNull MidiInputDevice midiInputDevice) { + public void onMidiInputDeviceAttached(@NonNull final MidiInputDevice midiInputDevice) { + final BleMidiDevice addedDevice; synchronized (midiDeviceMap) { - BleMidiDevice existingDevice = midiDeviceMap.get(midiInputDevice.getDeviceAddress()); + final BleMidiDevice existingDevice = midiDeviceMap.get(midiInputDevice.getDeviceAddress()); if (existingDevice != null) { + addedDevice = existingDevice; existingDevice.setMidiInputDevice(midiInputDevice); MidiSystem.addMidiDevice(existingDevice); } else { - BleMidiDevice midiDevice = new BleMidiDevice(midiInputDevice, null); + final BleMidiDevice midiDevice = new BleMidiDevice(midiInputDevice, null); + addedDevice = midiDevice; midiDeviceMap.put(midiInputDevice.getDeviceAddress(), midiDevice); MidiSystem.addMidiDevice(midiDevice); } } + + synchronized (midiSynthesizerMap) { + final BleMidiSynthesizer existingSynthesizer = midiSynthesizerMap.get(midiInputDevice.getDeviceAddress()); + if (existingSynthesizer == null) { + final BleMidiSynthesizer synthesizer = new BleMidiSynthesizer(addedDevice); + MidiSystem.addSynthesizer(synthesizer); + midiSynthesizerMap.put(midiInputDevice.getDeviceAddress(), synthesizer); + } + } } @Override - public void onMidiOutputDeviceAttached(@NonNull MidiOutputDevice midiOutputDevice) { + public void onMidiOutputDeviceAttached(@NonNull final MidiOutputDevice midiOutputDevice) { + final BleMidiDevice addedDevice; synchronized (midiDeviceMap) { - BleMidiDevice existingDevice = midiDeviceMap.get(midiOutputDevice.getDeviceAddress()); - if (existingDevice != null) { + final BleMidiDevice existingDevice = midiDeviceMap.get(midiOutputDevice.getDeviceAddress()); + if (existingDevice == null) { + final BleMidiDevice midiDevice = new BleMidiDevice(null, midiOutputDevice); + addedDevice = midiDevice; + midiDeviceMap.put(midiOutputDevice.getDeviceAddress(), midiDevice); + MidiSystem.addMidiDevice(midiDevice); + } else { + addedDevice = existingDevice; existingDevice.setMidiOutputDevice(midiOutputDevice); MidiSystem.addMidiDevice(existingDevice); + } + } + + synchronized (midiSynthesizerMap) { + final BleMidiSynthesizer existingSynthesizer = midiSynthesizerMap.get(midiOutputDevice.getDeviceAddress()); + if (existingSynthesizer == null) { + final BleMidiSynthesizer synthesizer = new BleMidiSynthesizer(addedDevice); + midiSynthesizerMap.put(midiOutputDevice.getDeviceAddress(), synthesizer); + MidiSystem.addSynthesizer(synthesizer); } else { - BleMidiDevice midiDevice = new BleMidiDevice(null, midiOutputDevice); - midiDeviceMap.put(midiOutputDevice.getDeviceAddress(), midiDevice); - MidiSystem.addMidiDevice(midiDevice); + try { + existingSynthesizer.setReceiver(addedDevice.getReceiver()); + } catch (final MidiUnavailableException ignored) { + } } } } @Override - public void onMidiInputDeviceDetached(@NonNull MidiInputDevice midiInputDevice) { + public void onMidiInputDeviceDetached(@NonNull final MidiInputDevice midiInputDevice) { + String removedDeviceAddress = null; synchronized (midiDeviceMap) { - BleMidiDevice existingDevice = midiDeviceMap.get(midiInputDevice.getDeviceAddress()); + final BleMidiDevice existingDevice = midiDeviceMap.get(midiInputDevice.getDeviceAddress()); if (existingDevice != null) { existingDevice.setMidiInputDevice(null); if (existingDevice.getMidiOutputDevice() == null) { // both of devices are disconnected + removedDeviceAddress = midiInputDevice.getDeviceAddress(); midiDeviceMap.remove(midiInputDevice.getDeviceAddress()); MidiSystem.removeMidiDevice(existingDevice); } } } + + if (removedDeviceAddress != null) { + synchronized (midiSynthesizerMap) { + MidiSystem.removeSynthesizer(midiSynthesizerMap.get(removedDeviceAddress)); + midiSynthesizerMap.remove(removedDeviceAddress); + } + } } @Override - public void onMidiOutputDeviceDetached(@NonNull MidiOutputDevice midiOutputDevice) { + public void onMidiOutputDeviceDetached(@NonNull final MidiOutputDevice midiOutputDevice) { + String removedDeviceAddress = null; synchronized (midiDeviceMap) { - BleMidiDevice existingDevice = midiDeviceMap.get(midiOutputDevice.getDeviceAddress()); + final BleMidiDevice existingDevice = midiDeviceMap.get(midiOutputDevice.getDeviceAddress()); if (existingDevice != null) { existingDevice.setMidiOutputDevice(null); if (existingDevice.getMidiInputDevice() == null) { // both of devices are disconnected + removedDeviceAddress = midiOutputDevice.getDeviceAddress(); midiDeviceMap.remove(midiOutputDevice.getDeviceAddress()); MidiSystem.removeMidiDevice(existingDevice); } } } + + if (removedDeviceAddress != null) { + synchronized (midiSynthesizerMap) { + MidiSystem.removeSynthesizer(midiSynthesizerMap.get(removedDeviceAddress)); + midiSynthesizerMap.remove(removedDeviceAddress); + } + } } } diff --git a/library/src/main/java/jp/kshoji/javax/sound/midi/ble/BleMidiDevice.java b/BLE-MIDI-library/src/main/java/jp/kshoji/javax/sound/midi/ble/BleMidiDevice.java similarity index 86% rename from library/src/main/java/jp/kshoji/javax/sound/midi/ble/BleMidiDevice.java rename to BLE-MIDI-library/src/main/java/jp/kshoji/javax/sound/midi/ble/BleMidiDevice.java index a2d28d7..5879806 100644 --- a/library/src/main/java/jp/kshoji/javax/sound/midi/ble/BleMidiDevice.java +++ b/BLE-MIDI-library/src/main/java/jp/kshoji/javax/sound/midi/ble/BleMidiDevice.java @@ -20,7 +20,9 @@ * @author K.Shoji */ public final class BleMidiDevice implements MidiDevice { + @Nullable private BleMidiReceiver receiver; + @Nullable private BleMidiTransmitter transmitter; private boolean isOpened; @@ -34,7 +36,7 @@ public final class BleMidiDevice implements MidiDevice { * @param midiInputDevice the input device * @param midiOutputDevice the output device */ - public BleMidiDevice(@Nullable MidiInputDevice midiInputDevice, @Nullable MidiOutputDevice midiOutputDevice) { + public BleMidiDevice(@Nullable final MidiInputDevice midiInputDevice, @Nullable final MidiOutputDevice midiOutputDevice) { this.midiInputDevice = midiInputDevice; this.midiOutputDevice = midiOutputDevice; @@ -124,37 +126,45 @@ public int getMaxTransmitters() { return transmitter == null ? 0 : 1; } + @NonNull @Override public Receiver getReceiver() throws MidiUnavailableException { + if (receiver == null) { + throw new MidiUnavailableException("Receiver not found"); + } return receiver; } @NonNull @Override public List getReceivers() { - ArrayList receivers = new ArrayList<>(); + final List receivers = new ArrayList<>(); if (receiver != null) { receivers.add(receiver); } return Collections.unmodifiableList(receivers); } + @NonNull @Override public Transmitter getTransmitter() throws MidiUnavailableException { + if (transmitter == null) { + throw new MidiUnavailableException("Tranmitter not found"); + } return transmitter; } @NonNull @Override public List getTransmitters() { - ArrayList transmitters = new ArrayList<>(); + final List transmitters = new ArrayList<>(); if (transmitter != null) { transmitters.add(transmitter); } return Collections.unmodifiableList(transmitters); } - public void setMidiInputDevice(@Nullable MidiInputDevice midiInputDevice) { + public void setMidiInputDevice(@Nullable final MidiInputDevice midiInputDevice) { this.midiInputDevice = midiInputDevice; if (transmitter != null) { transmitter.close(); @@ -171,7 +181,7 @@ public MidiInputDevice getMidiInputDevice() { return midiInputDevice; } - public void setMidiOutputDevice(@Nullable MidiOutputDevice midiOutputDevice) { + public void setMidiOutputDevice(@Nullable final MidiOutputDevice midiOutputDevice) { this.midiOutputDevice = midiOutputDevice; if (receiver != null) { receiver.close(); diff --git a/library/src/main/java/jp/kshoji/javax/sound/midi/ble/BleMidiReceiver.java b/BLE-MIDI-library/src/main/java/jp/kshoji/javax/sound/midi/ble/BleMidiReceiver.java similarity index 100% rename from library/src/main/java/jp/kshoji/javax/sound/midi/ble/BleMidiReceiver.java rename to BLE-MIDI-library/src/main/java/jp/kshoji/javax/sound/midi/ble/BleMidiReceiver.java diff --git a/BLE-MIDI-library/src/main/java/jp/kshoji/javax/sound/midi/ble/BleMidiSynthesizer.java b/BLE-MIDI-library/src/main/java/jp/kshoji/javax/sound/midi/ble/BleMidiSynthesizer.java new file mode 100644 index 0000000..ea8723b --- /dev/null +++ b/BLE-MIDI-library/src/main/java/jp/kshoji/javax/sound/midi/ble/BleMidiSynthesizer.java @@ -0,0 +1,207 @@ +package jp.kshoji.javax.sound.midi.ble; + +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; + +import java.util.List; + +import jp.kshoji.javax.sound.midi.Instrument; +import jp.kshoji.javax.sound.midi.MidiChannel; +import jp.kshoji.javax.sound.midi.MidiUnavailableException; +import jp.kshoji.javax.sound.midi.Patch; +import jp.kshoji.javax.sound.midi.Receiver; +import jp.kshoji.javax.sound.midi.Soundbank; +import jp.kshoji.javax.sound.midi.Synthesizer; +import jp.kshoji.javax.sound.midi.Transmitter; +import jp.kshoji.javax.sound.midi.VoiceStatus; +import jp.kshoji.javax.sound.midi.impl.MidiChannelImpl; + +/** + * {@link jp.kshoji.javax.sound.midi.Synthesizer} implementation + * + * @author K.Shoji + */ +public class BleMidiSynthesizer implements Synthesizer { + private final BleMidiDevice bleMidiDevice; + private MidiChannel[] channels; + private VoiceStatus[] voiceStatuses; + + /** + * Constructor + * + * @param bleMidiDevice the device + */ + public BleMidiSynthesizer(final BleMidiDevice bleMidiDevice) { + this.bleMidiDevice = bleMidiDevice; + + Receiver receiver = null; + try { + receiver = this.bleMidiDevice.getReceiver(); + } catch (final MidiUnavailableException ignored) { + } + + if (receiver == null) { + // empty + channels = new MidiChannel[0]; + voiceStatuses = new VoiceStatus[0]; + } else { + // 16 channels + voiceStatuses = new VoiceStatus[16]; + channels = new MidiChannel[16]; + for (int channel = 0; channel < 16; channel++) { + voiceStatuses[channel] = new VoiceStatus(); + channels[channel] = new MidiChannelImpl(channel, receiver, voiceStatuses[channel]); + } + } + } + + @NonNull + @Override + public MidiChannel[] getChannels() { + return channels; + } + + @Override + public long getLatency() { + return 0; + } + + @Override + public int getMaxPolyphony() { + return 127; + } + + @NonNull + @Override + public VoiceStatus[] getVoiceStatus() { + return voiceStatuses; + } + + @Nullable + @Override + public Soundbank getDefaultSoundbank() { + return null; + } + + @Override + public boolean isSoundbankSupported(@NonNull final Soundbank soundbank) { + return false; + } + + @NonNull + @Override + public Instrument[] getAvailableInstruments() { + return new Instrument[0]; + } + + @NonNull + @Override + public Instrument[] getLoadedInstruments() { + return new Instrument[0]; + } + + @Override + public boolean remapInstrument(@NonNull final Instrument from, @NonNull final Instrument to) { + return false; + } + + @Override + public boolean loadAllInstruments(@NonNull final Soundbank soundbank) { + return false; + } + + @Override + public void unloadAllInstruments(@NonNull final Soundbank soundbank) { + + } + + @Override + public boolean loadInstrument(@NonNull final Instrument instrument) { + return false; + } + + @Override + public void unloadInstrument(@NonNull final Instrument instrument) { + + } + + @Override + public boolean loadInstruments(@NonNull final Soundbank soundbank, @NonNull final Patch[] patchList) { + return false; + } + + @Override + public void unloadInstruments(@NonNull final Soundbank soundbank, @NonNull final Patch[] patchList) { + + } + + @NonNull + @Override + public Info getDeviceInfo() { + return bleMidiDevice.getDeviceInfo(); + } + + @Override + public void open() throws MidiUnavailableException { + bleMidiDevice.open(); + } + + @Override + public void close() { + bleMidiDevice.close(); + } + + @Override + public boolean isOpen() { + return bleMidiDevice.isOpen(); + } + + @Override + public long getMicrosecondPosition() { + return -1; + } + + @Override + public int getMaxReceivers() { + return bleMidiDevice.getMaxReceivers(); + } + + @Override + public int getMaxTransmitters() { + return bleMidiDevice.getMaxTransmitters(); + } + + @NonNull + @Override + public Receiver getReceiver() throws MidiUnavailableException { + return bleMidiDevice.getReceiver(); + } + + @NonNull + @Override + public List getReceivers() { + return bleMidiDevice.getReceivers(); + } + + @NonNull + @Override + public Transmitter getTransmitter() throws MidiUnavailableException { + return bleMidiDevice.getTransmitter(); + } + + @NonNull + @Override + public List getTransmitters() { + return bleMidiDevice.getTransmitters(); + } + + public void setReceiver(final Receiver receiver) { + // 16 channels + voiceStatuses = new VoiceStatus[16]; + channels = new MidiChannel[16]; + for (int channel = 0; channel < 16; channel++) { + voiceStatuses[channel] = new VoiceStatus(); + channels[channel] = new MidiChannelImpl(channel, receiver, voiceStatuses[channel]); + } + } +} diff --git a/library/src/main/java/jp/kshoji/javax/sound/midi/ble/BleMidiTransmitter.java b/BLE-MIDI-library/src/main/java/jp/kshoji/javax/sound/midi/ble/BleMidiTransmitter.java similarity index 100% rename from library/src/main/java/jp/kshoji/javax/sound/midi/ble/BleMidiTransmitter.java rename to BLE-MIDI-library/src/main/java/jp/kshoji/javax/sound/midi/ble/BleMidiTransmitter.java diff --git a/BLE-MIDI-library/src/main/java/jp/kshoji/unity/midi/BleMidiUnityPlugin.java b/BLE-MIDI-library/src/main/java/jp/kshoji/unity/midi/BleMidiUnityPlugin.java new file mode 100644 index 0000000..69882f3 --- /dev/null +++ b/BLE-MIDI-library/src/main/java/jp/kshoji/unity/midi/BleMidiUnityPlugin.java @@ -0,0 +1,452 @@ +package jp.kshoji.unity.midi; + +import java.util.HashMap; +import java.util.Locale; +import android.content.Context; +import android.os.Build; +import android.support.annotation.NonNull; +import android.text.TextUtils; + +import com.unity3d.player.UnityPlayer; +import jp.kshoji.blemidi.central.BleMidiCentralProvider; +import jp.kshoji.blemidi.device.MidiInputDevice; +import jp.kshoji.blemidi.device.MidiOutputDevice; +import jp.kshoji.blemidi.listener.OnMidiDeviceAttachedListener; +import jp.kshoji.blemidi.listener.OnMidiDeviceDetachedListener; +import jp.kshoji.blemidi.listener.OnMidiInputEventListener; + +/** + * BLE MIDI Plugin for Unity + * @author K.Shoji + */ +public class BleMidiUnityPlugin { + private static final String GAME_OBJECT_NAME = "MidiManager"; + + private final OnMidiInputEventListener midiInputEventListener = new OnMidiInputEventListener() { + + private String serializeMidiMessage(String deviceAddress, int[] data) { + StringBuilder sb = new StringBuilder(deviceAddress); + for (int i = 0; i < data.length; i++) { + sb.append(","); + sb.append(String.format(Locale.ROOT, "%d", data[i])); + if (i == data.length - 1) { + return sb.toString(); + } + } + return sb.toString(); + } + + private String serializeMidiMessage(String deviceAddress, int cable, byte[] data) { + StringBuilder sb = new StringBuilder(deviceAddress); + sb.append(","); + sb.append(String.format(Locale.ROOT, "%d", cable)); + for (int i = 0; i < data.length; i++) { + sb.append(","); + sb.append(String.format(Locale.ROOT, "%d", data[i] & 0xff)); + if (i == data.length - 1) { + return sb.toString(); + } + } + return sb.toString(); + } + + private String serializeMidiMessage(String deviceAddress, int[] data1, byte[] data2) { + StringBuilder sb = new StringBuilder(deviceAddress); + for (int i = 0; i < data1.length; i++) { + sb.append(","); + sb.append(String.format(Locale.ROOT, "%d", data1[i])); + } + for (int i = 0; i < data2.length; i++) { + sb.append(","); + sb.append(String.format(Locale.ROOT, "%d", data2[i] & 0xff)); + } + return sb.toString(); + } + + private String serializeMidiMessage(String deviceAddress, int[] data1, long data2) { + StringBuilder sb = new StringBuilder(deviceAddress); + for (int i = 0; i < data1.length; i++) { + sb.append(","); + sb.append(String.format(Locale.ROOT, "%d", data1[i])); + } + sb.append(","); + sb.append(String.format(Locale.ROOT, "%d", data2)); + return sb.toString(); + } + + private static final int cable = 0; + + @Override + public void onMidiNoteOff(final MidiInputDevice sender, int channel, int note, int velocity) { + UnityPlayer.UnitySendMessage(GAME_OBJECT_NAME, "OnMidiNoteOff", serializeMidiMessage(sender.getDeviceAddress(), new int[] {cable, channel, note, velocity})); + } + + @Override + public void onMidiNoteOn(final MidiInputDevice sender, int channel, int note, int velocity) { + UnityPlayer.UnitySendMessage(GAME_OBJECT_NAME, "OnMidiNoteOn", serializeMidiMessage(sender.getDeviceAddress(), new int[] {cable, channel, note, velocity})); + } + + @Override + public void onMidiPolyphonicAftertouch(final MidiInputDevice sender, int channel, int note, int pressure) { + UnityPlayer.UnitySendMessage(GAME_OBJECT_NAME, "OnMidiPolyphonicAftertouch", serializeMidiMessage(sender.getDeviceAddress(), new int[] {cable, channel, note, pressure})); + } + + @Override + public void onMidiControlChange(final MidiInputDevice sender, int channel, int function, int value) { + UnityPlayer.UnitySendMessage(GAME_OBJECT_NAME, "OnMidiControlChange", serializeMidiMessage(sender.getDeviceAddress(), new int[] {cable, channel, function, value})); + } + + @Override + public void onMidiProgramChange(final MidiInputDevice sender, int channel, int program) { + UnityPlayer.UnitySendMessage(GAME_OBJECT_NAME, "OnMidiProgramChange", serializeMidiMessage(sender.getDeviceAddress(), new int[] {cable, channel, program})); + } + + @Override + public void onMidiChannelAftertouch(final MidiInputDevice sender, int channel, int pressure) { + UnityPlayer.UnitySendMessage(GAME_OBJECT_NAME, "OnMidiChannelAftertouch", serializeMidiMessage(sender.getDeviceAddress(), new int[] {cable, channel, pressure})); + } + + @Override + public void onMidiPitchWheel(final MidiInputDevice sender, int channel, int amount) { + UnityPlayer.UnitySendMessage(GAME_OBJECT_NAME, "OnMidiPitchWheel", serializeMidiMessage(sender.getDeviceAddress(), new int[] {cable, channel, amount})); + } + + @Override + public void onMidiSystemExclusive(final MidiInputDevice sender, @NonNull final byte[] systemExclusive) { + UnityPlayer.UnitySendMessage(GAME_OBJECT_NAME, "OnMidiSystemExclusive", serializeMidiMessage(sender.getDeviceAddress(), cable, systemExclusive)); + } + + @Override + public void onMidiTimeCodeQuarterFrame(MidiInputDevice sender, int timing) { + UnityPlayer.UnitySendMessage(GAME_OBJECT_NAME, "OnMidiTimeCodeQuarterFrame", serializeMidiMessage(sender.getDeviceAddress(), new int[] {cable, timing})); + } + + @Override + public void onMidiSongSelect(MidiInputDevice sender, int song) { + UnityPlayer.UnitySendMessage(GAME_OBJECT_NAME, "OnMidiSongSelect", serializeMidiMessage(sender.getDeviceAddress(), new int[] {cable, song})); + } + + @Override + public void onMidiSongPositionPointer(MidiInputDevice sender, int position) { + UnityPlayer.UnitySendMessage(GAME_OBJECT_NAME, "OnMidiSongPositionPointer", serializeMidiMessage(sender.getDeviceAddress(), new int[] {cable, position})); + } + + @Override + public void onMidiTuneRequest(MidiInputDevice sender) { + UnityPlayer.UnitySendMessage(GAME_OBJECT_NAME, "OnMidiTuneRequest", serializeMidiMessage(sender.getDeviceAddress(), new int[] {cable})); + } + + @Override + public void onMidiTimingClock(MidiInputDevice sender) { + UnityPlayer.UnitySendMessage(GAME_OBJECT_NAME, "OnMidiTimingClock", serializeMidiMessage(sender.getDeviceAddress(), new int[] {cable})); + } + + @Override + public void onMidiStart(MidiInputDevice sender) { + UnityPlayer.UnitySendMessage(GAME_OBJECT_NAME, "OnMidiStart", serializeMidiMessage(sender.getDeviceAddress(), new int[] {cable})); + } + + @Override + public void onMidiContinue(MidiInputDevice sender) { + UnityPlayer.UnitySendMessage(GAME_OBJECT_NAME, "OnMidiContinue", serializeMidiMessage(sender.getDeviceAddress(), new int[] {cable})); + } + + @Override + public void onMidiStop(MidiInputDevice sender) { + UnityPlayer.UnitySendMessage(GAME_OBJECT_NAME, "OnMidiStop", serializeMidiMessage(sender.getDeviceAddress(), new int[] {cable})); + } + + @Override + public void onMidiActiveSensing(MidiInputDevice sender) { + UnityPlayer.UnitySendMessage(GAME_OBJECT_NAME, "OnMidiActiveSensing", serializeMidiMessage(sender.getDeviceAddress(), new int[] {cable})); + } + + @Override + public void onMidiReset(MidiInputDevice sender) { + UnityPlayer.UnitySendMessage(GAME_OBJECT_NAME, "OnMidiReset", serializeMidiMessage(sender.getDeviceAddress(), new int[] {cable})); + } + + @Override + public void onRPNMessage(@NonNull MidiInputDevice sender, int channel, int function, int value) { + + } + + @Override + public void onNRPNMessage(@NonNull MidiInputDevice sender, int channel, int function, int value) { + + } + }; + + public void sendMidiNoteOn(String serializedMidiMessage) { + String[] split = serializedMidiMessage.split(","); + if (split.length < 5) { + return; + } + MidiOutputDevice midiOutputDevice = midiOutputDeviceMap.get(split[0]); + if (midiOutputDevice != null) { + midiOutputDevice.sendMidiNoteOn(Integer.parseInt(split[2]), Integer.parseInt(split[3]), Integer.parseInt(split[4])); + } + } + + public void sendMidiNoteOff(String serializedMidiMessage) { + String[] split = serializedMidiMessage.split(","); + if (split.length < 5) { + return; + } + MidiOutputDevice midiOutputDevice = midiOutputDeviceMap.get(split[0]); + if (midiOutputDevice != null) { + midiOutputDevice.sendMidiNoteOff(Integer.parseInt(split[2]), Integer.parseInt(split[3]), Integer.parseInt(split[4])); + } + } + + public void sendMidiPolyphonicAftertouch(String serializedMidiMessage) { + String[] split = serializedMidiMessage.split(","); + if (split.length < 5) { + return; + } + MidiOutputDevice midiOutputDevice = midiOutputDeviceMap.get(split[0]); + if (midiOutputDevice != null) { + midiOutputDevice.sendMidiPolyphonicAftertouch(Integer.parseInt(split[2]), Integer.parseInt(split[3]), Integer.parseInt(split[4])); + } + } + + public void sendMidiControlChange(String serializedMidiMessage) { + String[] split = serializedMidiMessage.split(","); + if (split.length < 5) { + return; + } + MidiOutputDevice midiOutputDevice = midiOutputDeviceMap.get(split[0]); + if (midiOutputDevice != null) { + midiOutputDevice.sendMidiControlChange(Integer.parseInt(split[2]), Integer.parseInt(split[3]), Integer.parseInt(split[4])); + } + } + + public void sendMidiProgramChange(String serializedMidiMessage) { + String[] split = serializedMidiMessage.split(","); + if (split.length < 4) { + return; + } + MidiOutputDevice midiOutputDevice = midiOutputDeviceMap.get(split[0]); + if (midiOutputDevice != null) { + midiOutputDevice.sendMidiProgramChange(Integer.parseInt(split[2]), Integer.parseInt(split[3])); + } + } + + public void sendMidiChannelAftertouch(String serializedMidiMessage) { + String[] split = serializedMidiMessage.split(","); + if (split.length < 4) { + return; + } + MidiOutputDevice midiOutputDevice = midiOutputDeviceMap.get(split[0]); + if (midiOutputDevice != null) { + midiOutputDevice.sendMidiChannelAftertouch(Integer.parseInt(split[2]), Integer.parseInt(split[3])); + } + } + + public void sendMidiPitchWheel(String serializedMidiMessage) { + String[] split = serializedMidiMessage.split(","); + if (split.length < 4) { + return; + } + MidiOutputDevice midiOutputDevice = midiOutputDeviceMap.get(split[0]); + if (midiOutputDevice != null) { + midiOutputDevice.sendMidiPitchWheel(Integer.parseInt(split[2]), Integer.parseInt(split[3])); + } + } + + public void sendMidiSystemExclusive(String serializedMidiMessage) { + String[] split = serializedMidiMessage.split(","); + if (split.length < 1) { + return; + } + byte[] sysEx = new byte[split.length - 1]; + for (int i = 0; i < split.length - 1; i++) { + sysEx[i] = (byte) (Integer.parseInt(split[i + 1]) & 0xff); + } + MidiOutputDevice midiOutputDevice = midiOutputDeviceMap.get(split[0]); + if (midiOutputDevice != null) { + midiOutputDevice.sendMidiSystemExclusive(sysEx); + } + } + + public void sendMidiTimeCodeQuarterFrame(String serializedMidiMessage) { + String[] split = serializedMidiMessage.split(","); + if (split.length < 3) { + return; + } + MidiOutputDevice midiOutputDevice = midiOutputDeviceMap.get(split[0]); + if (midiOutputDevice != null) { + midiOutputDevice.sendMidiTimeCodeQuarterFrame(Integer.parseInt(split[2])); + } + } + + public void sendMidiSongSelect(String serializedMidiMessage) { + String[] split = serializedMidiMessage.split(","); + if (split.length < 3) { + return; + } + MidiOutputDevice midiOutputDevice = midiOutputDeviceMap.get(split[0]); + if (midiOutputDevice != null) { + midiOutputDevice.sendMidiSongSelect(Integer.parseInt(split[2])); + } + } + + public void sendMidiSongPositionPointer(String serializedMidiMessage) { + String[] split = serializedMidiMessage.split(","); + if (split.length < 3) { + return; + } + MidiOutputDevice midiOutputDevice = midiOutputDeviceMap.get(split[0]); + if (midiOutputDevice != null) { + midiOutputDevice.sendMidiSongPositionPointer(Integer.parseInt(split[2])); + } + } + + public void sendMidiTuneRequest(String serializedMidiMessage) { + String[] split = serializedMidiMessage.split(","); + if (split.length < 1) { + return; + } + MidiOutputDevice midiOutputDevice = midiOutputDeviceMap.get(split[0]); + if (midiOutputDevice != null) { + midiOutputDevice.sendMidiTuneRequest(); + } + } + + public void sendMidiTimingClock(String serializedMidiMessage) { + String[] split = serializedMidiMessage.split(","); + if (split.length < 1) { + return; + } + MidiOutputDevice midiOutputDevice = midiOutputDeviceMap.get(split[0]); + if (midiOutputDevice != null) { + midiOutputDevice.sendMidiTimingClock(); + } + } + + public void sendMidiStart(String serializedMidiMessage) { + String[] split = serializedMidiMessage.split(","); + if (split.length < 1) { + return; + } + MidiOutputDevice midiOutputDevice = midiOutputDeviceMap.get(split[0]); + if (midiOutputDevice != null) { + midiOutputDevice.sendMidiStart(); + } + } + + public void sendMidiContinue(String serializedMidiMessage) { + String[] split = serializedMidiMessage.split(","); + if (split.length < 1) { + return; + } + MidiOutputDevice midiOutputDevice = midiOutputDeviceMap.get(split[0]); + if (midiOutputDevice != null) { + midiOutputDevice.sendMidiContinue(); + } + } + + public void sendMidiStop(String serializedMidiMessage) { + String[] split = serializedMidiMessage.split(","); + if (split.length < 2) { + return; + } + MidiOutputDevice midiOutputDevice = midiOutputDeviceMap.get(split[0]); + if (midiOutputDevice != null) { + midiOutputDevice.sendMidiStop(); + } + } + + public void sendMidiActiveSensing(String serializedMidiMessage) { + String[] split = serializedMidiMessage.split(","); + if (split.length < 1) { + return; + } + MidiOutputDevice midiOutputDevice = midiOutputDeviceMap.get(split[0]); + if (midiOutputDevice != null) { + midiOutputDevice.sendMidiActiveSensing(); + } + } + + public void sendMidiReset(String serializedMidiMessage) { + String[] split = serializedMidiMessage.split(","); + if (split.length < 1) { + return; + } + MidiOutputDevice midiOutputDevice = midiOutputDeviceMap.get(split[0]); + if (midiOutputDevice != null) { + midiOutputDevice.sendMidiReset(); + } + } + + private BleMidiCentralProvider bleMidiCentralProvider; + HashMap midiOutputDeviceMap = new HashMap<>(); + + public void initialize(Context context) { + bleMidiCentralProvider = new BleMidiCentralProvider(context); + bleMidiCentralProvider.setOnMidiDeviceAttachedListener(new OnMidiDeviceAttachedListener() { + @Override + public void onMidiInputDeviceAttached(@NonNull MidiInputDevice midiInputDevice) { + midiInputDevice.setOnMidiInputEventListener(midiInputEventListener); + UnityPlayer.UnitySendMessage(GAME_OBJECT_NAME, "OnMidiInputDeviceAttached", midiInputDevice.getDeviceAddress()); + } + + @Override + public void onMidiOutputDeviceAttached(@NonNull MidiOutputDevice midiOutputDevice) { + midiOutputDeviceMap.put(midiOutputDevice.getDeviceAddress(), midiOutputDevice); + UnityPlayer.UnitySendMessage(GAME_OBJECT_NAME, "OnMidiOutputDeviceAttached", midiOutputDevice.getDeviceAddress()); + } + }); + + bleMidiCentralProvider.setOnMidiDeviceDetachedListener(new OnMidiDeviceDetachedListener() { + @Override + public void onMidiInputDeviceDetached(@NonNull MidiInputDevice midiInputDevice) { + UnityPlayer.UnitySendMessage(GAME_OBJECT_NAME, "OnMidiInputDeviceDetached", midiInputDevice.getDeviceAddress()); + } + + @Override + public void onMidiOutputDeviceDetached(@NonNull MidiOutputDevice midiOutputDevice) { + midiOutputDeviceMap.remove(midiOutputDevice.getDeviceAddress()); + UnityPlayer.UnitySendMessage(GAME_OBJECT_NAME, "OnMidiOutputDeviceDetached", midiOutputDevice.getDeviceAddress()); + } + }); + } + + /** + * Starts scan device + * @param timeoutInMilliSeconds timeout in msec, 0 : no timeout + */ + public void startScanDevice(int timeoutInMilliSeconds) { + bleMidiCentralProvider.startScanDevice(timeoutInMilliSeconds); + } + + /** + * Stops scan device + */ + public void stopScanDevice() { + bleMidiCentralProvider.stopScanDevice(); + } + + + /** + * Obtains device name for deviceId + * @param deviceId the device id + * @return device name, product name, or null + */ + public String getDeviceName(String deviceId) { + MidiOutputDevice device = midiOutputDeviceMap.get(deviceId); + if (device != null) { + if (!TextUtils.isEmpty(device.getDeviceName())) { + return device.getDeviceName(); + } + } + return null; + } + + public void terminate() { + if (bleMidiCentralProvider != null) { + bleMidiCentralProvider.stopScanDevice(); + bleMidiCentralProvider.terminate(); + } + } +} diff --git a/library/src/main/res/values/uuids.xml b/BLE-MIDI-library/src/main/res/values/uuids.xml similarity index 100% rename from library/src/main/res/values/uuids.xml rename to BLE-MIDI-library/src/main/res/values/uuids.xml diff --git a/README.md b/README.md index add8c9a..3d5c6b5 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ BLE MIDI for Android ==================== -[![Build Status](https://travis-ci.org/kshoji/BLE-MIDI-for-Android.svg?branch=master)](https://travis-ci.org/kshoji/BLE-MIDI-for-Android) +[![Build Status](https://travis-ci.com/kshoji/BLE-MIDI-for-Android.svg?branch=develop)](https://travis-ci.com/kshoji/BLE-MIDI-for-Android) MIDI over Bluetooth LE library for Android `API Level 18`(4.3, JellyBean) or later @@ -30,9 +30,6 @@ Repository Overview - Sample Project: `sample` - Includes `BleMidiCentralActivity`, and `BleMidiPeripheralActivity` examples. -Pre-compiled sample app is available on [Google Play Market](https://play.google.com/store/apps/details?id=jp.kshoji.blemidi.sample). -
![QR Code](https://dl.dropboxusercontent.com/u/3968074/qr_ble_midi_sample.png) - Usage of the library -------------------- diff --git a/UnityPlayerMock/.gitignore b/UnityPlayerMock/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/UnityPlayerMock/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/UnityPlayerMock/build.gradle b/UnityPlayerMock/build.gradle new file mode 100644 index 0000000..40b7f78 --- /dev/null +++ b/UnityPlayerMock/build.gradle @@ -0,0 +1,9 @@ +apply plugin: 'java' + +sourceCompatibility = JavaVersion.VERSION_1_8 +targetCompatibility = JavaVersion.VERSION_1_8 + +jar { + archiveBaseName = 'unityplayermock' + archiveVersion = '0.0.1' +} diff --git a/UnityPlayerMock/src/main/java/com/unity3d/player/UnityPlayer.java b/UnityPlayerMock/src/main/java/com/unity3d/player/UnityPlayer.java new file mode 100644 index 0000000..998d083 --- /dev/null +++ b/UnityPlayerMock/src/main/java/com/unity3d/player/UnityPlayer.java @@ -0,0 +1,6 @@ +package com.unity3d.player; + +public class UnityPlayer { + public static void UnitySendMessage(String gameObjectName, String onMidiInputDeviceAttached, String deviceAddress) { + } +} diff --git a/build.gradle b/build.gradle index a6fcfe1..d1e5c6f 100644 --- a/build.gradle +++ b/build.gradle @@ -2,10 +2,11 @@ buildscript { repositories { - jcenter() + mavenCentral() + google() } dependencies { - classpath 'com.android.tools.build:gradle:1.5.0' + classpath 'com.android.tools.build:gradle:4.2.1' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files @@ -14,6 +15,7 @@ buildscript { allprojects { repositories { - jcenter() + mavenCentral() + google() } } diff --git a/gradle.properties b/gradle.properties index 5d08ba7..07cd1b8 100644 --- a/gradle.properties +++ b/gradle.properties @@ -15,4 +15,6 @@ # When configured, Gradle will run in incubating parallel mode. # This option should only be used with decoupled projects. More details, visit # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects -# org.gradle.parallel=true \ No newline at end of file +# org.gradle.parallel=true +android.useAndroidX=true +org.gradle.jvmargs=-Xmx4096m -XX:MaxMetaspaceSize=512m diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 55897a6..01104c9 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Thu Nov 27 10:31:49 JST 2014 +#Fri Oct 30 09:54:11 JST 2020 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-2.2.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-6.7.1-all.zip diff --git a/library/repository/jp/kshoji/ble-midi/0.0.10-SNAPSHOT/ble-midi-0.0.10-20201109.103103-1.aar b/library/repository/jp/kshoji/ble-midi/0.0.10-SNAPSHOT/ble-midi-0.0.10-20201109.103103-1.aar new file mode 100644 index 0000000..1b1620d Binary files /dev/null and b/library/repository/jp/kshoji/ble-midi/0.0.10-SNAPSHOT/ble-midi-0.0.10-20201109.103103-1.aar differ diff --git a/library/repository/jp/kshoji/ble-midi/0.0.10-SNAPSHOT/ble-midi-0.0.10-20201109.103103-1.aar.md5 b/library/repository/jp/kshoji/ble-midi/0.0.10-SNAPSHOT/ble-midi-0.0.10-20201109.103103-1.aar.md5 new file mode 100644 index 0000000..4afe9a9 --- /dev/null +++ b/library/repository/jp/kshoji/ble-midi/0.0.10-SNAPSHOT/ble-midi-0.0.10-20201109.103103-1.aar.md5 @@ -0,0 +1 @@ +3563199dee261b713fc3dba42a511abb \ No newline at end of file diff --git a/library/repository/jp/kshoji/ble-midi/0.0.10-SNAPSHOT/ble-midi-0.0.10-20201109.103103-1.aar.sha1 b/library/repository/jp/kshoji/ble-midi/0.0.10-SNAPSHOT/ble-midi-0.0.10-20201109.103103-1.aar.sha1 new file mode 100644 index 0000000..a75d82a --- /dev/null +++ b/library/repository/jp/kshoji/ble-midi/0.0.10-SNAPSHOT/ble-midi-0.0.10-20201109.103103-1.aar.sha1 @@ -0,0 +1 @@ +151405d0259818a2b4c740446b24886d2a815e10 \ No newline at end of file diff --git a/library/repository/jp/kshoji/ble-midi/0.0.10-SNAPSHOT/ble-midi-0.0.10-20201109.103103-1.pom b/library/repository/jp/kshoji/ble-midi/0.0.10-SNAPSHOT/ble-midi-0.0.10-20201109.103103-1.pom new file mode 100644 index 0000000..4e26c2e --- /dev/null +++ b/library/repository/jp/kshoji/ble-midi/0.0.10-SNAPSHOT/ble-midi-0.0.10-20201109.103103-1.pom @@ -0,0 +1,31 @@ + + + 4.0.0 + jp.kshoji + ble-midi + 0.0.10-SNAPSHOT + aar + + + jp.kshoji + javax-sound-midi + 0.0.4-SNAPSHOT + aar + + compile + + + * + * + + + + + com.android.support + support-annotations + 22.2.1 + compile + + + diff --git a/library/repository/jp/kshoji/ble-midi/0.0.10-SNAPSHOT/ble-midi-0.0.10-20201109.103103-1.pom.md5 b/library/repository/jp/kshoji/ble-midi/0.0.10-SNAPSHOT/ble-midi-0.0.10-20201109.103103-1.pom.md5 new file mode 100644 index 0000000..f9e23bd --- /dev/null +++ b/library/repository/jp/kshoji/ble-midi/0.0.10-SNAPSHOT/ble-midi-0.0.10-20201109.103103-1.pom.md5 @@ -0,0 +1 @@ +64fc113574406285d6943cff268ff589 \ No newline at end of file diff --git a/library/repository/jp/kshoji/ble-midi/0.0.10-SNAPSHOT/ble-midi-0.0.10-20201109.103103-1.pom.sha1 b/library/repository/jp/kshoji/ble-midi/0.0.10-SNAPSHOT/ble-midi-0.0.10-20201109.103103-1.pom.sha1 new file mode 100644 index 0000000..93c7a43 --- /dev/null +++ b/library/repository/jp/kshoji/ble-midi/0.0.10-SNAPSHOT/ble-midi-0.0.10-20201109.103103-1.pom.sha1 @@ -0,0 +1 @@ +e7909d82e68d605dda312932da31f6eaf3fe0807 \ No newline at end of file diff --git a/library/repository/jp/kshoji/ble-midi/0.0.10-SNAPSHOT/ble-midi-0.0.10-20210531.055408-2.aar b/library/repository/jp/kshoji/ble-midi/0.0.10-SNAPSHOT/ble-midi-0.0.10-20210531.055408-2.aar new file mode 100644 index 0000000..2259690 Binary files /dev/null and b/library/repository/jp/kshoji/ble-midi/0.0.10-SNAPSHOT/ble-midi-0.0.10-20210531.055408-2.aar differ diff --git a/library/repository/jp/kshoji/ble-midi/0.0.10-SNAPSHOT/ble-midi-0.0.10-20210531.055408-2.aar.md5 b/library/repository/jp/kshoji/ble-midi/0.0.10-SNAPSHOT/ble-midi-0.0.10-20210531.055408-2.aar.md5 new file mode 100644 index 0000000..e549e3a --- /dev/null +++ b/library/repository/jp/kshoji/ble-midi/0.0.10-SNAPSHOT/ble-midi-0.0.10-20210531.055408-2.aar.md5 @@ -0,0 +1 @@ +2bf2274c5ddbbed2d6ee578ae1b9f6f1 \ No newline at end of file diff --git a/library/repository/jp/kshoji/ble-midi/0.0.10-SNAPSHOT/ble-midi-0.0.10-20210531.055408-2.aar.sha1 b/library/repository/jp/kshoji/ble-midi/0.0.10-SNAPSHOT/ble-midi-0.0.10-20210531.055408-2.aar.sha1 new file mode 100644 index 0000000..8dd98e9 --- /dev/null +++ b/library/repository/jp/kshoji/ble-midi/0.0.10-SNAPSHOT/ble-midi-0.0.10-20210531.055408-2.aar.sha1 @@ -0,0 +1 @@ +44e9a5fbf9d4a71e0f033202869b914bd8151f43 \ No newline at end of file diff --git a/library/repository/jp/kshoji/ble-midi/0.0.10-SNAPSHOT/ble-midi-0.0.10-20210531.055408-2.pom b/library/repository/jp/kshoji/ble-midi/0.0.10-SNAPSHOT/ble-midi-0.0.10-20210531.055408-2.pom new file mode 100644 index 0000000..cba601b --- /dev/null +++ b/library/repository/jp/kshoji/ble-midi/0.0.10-SNAPSHOT/ble-midi-0.0.10-20210531.055408-2.pom @@ -0,0 +1,31 @@ + + + 4.0.0 + jp.kshoji + ble-midi + 0.0.10-SNAPSHOT + aar + + + jp.kshoji + javax-sound-midi + 0.0.4-SNAPSHOT + aar + + compile + + + * + * + + + + + com.android.support + support-annotations + 28.0.0 + compile + + + diff --git a/library/repository/jp/kshoji/ble-midi/0.0.10-SNAPSHOT/ble-midi-0.0.10-20210531.055408-2.pom.md5 b/library/repository/jp/kshoji/ble-midi/0.0.10-SNAPSHOT/ble-midi-0.0.10-20210531.055408-2.pom.md5 new file mode 100644 index 0000000..564c62c --- /dev/null +++ b/library/repository/jp/kshoji/ble-midi/0.0.10-SNAPSHOT/ble-midi-0.0.10-20210531.055408-2.pom.md5 @@ -0,0 +1 @@ +b4f64e6296f5857f199449dd126a4af7 \ No newline at end of file diff --git a/library/repository/jp/kshoji/ble-midi/0.0.10-SNAPSHOT/ble-midi-0.0.10-20210531.055408-2.pom.sha1 b/library/repository/jp/kshoji/ble-midi/0.0.10-SNAPSHOT/ble-midi-0.0.10-20210531.055408-2.pom.sha1 new file mode 100644 index 0000000..b6f5024 --- /dev/null +++ b/library/repository/jp/kshoji/ble-midi/0.0.10-SNAPSHOT/ble-midi-0.0.10-20210531.055408-2.pom.sha1 @@ -0,0 +1 @@ +22b1b0971bedaf24f915ac7ccffc58dbb4de2395 \ No newline at end of file diff --git a/library/repository/jp/kshoji/ble-midi/0.0.10-SNAPSHOT/ble-midi-0.0.10-20210604.045028-3.aar b/library/repository/jp/kshoji/ble-midi/0.0.10-SNAPSHOT/ble-midi-0.0.10-20210604.045028-3.aar new file mode 100644 index 0000000..7e305e5 Binary files /dev/null and b/library/repository/jp/kshoji/ble-midi/0.0.10-SNAPSHOT/ble-midi-0.0.10-20210604.045028-3.aar differ diff --git a/library/repository/jp/kshoji/ble-midi/0.0.10-SNAPSHOT/ble-midi-0.0.10-20210604.045028-3.aar.md5 b/library/repository/jp/kshoji/ble-midi/0.0.10-SNAPSHOT/ble-midi-0.0.10-20210604.045028-3.aar.md5 new file mode 100644 index 0000000..b972e9d --- /dev/null +++ b/library/repository/jp/kshoji/ble-midi/0.0.10-SNAPSHOT/ble-midi-0.0.10-20210604.045028-3.aar.md5 @@ -0,0 +1 @@ +3e6f5b23437833ea4825f3d0a5ab184f \ No newline at end of file diff --git a/library/repository/jp/kshoji/ble-midi/0.0.10-SNAPSHOT/ble-midi-0.0.10-20210604.045028-3.aar.sha1 b/library/repository/jp/kshoji/ble-midi/0.0.10-SNAPSHOT/ble-midi-0.0.10-20210604.045028-3.aar.sha1 new file mode 100644 index 0000000..d19602c --- /dev/null +++ b/library/repository/jp/kshoji/ble-midi/0.0.10-SNAPSHOT/ble-midi-0.0.10-20210604.045028-3.aar.sha1 @@ -0,0 +1 @@ +68da6afa473ba2ee0de5bd7a7bca407431e50227 \ No newline at end of file diff --git a/library/repository/jp/kshoji/ble-midi/0.0.10-SNAPSHOT/ble-midi-0.0.10-20210604.045028-3.pom b/library/repository/jp/kshoji/ble-midi/0.0.10-SNAPSHOT/ble-midi-0.0.10-20210604.045028-3.pom new file mode 100644 index 0000000..cba601b --- /dev/null +++ b/library/repository/jp/kshoji/ble-midi/0.0.10-SNAPSHOT/ble-midi-0.0.10-20210604.045028-3.pom @@ -0,0 +1,31 @@ + + + 4.0.0 + jp.kshoji + ble-midi + 0.0.10-SNAPSHOT + aar + + + jp.kshoji + javax-sound-midi + 0.0.4-SNAPSHOT + aar + + compile + + + * + * + + + + + com.android.support + support-annotations + 28.0.0 + compile + + + diff --git a/library/repository/jp/kshoji/ble-midi/0.0.10-SNAPSHOT/ble-midi-0.0.10-20210604.045028-3.pom.md5 b/library/repository/jp/kshoji/ble-midi/0.0.10-SNAPSHOT/ble-midi-0.0.10-20210604.045028-3.pom.md5 new file mode 100644 index 0000000..564c62c --- /dev/null +++ b/library/repository/jp/kshoji/ble-midi/0.0.10-SNAPSHOT/ble-midi-0.0.10-20210604.045028-3.pom.md5 @@ -0,0 +1 @@ +b4f64e6296f5857f199449dd126a4af7 \ No newline at end of file diff --git a/library/repository/jp/kshoji/ble-midi/0.0.10-SNAPSHOT/ble-midi-0.0.10-20210604.045028-3.pom.sha1 b/library/repository/jp/kshoji/ble-midi/0.0.10-SNAPSHOT/ble-midi-0.0.10-20210604.045028-3.pom.sha1 new file mode 100644 index 0000000..b6f5024 --- /dev/null +++ b/library/repository/jp/kshoji/ble-midi/0.0.10-SNAPSHOT/ble-midi-0.0.10-20210604.045028-3.pom.sha1 @@ -0,0 +1 @@ +22b1b0971bedaf24f915ac7ccffc58dbb4de2395 \ No newline at end of file diff --git a/library/repository/jp/kshoji/ble-midi/0.0.10-SNAPSHOT/ble-midi-0.0.10-20210612.070708-4.aar b/library/repository/jp/kshoji/ble-midi/0.0.10-SNAPSHOT/ble-midi-0.0.10-20210612.070708-4.aar new file mode 100644 index 0000000..ee1a40d Binary files /dev/null and b/library/repository/jp/kshoji/ble-midi/0.0.10-SNAPSHOT/ble-midi-0.0.10-20210612.070708-4.aar differ diff --git a/library/repository/jp/kshoji/ble-midi/0.0.10-SNAPSHOT/ble-midi-0.0.10-20210612.070708-4.aar.md5 b/library/repository/jp/kshoji/ble-midi/0.0.10-SNAPSHOT/ble-midi-0.0.10-20210612.070708-4.aar.md5 new file mode 100644 index 0000000..eca38bd --- /dev/null +++ b/library/repository/jp/kshoji/ble-midi/0.0.10-SNAPSHOT/ble-midi-0.0.10-20210612.070708-4.aar.md5 @@ -0,0 +1 @@ +eba66b743dd45edc997ccb66135c9f8f \ No newline at end of file diff --git a/library/repository/jp/kshoji/ble-midi/0.0.10-SNAPSHOT/ble-midi-0.0.10-20210612.070708-4.aar.sha1 b/library/repository/jp/kshoji/ble-midi/0.0.10-SNAPSHOT/ble-midi-0.0.10-20210612.070708-4.aar.sha1 new file mode 100644 index 0000000..3e1b143 --- /dev/null +++ b/library/repository/jp/kshoji/ble-midi/0.0.10-SNAPSHOT/ble-midi-0.0.10-20210612.070708-4.aar.sha1 @@ -0,0 +1 @@ +6b7cb1b5edacef9c7df433410b0fd37898d32623 \ No newline at end of file diff --git a/library/repository/jp/kshoji/ble-midi/0.0.10-SNAPSHOT/ble-midi-0.0.10-20210612.070708-4.pom b/library/repository/jp/kshoji/ble-midi/0.0.10-SNAPSHOT/ble-midi-0.0.10-20210612.070708-4.pom new file mode 100644 index 0000000..cba601b --- /dev/null +++ b/library/repository/jp/kshoji/ble-midi/0.0.10-SNAPSHOT/ble-midi-0.0.10-20210612.070708-4.pom @@ -0,0 +1,31 @@ + + + 4.0.0 + jp.kshoji + ble-midi + 0.0.10-SNAPSHOT + aar + + + jp.kshoji + javax-sound-midi + 0.0.4-SNAPSHOT + aar + + compile + + + * + * + + + + + com.android.support + support-annotations + 28.0.0 + compile + + + diff --git a/library/repository/jp/kshoji/ble-midi/0.0.10-SNAPSHOT/ble-midi-0.0.10-20210612.070708-4.pom.md5 b/library/repository/jp/kshoji/ble-midi/0.0.10-SNAPSHOT/ble-midi-0.0.10-20210612.070708-4.pom.md5 new file mode 100644 index 0000000..564c62c --- /dev/null +++ b/library/repository/jp/kshoji/ble-midi/0.0.10-SNAPSHOT/ble-midi-0.0.10-20210612.070708-4.pom.md5 @@ -0,0 +1 @@ +b4f64e6296f5857f199449dd126a4af7 \ No newline at end of file diff --git a/library/repository/jp/kshoji/ble-midi/0.0.10-SNAPSHOT/ble-midi-0.0.10-20210612.070708-4.pom.sha1 b/library/repository/jp/kshoji/ble-midi/0.0.10-SNAPSHOT/ble-midi-0.0.10-20210612.070708-4.pom.sha1 new file mode 100644 index 0000000..b6f5024 --- /dev/null +++ b/library/repository/jp/kshoji/ble-midi/0.0.10-SNAPSHOT/ble-midi-0.0.10-20210612.070708-4.pom.sha1 @@ -0,0 +1 @@ +22b1b0971bedaf24f915ac7ccffc58dbb4de2395 \ No newline at end of file diff --git a/library/repository/jp/kshoji/ble-midi/0.0.10-SNAPSHOT/maven-metadata.xml b/library/repository/jp/kshoji/ble-midi/0.0.10-SNAPSHOT/maven-metadata.xml new file mode 100644 index 0000000..76beea6 --- /dev/null +++ b/library/repository/jp/kshoji/ble-midi/0.0.10-SNAPSHOT/maven-metadata.xml @@ -0,0 +1,25 @@ + + + jp.kshoji + ble-midi + 0.0.10-SNAPSHOT + + + 20210612.070708 + 4 + + 20210612070708 + + + aar + 0.0.10-20210612.070708-4 + 20210612070708 + + + pom + 0.0.10-20210612.070708-4 + 20210612070708 + + + + diff --git a/library/repository/jp/kshoji/ble-midi/0.0.10-SNAPSHOT/maven-metadata.xml.md5 b/library/repository/jp/kshoji/ble-midi/0.0.10-SNAPSHOT/maven-metadata.xml.md5 new file mode 100644 index 0000000..d7b023b --- /dev/null +++ b/library/repository/jp/kshoji/ble-midi/0.0.10-SNAPSHOT/maven-metadata.xml.md5 @@ -0,0 +1 @@ +80aa06aa83d90ebf8d55ce79a8cc2803 \ No newline at end of file diff --git a/library/repository/jp/kshoji/ble-midi/0.0.10-SNAPSHOT/maven-metadata.xml.sha1 b/library/repository/jp/kshoji/ble-midi/0.0.10-SNAPSHOT/maven-metadata.xml.sha1 new file mode 100644 index 0000000..313f2f8 --- /dev/null +++ b/library/repository/jp/kshoji/ble-midi/0.0.10-SNAPSHOT/maven-metadata.xml.sha1 @@ -0,0 +1 @@ +0dcbf25dd55629b28dc07bc7d618661b8e20e964 \ No newline at end of file diff --git a/library/repository/jp/kshoji/ble-midi/0.0.10/ble-midi-0.0.10.aar b/library/repository/jp/kshoji/ble-midi/0.0.10/ble-midi-0.0.10.aar new file mode 100644 index 0000000..ee1a40d Binary files /dev/null and b/library/repository/jp/kshoji/ble-midi/0.0.10/ble-midi-0.0.10.aar differ diff --git a/library/repository/jp/kshoji/ble-midi/0.0.10/ble-midi-0.0.10.aar.md5 b/library/repository/jp/kshoji/ble-midi/0.0.10/ble-midi-0.0.10.aar.md5 new file mode 100644 index 0000000..eca38bd --- /dev/null +++ b/library/repository/jp/kshoji/ble-midi/0.0.10/ble-midi-0.0.10.aar.md5 @@ -0,0 +1 @@ +eba66b743dd45edc997ccb66135c9f8f \ No newline at end of file diff --git a/library/repository/jp/kshoji/ble-midi/0.0.10/ble-midi-0.0.10.aar.sha1 b/library/repository/jp/kshoji/ble-midi/0.0.10/ble-midi-0.0.10.aar.sha1 new file mode 100644 index 0000000..3e1b143 --- /dev/null +++ b/library/repository/jp/kshoji/ble-midi/0.0.10/ble-midi-0.0.10.aar.sha1 @@ -0,0 +1 @@ +6b7cb1b5edacef9c7df433410b0fd37898d32623 \ No newline at end of file diff --git a/library/repository/jp/kshoji/ble-midi/0.0.10/ble-midi-0.0.10.pom b/library/repository/jp/kshoji/ble-midi/0.0.10/ble-midi-0.0.10.pom new file mode 100644 index 0000000..1e80e06 --- /dev/null +++ b/library/repository/jp/kshoji/ble-midi/0.0.10/ble-midi-0.0.10.pom @@ -0,0 +1,31 @@ + + + 4.0.0 + jp.kshoji + ble-midi + 0.0.10 + aar + + + jp.kshoji + javax-sound-midi + 0.0.4-SNAPSHOT + aar + + compile + + + * + * + + + + + com.android.support + support-annotations + 28.0.0 + compile + + + diff --git a/library/repository/jp/kshoji/ble-midi/0.0.10/ble-midi-0.0.10.pom.md5 b/library/repository/jp/kshoji/ble-midi/0.0.10/ble-midi-0.0.10.pom.md5 new file mode 100644 index 0000000..7b6bbdb --- /dev/null +++ b/library/repository/jp/kshoji/ble-midi/0.0.10/ble-midi-0.0.10.pom.md5 @@ -0,0 +1 @@ +bfc9c48513c3c0f74b50313b5b12d30b \ No newline at end of file diff --git a/library/repository/jp/kshoji/ble-midi/0.0.10/ble-midi-0.0.10.pom.sha1 b/library/repository/jp/kshoji/ble-midi/0.0.10/ble-midi-0.0.10.pom.sha1 new file mode 100644 index 0000000..25f3b83 --- /dev/null +++ b/library/repository/jp/kshoji/ble-midi/0.0.10/ble-midi-0.0.10.pom.sha1 @@ -0,0 +1 @@ +8fdcbee40a1d78af78cd09eb1ee7923de46752e3 \ No newline at end of file diff --git a/library/repository/jp/kshoji/ble-midi/maven-metadata.xml b/library/repository/jp/kshoji/ble-midi/maven-metadata.xml index df662f2..fa9e248 100644 --- a/library/repository/jp/kshoji/ble-midi/maven-metadata.xml +++ b/library/repository/jp/kshoji/ble-midi/maven-metadata.xml @@ -2,8 +2,8 @@ jp.kshoji ble-midi - 0.0.1 + 0.0.10 0.0.1 0.0.2-SNAPSHOT @@ -19,7 +19,9 @@ 0.0.7 0.0.8 0.0.9 + 0.0.10-SNAPSHOT + 0.0.10 - 20151215053958 + 20210701002824 diff --git a/library/repository/jp/kshoji/ble-midi/maven-metadata.xml.md5 b/library/repository/jp/kshoji/ble-midi/maven-metadata.xml.md5 index a1db34b..b9e4235 100644 --- a/library/repository/jp/kshoji/ble-midi/maven-metadata.xml.md5 +++ b/library/repository/jp/kshoji/ble-midi/maven-metadata.xml.md5 @@ -1 +1 @@ -b92c0a930ddf88bc20a5fb32a5b45d20 +6a42a9d5d48a8fcb97bd51906e871600 \ No newline at end of file diff --git a/library/repository/jp/kshoji/ble-midi/maven-metadata.xml.sha1 b/library/repository/jp/kshoji/ble-midi/maven-metadata.xml.sha1 index e8e4bd2..2217d78 100644 --- a/library/repository/jp/kshoji/ble-midi/maven-metadata.xml.sha1 +++ b/library/repository/jp/kshoji/ble-midi/maven-metadata.xml.sha1 @@ -1 +1 @@ -5da16141807740ebb9c05ee9a647514647f13f76 +bc6f59bcc579a36878a6f79680dce773510a147a \ No newline at end of file diff --git a/sample-wear/build.gradle b/sample-wear/build.gradle index 06c041f..17a712b 100644 --- a/sample-wear/build.gradle +++ b/sample-wear/build.gradle @@ -1,12 +1,12 @@ apply plugin: 'com.android.application' android { - compileSdkVersion 22 - buildToolsVersion "22.0.1" + compileSdkVersion 30 defaultConfig { applicationId "jp.kshoji.blemidi.sample" minSdkVersion 22 + targetSdkVersion 30 versionCode 3 versionName "1.2" } @@ -32,9 +32,9 @@ repositories { } dependencies { - compile fileTree(dir: 'libs', include: ['*.jar']) - compile project(":library") - compile 'com.google.android.support:wearable:1.2.0' - provided 'com.google.android.wearable:wearable:1.0.0' - compile 'com.google.android.gms:play-services-wearable:8.3.0' + implementation fileTree(dir: 'libs', include: ['*.jar']) + implementation project(':BLE-MIDI-library') + implementation 'com.google.android.support:wearable:2.8.1' + compileOnly 'com.google.android.wearable:wearable:2.8.1' + implementation 'com.google.android.gms:play-services-wearable:17.1.0' } diff --git a/sample/build.gradle b/sample/build.gradle index 4d79934..e28fb09 100644 --- a/sample/build.gradle +++ b/sample/build.gradle @@ -1,12 +1,12 @@ apply plugin: 'com.android.application' android { - compileSdkVersion 22 - buildToolsVersion "22.0.1" + compileSdkVersion 30 defaultConfig { applicationId "jp.kshoji.blemidi.sample" minSdkVersion 18 + targetSdkVersion 29 versionCode 3 versionName "1.2" } @@ -32,8 +32,8 @@ repositories { } dependencies { - compile fileTree(dir: 'libs', include: ['*.jar']) + implementation fileTree(dir: 'libs', include: ['*.jar']) wearApp project(':sample-wear') - compile project(":library") - compile 'com.google.android.gms:play-services:8.3.0' + implementation project(':BLE-MIDI-library') + api 'com.android.support:support-annotations:28.0.0' } diff --git a/sample/src/main/AndroidManifest.xml b/sample/src/main/AndroidManifest.xml index 184ac90..5deb7b9 100644 --- a/sample/src/main/AndroidManifest.xml +++ b/sample/src/main/AndroidManifest.xml @@ -2,10 +2,7 @@ - - - - + = Build.VERSION_CODES.M) { + if (checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) { + if (!shouldShowRequestPermissionRationale(Manifest.permission.ACCESS_FINE_LOCATION)) { + scanDuration = duration; + requestPermissions(new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, PERMISSION_REQUEST_FINE_LOCATION); + return; + } + } + } + + // already has permission + bleMidiCentralProvider.startScanDevice(duration); + } + @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { @@ -74,13 +95,25 @@ public boolean onOptionsItemSelected(MenuItem item) { if (isScanning) { bleMidiCentralProvider.stopScanDevice(); } else { - bleMidiCentralProvider.startScanDevice(0); + startScanDeviceWithRequestingPermission(scanDuration); } return true; } return super.onOptionsItemSelected(item); } + @Override + public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + if (requestCode == PERMISSION_REQUEST_FINE_LOCATION) { + if (checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) { + bleMidiCentralProvider.startScanDevice(0); + } + } + } + } + // User interface final Handler midiInputEventHandler = new Handler(new Handler.Callback() { @Override @@ -576,7 +609,7 @@ public void onMidiScanStatusChanged(boolean isScanning) { }); // scan devices for 30 seconds - bleMidiCentralProvider.startScanDevice(30000); + startScanDeviceWithRequestingPermission(30000); } @Override @@ -616,8 +649,6 @@ public void onDismiss(DialogInterface dialog) { @Override protected void onDestroy() { - super.onDestroy(); - if (bleMidiCentralProvider != null) { bleMidiCentralProvider.terminate(); } @@ -643,6 +674,8 @@ protected void onDestroy() { audioTrack = null; } } + + super.onDestroy(); } /** diff --git a/sample/src/main/java/jp/kshoji/blemidi/sample/PeripheralActivity.java b/sample/src/main/java/jp/kshoji/blemidi/sample/PeripheralActivity.java index 0b615f1..201ec05 100644 --- a/sample/src/main/java/jp/kshoji/blemidi/sample/PeripheralActivity.java +++ b/sample/src/main/java/jp/kshoji/blemidi/sample/PeripheralActivity.java @@ -594,8 +594,6 @@ public void onDismiss(DialogInterface dialog) { @Override protected void onDestroy() { - super.onDestroy(); - if (bleMidiPeripheralProvider != null) { bleMidiPeripheralProvider.terminate(); } @@ -621,6 +619,8 @@ protected void onDestroy() { audioTrack = null; } } + + super.onDestroy(); } /** diff --git a/settings.gradle b/settings.gradle index 3c268ab..f5c297b 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1 +1 @@ -include ':library', ':sample', ':sample-wear' +include ':BLE-MIDI-library', ':sample', ':sample-wear', ':UnityPlayerMock'