From 89857bb7385e1d256d109c9122fd1bce589dec6e Mon Sep 17 00:00:00 2001 From: Mas Azalya <43565312+MAzalya@users.noreply.github.com> Date: Thu, 23 Jul 2026 14:30:17 +0800 Subject: [PATCH 1/4] switch to ShimmerResearch --- ShimmerAndroidInstrumentDriver/build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ShimmerAndroidInstrumentDriver/build.gradle b/ShimmerAndroidInstrumentDriver/build.gradle index 482081d..e1e2708 100644 --- a/ShimmerAndroidInstrumentDriver/build.gradle +++ b/ShimmerAndroidInstrumentDriver/build.gradle @@ -28,7 +28,7 @@ allprojects { google() maven { name = "GitHubPackages" - url = uri("https://maven.pkg.github.com/ShimmerEngineering/Shimmer-Java-Android-API") + url = uri("https://maven.pkg.github.com/ShimmerResearch/Shimmer-Java-Android-API") credentials { /* Create gradle.properties file in GRADLE_USER_HOME/.gradle/ (e.g. C:/Users/YourUsername/.gradle/) with the two lines listed below. Fill in your @@ -48,7 +48,7 @@ allprojects { } maven { name = "GitHubPackages" - url = uri("https://maven.pkg.github.com/ShimmerEngineering/ShimmerAndroidAPI") + url = uri("https://maven.pkg.github.com/ShimmerResearch/ShimmerAndroidAPI") credentials { /* Create gradle.properties file in GRADLE_USER_HOME/.gradle/ (e.g. C:/Users/YourUsername/.gradle/) with the two lines listed below. Fill in your From 931bcc1be85d5adcb9b26160e1c20b8fd210ae06 Mon Sep 17 00:00:00 2001 From: Danesh Mariapan <161300025+dmariapan-shimmer@users.noreply.github.com> Date: Tue, 28 Jul 2026 14:27:10 +0800 Subject: [PATCH 2/4] Fixes for shimmerLegacyExample --- .../src/main/AndroidManifest.xml | 7 +- .../guiUtilities/ShimmerBluetoothDialog.java | 111 ++++++++++++++---- .../src/main/AndroidManifest.xml | 6 + .../shimmerlegacyexample/MainActivity.java | 73 +++++++++++- 4 files changed, 167 insertions(+), 30 deletions(-) diff --git a/ShimmerAndroidInstrumentDriver/ShimmerAndroidInstrumentDriver/src/main/AndroidManifest.xml b/ShimmerAndroidInstrumentDriver/ShimmerAndroidInstrumentDriver/src/main/AndroidManifest.xml index b12bf64..1c36285 100644 --- a/ShimmerAndroidInstrumentDriver/ShimmerAndroidInstrumentDriver/src/main/AndroidManifest.xml +++ b/ShimmerAndroidInstrumentDriver/ShimmerAndroidInstrumentDriver/src/main/AndroidManifest.xml @@ -2,8 +2,11 @@ package="com.shimmerresearch.androidinstrumentdriver" android:versionCode="1" android:versionName="1.0" > - - + + + + + = 21) { @@ -126,21 +129,19 @@ public void onClick(View v) { // Get the local Bluetooth adapter mBtAdapter = BluetoothAdapter.getDefaultAdapter(); - // Get a set of currently paired devices - Set pairedDevices = mBtAdapter.getBondedDevices(); + if (mBtAdapter == null) { + Toast.makeText(this, "Bluetooth is not available on this device", Toast.LENGTH_SHORT).show(); + finish(); + return; + } - // If there are paired devices, add each one to the ArrayAdapter - if (pairedDevices.size() > 0) { - pairedListView.setEnabled(true); - findViewById(R.id.title_paired_devices).setVisibility(View.VISIBLE); - for (BluetoothDevice device : pairedDevices) { - mPairedDevicesArrayAdapter.add(device.getName() + "\n" + device.getAddress()); - } - } else { - String noDevices = getResources().getText(R.string.none_paired).toString(); - mPairedDevicesArrayAdapter.add(noDevices); - pairedListView.setEnabled(false); + if (!hasBluetoothConnectPermission()) { + requestBluetoothPermissions(); + showNoPermissionPairedState(pairedListView); + return; } + + populatePairedDevices(pairedListView); } @Override @@ -148,7 +149,7 @@ protected void onDestroy() { super.onDestroy(); // Make sure we're not doing discovery anymore - if (mBtAdapter != null) { + if (mBtAdapter != null && hasBluetoothScanPermission()) { mBtAdapter.cancelDiscovery(); } @@ -159,6 +160,7 @@ protected void onDestroy() { /** * Start device discover with the BluetoothAdapter */ + @SuppressLint("MissingPermission") private void doDiscovery() { if (D) Log.d(TAG, "doDiscovery()"); @@ -171,17 +173,10 @@ private void doDiscovery() { findViewById(R.id.layoutNewDevices).setVisibility(View.VISIBLE); // If we're already discovering, stop it - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { - if (ActivityCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH_SCAN) != PackageManager.PERMISSION_GRANTED) { - // TODO: Consider calling - // ActivityCompat#requestPermissions - // here to request the missing permissions, and then overriding - // public void onRequestPermissionsResult(int requestCode, String[] permissions, - // int[] grantResults) - // to handle the case where the user grants the permission. See the documentation - // for ActivityCompat#requestPermissions for more details. - return; - } + if (!hasBluetoothScanPermission()) { + requestBluetoothPermissions(); + Toast.makeText(this, "Bluetooth permission required to scan devices", Toast.LENGTH_SHORT).show(); + return; } if (mBtAdapter.isDiscovering()) { @@ -219,6 +214,7 @@ public void onItemClick(AdapterView av, View v, int arg2, long arg3) { // changes the title when discovery is finished private final BroadcastReceiver mReceiver = new BroadcastReceiver() { @Override + @SuppressLint("MissingPermission") public void onReceive(Context context, Intent intent) { String action = intent.getAction(); @@ -227,7 +223,7 @@ public void onReceive(Context context, Intent intent) { // Get the BluetoothDevice object from the Intent BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); // If it's already paired, skip it, because it's been listed already - if (device.getBondState() != BluetoothDevice.BOND_BONDED) { + if (device != null && hasBluetoothConnectPermission() && device.getBondState() != BluetoothDevice.BOND_BONDED) { mNewDevicesArrayAdapter.add(device.getName() + "\n" + device.getAddress()); } // When discovery is finished, change the Activity title @@ -242,4 +238,67 @@ public void onReceive(Context context, Intent intent) { } }; + private boolean hasBluetoothConnectPermission() { + return Build.VERSION.SDK_INT < Build.VERSION_CODES.S || + ActivityCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH_CONNECT) == PackageManager.PERMISSION_GRANTED; + } + + private boolean hasBluetoothScanPermission() { + return Build.VERSION.SDK_INT < Build.VERSION_CODES.S || + ActivityCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH_SCAN) == PackageManager.PERMISSION_GRANTED; + } + + private void requestBluetoothPermissions() { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { + ActivityCompat.requestPermissions( + this, + new String[]{Manifest.permission.BLUETOOTH_CONNECT, Manifest.permission.BLUETOOTH_SCAN}, + REQUEST_BLUETOOTH_PERMISSIONS + ); + } + } + + private void showNoPermissionPairedState(ListView pairedListView) { + String noPermission = "Bluetooth permission not granted"; + mPairedDevicesArrayAdapter.clear(); + mPairedDevicesArrayAdapter.add(noPermission); + pairedListView.setEnabled(false); + } + + @Override + @SuppressLint("MissingPermission") + public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults); + + if (requestCode != REQUEST_BLUETOOTH_PERMISSIONS) { + return; + } + + if (!hasBluetoothConnectPermission() || !hasBluetoothScanPermission()) { + Toast.makeText(this, "Bluetooth permission denied", Toast.LENGTH_SHORT).show(); + return; + } + + ListView pairedListView = (ListView) findViewById(R.id.paired_devices); + populatePairedDevices(pairedListView); + } + + @SuppressLint("MissingPermission") + private void populatePairedDevices(ListView pairedListView) { + mPairedDevicesArrayAdapter.clear(); + Set pairedDevices = mBtAdapter.getBondedDevices(); + + if (!pairedDevices.isEmpty()) { + pairedListView.setEnabled(true); + findViewById(R.id.title_paired_devices).setVisibility(View.VISIBLE); + for (BluetoothDevice device : pairedDevices) { + mPairedDevicesArrayAdapter.add(device.getName() + "\n" + device.getAddress()); + } + } else { + String noDevices = getResources().getText(R.string.none_paired).toString(); + mPairedDevicesArrayAdapter.add(noDevices); + pairedListView.setEnabled(false); + } + } + } diff --git a/ShimmerAndroidInstrumentDriver/shimmerLegacyExample/src/main/AndroidManifest.xml b/ShimmerAndroidInstrumentDriver/shimmerLegacyExample/src/main/AndroidManifest.xml index 9f48500..566811c 100644 --- a/ShimmerAndroidInstrumentDriver/shimmerLegacyExample/src/main/AndroidManifest.xml +++ b/ShimmerAndroidInstrumentDriver/shimmerLegacyExample/src/main/AndroidManifest.xml @@ -2,6 +2,12 @@ + + + + + + diff --git a/ShimmerAndroidInstrumentDriver/shimmerLegacyExample/src/main/java/com/shimmerresearch/shimmerlegacyexample/MainActivity.java b/ShimmerAndroidInstrumentDriver/shimmerLegacyExample/src/main/java/com/shimmerresearch/shimmerlegacyexample/MainActivity.java index 47c523d..8d2156b 100644 --- a/ShimmerAndroidInstrumentDriver/shimmerLegacyExample/src/main/java/com/shimmerresearch/shimmerlegacyexample/MainActivity.java +++ b/ShimmerAndroidInstrumentDriver/shimmerLegacyExample/src/main/java/com/shimmerresearch/shimmerlegacyexample/MainActivity.java @@ -1,10 +1,14 @@ package com.shimmerresearch.shimmerlegacyexample; import android.app.Activity; +import android.Manifest; import android.content.Intent; +import android.content.pm.PackageManager; +import android.os.Build; import android.os.Handler; import android.os.Message; import androidx.appcompat.app.AppCompatActivity; +import androidx.core.app.ActivityCompat; import android.os.Bundle; import android.util.Log; import android.view.View; @@ -40,16 +44,53 @@ public class MainActivity extends AppCompatActivity { String shimmerBtAdd = ""; final static String LOG_TAG = "ShimmerLegacyExample"; private boolean mFirstTimeConnection = true; + private static final int REQUEST_BLUETOOTH_PERMISSIONS = 2001; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); + ensureBluetoothPermissionsAndInitManager(); + } + + private void ensureBluetoothPermissionsAndInitManager() { + if (hasRequiredBluetoothPermissions()) { + initializeBtManager(); + } else { + ActivityCompat.requestPermissions( + this, + new String[]{Manifest.permission.BLUETOOTH_CONNECT, Manifest.permission.BLUETOOTH_SCAN}, + REQUEST_BLUETOOTH_PERMISSIONS + ); + } + } + + private boolean hasRequiredBluetoothPermissions() { + return Build.VERSION.SDK_INT < Build.VERSION_CODES.S || + (ActivityCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH_CONNECT) == PackageManager.PERMISSION_GRANTED + && ActivityCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH_SCAN) == PackageManager.PERMISSION_GRANTED); + } + + private void initializeBtManager() { try { btManager = new ShimmerBluetoothManagerAndroid(this, mHandler); - } catch(Exception e) { + } catch (Exception e) { e.printStackTrace(); + Toast.makeText(this, "Unable to initialize Bluetooth manager", Toast.LENGTH_SHORT).show(); + } + } + + @Override + public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults); + + if (requestCode == REQUEST_BLUETOOTH_PERMISSIONS) { + if (hasRequiredBluetoothPermissions()) { + initializeBtManager(); + } else { + Toast.makeText(this, "Bluetooth permissions are required", Toast.LENGTH_LONG).show(); + } } } @@ -137,11 +178,22 @@ public void handleMessage(Message msg) { }; public void selectDevice(View v) { + if (!hasRequiredBluetoothPermissions()) { + ensureBluetoothPermissionsAndInitManager(); + Toast.makeText(this, "Grant Bluetooth permissions to select a device", Toast.LENGTH_SHORT).show(); + return; + } + Intent intent = new Intent(getApplicationContext(), ShimmerBluetoothDialog.class); startActivityForResult(intent, ShimmerBluetoothDialog.REQUEST_CONNECT_SHIMMER); } public void startStreaming(View v) { + if (btManager == null) { + Toast.makeText(this, "Bluetooth manager not ready", Toast.LENGTH_SHORT).show(); + return; + } + try { btManager.startStreaming(shimmerBtAdd); } catch (ShimmerException e) { @@ -150,6 +202,11 @@ public void startStreaming(View v) { } public void stopStreaming(View v) { + if (btManager == null) { + Toast.makeText(this, "Bluetooth manager not ready", Toast.LENGTH_SHORT).show(); + return; + } + try { btManager.stopStreaming(shimmerBtAdd); } catch (ShimmerException e) { @@ -158,6 +215,11 @@ public void stopStreaming(View v) { } public void disconnectDevice(View v){ + if (btManager == null) { + Toast.makeText(this, "Bluetooth manager not ready", Toast.LENGTH_SHORT).show(); + return; + } + btManager.disconnectAllDevices(); mFirstTimeConnection = true; } @@ -191,6 +253,11 @@ public void configureSensors(View v) { protected void onActivityResult(int requestCode, int resultCode, Intent data) { if(requestCode == 2) { if (resultCode == Activity.RESULT_OK) { + if (btManager == null) { + Toast.makeText(this, "Bluetooth manager not ready", Toast.LENGTH_SHORT).show(); + return; + } + //Ensure no previous device is connected to the App as it only supports a single device at a time: btManager.disconnectAllDevices(); @@ -206,7 +273,9 @@ protected void onActivityResult(int requestCode, int resultCode, Intent data) { @Override protected void onDestroy() { - btManager.disconnectAllDevices(); + if (btManager != null) { + btManager.disconnectAllDevices(); + } super.onDestroy(); } } From 5f71704a929652f5d474b2001b1421deede79be5 Mon Sep 17 00:00:00 2001 From: Danesh Mariapan <161300025+dmariapan-shimmer@users.noreply.github.com> Date: Tue, 28 Jul 2026 14:37:29 +0800 Subject: [PATCH 3/4] Build fix for shimmerspeedtest --- ShimmerAndroidInstrumentDriver/shimmerspeedtest/build.gradle | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/ShimmerAndroidInstrumentDriver/shimmerspeedtest/build.gradle b/ShimmerAndroidInstrumentDriver/shimmerspeedtest/build.gradle index 94ef84d..edacc39 100644 --- a/ShimmerAndroidInstrumentDriver/shimmerspeedtest/build.gradle +++ b/ShimmerAndroidInstrumentDriver/shimmerspeedtest/build.gradle @@ -46,9 +46,10 @@ android { dependencies { implementation 'androidx.constraintlayout:constraintlayout:2.1.4' + implementation 'com.google.android.material:material:1.12.0' implementation project(':ShimmerAndroidInstrumentDriver') - implementation 'android.arch.navigation:navigation-fragment:1.0.0' - implementation 'android.arch.navigation:navigation-ui:1.0.0' + implementation 'androidx.navigation:navigation-fragment:2.7.7' + implementation 'androidx.navigation:navigation-ui:2.7.7' testImplementation 'junit:junit:4.13.2' androidTestImplementation 'androidx.test:runner:1.5.2' androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1' From 94026613537c1811eb2dbe534ffed5b119ff201e Mon Sep 17 00:00:00 2001 From: Danesh Mariapan <161300025+dmariapan-shimmer@users.noreply.github.com> Date: Tue, 28 Jul 2026 14:59:06 +0800 Subject: [PATCH 4/4] Connection fixes for multiverisenseblebasicexample --- .../src/main/AndroidManifest.xml | 4 +- .../MainActivity.java | 210 ++++++++++-------- 2 files changed, 125 insertions(+), 89 deletions(-) diff --git a/ShimmerAndroidInstrumentDriver/multiverisenseblebasicexample/src/main/AndroidManifest.xml b/ShimmerAndroidInstrumentDriver/multiverisenseblebasicexample/src/main/AndroidManifest.xml index b66c24f..afd0bfd 100644 --- a/ShimmerAndroidInstrumentDriver/multiverisenseblebasicexample/src/main/AndroidManifest.xml +++ b/ShimmerAndroidInstrumentDriver/multiverisenseblebasicexample/src/main/AndroidManifest.xml @@ -7,7 +7,6 @@ android:maxSdkVersion="30" /> - @@ -31,6 +30,9 @@ + \ No newline at end of file diff --git a/ShimmerAndroidInstrumentDriver/multiverisenseblebasicexample/src/main/java/shimmerresearch/com/multiverisenseblebasicexample/MainActivity.java b/ShimmerAndroidInstrumentDriver/multiverisenseblebasicexample/src/main/java/shimmerresearch/com/multiverisenseblebasicexample/MainActivity.java index 8f54fee..b05870e 100644 --- a/ShimmerAndroidInstrumentDriver/multiverisenseblebasicexample/src/main/java/shimmerresearch/com/multiverisenseblebasicexample/MainActivity.java +++ b/ShimmerAndroidInstrumentDriver/multiverisenseblebasicexample/src/main/java/shimmerresearch/com/multiverisenseblebasicexample/MainActivity.java @@ -22,6 +22,7 @@ import com.clj.fastble.BleManager; import com.shimmerresearch.android.Shimmer; import com.shimmerresearch.android.VerisenseDeviceAndroid; +import com.shimmerresearch.android.guiUtilities.ShimmerBluetoothDialog; import com.shimmerresearch.android.manager.ShimmerBluetoothManagerAndroid; import com.shimmerresearch.androidradiodriver.VerisenseBleAndroidRadioByteCommunication; import com.shimmerresearch.bluetooth.ShimmerBluetooth; @@ -34,11 +35,17 @@ import com.shimmerresearch.verisense.sensors.SensorLIS2DW12; import java.io.IOException; +import java.util.ArrayList; import java.util.Collection; +import java.util.List; public class MainActivity extends AppCompatActivity { private final static String LOG_TAG = "MultiVeriBLEExample"; + private static final int REQUEST_CONNECT_SENSOR_1 = 201; + private static final int REQUEST_CONNECT_SENSOR_2 = 202; + private static final int REQUEST_CONNECT_SENSOR_3 = 203; + VerisenseBleAndroidRadioByteCommunication radio1 = new VerisenseBleAndroidRadioByteCommunication("DA:A6:19:F0:4A:D7"); VerisenseProtocolByteCommunication protocol1 = new VerisenseProtocolByteCommunication(radio1); VerisenseDeviceAndroid device1; @@ -60,81 +67,131 @@ public class MainActivity extends AppCompatActivity { private Thread t2 = null; private Thread t3 = null; - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.activity_main); - boolean permissionGranted = true; - int permissionCheck = 0; - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { - permissionCheck = ContextCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH_CONNECT); + private void initializeBleAndDevices() { + BleManager.getInstance().init(getApplication()); + device1 = new VerisenseDeviceAndroid(mHandler); + device2 = new VerisenseDeviceAndroid(mHandler); + device3 = new VerisenseDeviceAndroid(mHandler); + } - if (permissionCheck != PackageManager.PERMISSION_GRANTED) { - permissionGranted = false; + private boolean hasPermission(String permission) { + return ContextCompat.checkSelfPermission(this, permission) == PackageManager.PERMISSION_GRANTED; + } + + private String[] getMissingRequiredPermissions() { + List missingPermissions = new ArrayList<>(); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { + if (!hasPermission(Manifest.permission.BLUETOOTH_CONNECT)) { + missingPermissions.add(Manifest.permission.BLUETOOTH_CONNECT); } - permissionCheck = ContextCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH_SCAN); - if (permissionCheck != PackageManager.PERMISSION_GRANTED) { - permissionGranted = false; + if (!hasPermission(Manifest.permission.BLUETOOTH_SCAN)) { + missingPermissions.add(Manifest.permission.BLUETOOTH_SCAN); } } else { - permissionCheck = ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_BACKGROUND_LOCATION); - if (permissionCheck != PackageManager.PERMISSION_GRANTED) { - permissionGranted = false; + if (!hasPermission(Manifest.permission.ACCESS_FINE_LOCATION) + && !hasPermission(Manifest.permission.ACCESS_COARSE_LOCATION)) { + missingPermissions.add(Manifest.permission.ACCESS_FINE_LOCATION); } } - permissionCheck = ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION); - if (permissionCheck != PackageManager.PERMISSION_GRANTED) { - permissionGranted = false; + return missingPermissions.toArray(new String[0]); + } + + private boolean hasRequiredBluetoothPermissions() { + return getMissingRequiredPermissions().length == 0; + } + + private boolean ensureDevicesReady() { + if (device1 == null || device2 == null || device3 == null) { + runOnUiThread(() -> Toast.makeText(MainActivity.this, + "Bluetooth permissions are required before connecting.", + Toast.LENGTH_SHORT).show()); + return false; } - permissionCheck = ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION); - if (permissionCheck != PackageManager.PERMISSION_GRANTED) { - permissionGranted = false; + return true; + } + + private void launchDevicePicker(int requestCode) { + Intent pairedDevicesIntent = new Intent(this.getApplicationContext(), ShimmerBluetoothDialog.class); + startActivityForResult(pairedDevicesIntent, requestCode); + } + + private void connectToSelectedDevice(int requestCode, String macAddress) { + if (macAddress == null || macAddress.isEmpty()) { + Toast.makeText(this, "No device selected.", Toast.LENGTH_SHORT).show(); + return; } + switch (requestCode) { + case REQUEST_CONNECT_SENSOR_1: + radio1 = new VerisenseBleAndroidRadioByteCommunication(macAddress); + protocol1 = new VerisenseProtocolByteCommunication(radio1); + connectDeviceInThread(device1, protocol1, "Sensor 1"); + break; + case REQUEST_CONNECT_SENSOR_2: + radio2 = new VerisenseBleAndroidRadioByteCommunication(macAddress); + protocol2 = new VerisenseProtocolByteCommunication(radio2); + connectDeviceInThread(device2, protocol2, "Sensor 2"); + break; + case REQUEST_CONNECT_SENSOR_3: + radio3 = new VerisenseBleAndroidRadioByteCommunication(macAddress); + protocol3 = new VerisenseProtocolByteCommunication(radio3); + connectDeviceInThread(device3, protocol3, "Sensor 3"); + break; + } + } - if (!permissionGranted) { - // Should we show an explanation? - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { - ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.BLUETOOTH_CONNECT, Manifest.permission.BLUETOOTH_SCAN, Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION}, 110); - } else { - ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_BACKGROUND_LOCATION}, 110); + private void connectDeviceInThread(VerisenseDeviceAndroid device, + VerisenseProtocolByteCommunication protocol, + String sensorName) { + Thread thread = new Thread() { + public void run() { + device.setProtocol(Configuration.COMMUNICATION_TYPE.BLUETOOTH, protocol); + try { + device.connect(); + } catch (ShimmerException e1) { + Log.e(LOG_TAG, "Connect failed for " + sensorName, e1); + runOnUiThread(() -> Toast.makeText(MainActivity.this, + "Connect failed for " + sensorName, + Toast.LENGTH_SHORT).show()); + } } + }; + thread.start(); + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_main); + String[] missingPermissions = getMissingRequiredPermissions(); + if (missingPermissions.length > 0) { + ActivityCompat.requestPermissions(this, missingPermissions, 110); } else { - BleManager.getInstance().init(getApplication()); - device1 = new VerisenseDeviceAndroid(mHandler); - device2 = new VerisenseDeviceAndroid(mHandler); - device3 = new VerisenseDeviceAndroid(mHandler); + initializeBleAndDevices(); } } @Override public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults); if (requestCode == 110){ - BleManager.getInstance().init(getApplication()); - device1 = new VerisenseDeviceAndroid(mHandler); - device2 = new VerisenseDeviceAndroid(mHandler); - device3 = new VerisenseDeviceAndroid(mHandler); + // Re-check actual permission state because Android may split/merge dialog results. + if (hasRequiredBluetoothPermissions()) { + initializeBleAndDevices(); + } else { + Toast.makeText(this, + "Required Bluetooth permission denied. Cannot connect to devices.", + Toast.LENGTH_SHORT).show(); + } } } //Sensor 1 public void connectDevice1(View v) { - - Thread thread = new Thread(){ - public void run(){ - - device1.setProtocol(Configuration.COMMUNICATION_TYPE.BLUETOOTH, protocol1); - try { - device1.connect(); - } catch (ShimmerException e1) { - // TODO Auto-generated catch block - e1.printStackTrace(); - } - - } - }; - - thread.start(); + if (!ensureDevicesReady()) { + return; + } + launchDevicePicker(REQUEST_CONNECT_SENSOR_1); } public void disconnectDevice1(View v) { @@ -229,22 +286,10 @@ public void run(){ //Sensor 2 public void connectDevice2(View v) { - - Thread thread = new Thread(){ - public void run(){ - - device2.setProtocol(Configuration.COMMUNICATION_TYPE.BLUETOOTH, protocol2); - try { - device2.connect(); - } catch (ShimmerException e1) { - // TODO Auto-generated catch block - e1.printStackTrace(); - } - - } - }; - - thread.start(); + if (!ensureDevicesReady()) { + return; + } + launchDevicePicker(REQUEST_CONNECT_SENSOR_2); } public void disconnectDevice2(View v) { @@ -342,22 +387,10 @@ public void run(){ } //Sensor 3 public void connectDevice3(View v) { - - Thread thread = new Thread(){ - public void run(){ - - device3.setProtocol(Configuration.COMMUNICATION_TYPE.BLUETOOTH, protocol3); - try { - device3.connect(); - } catch (ShimmerException e1) { - // TODO Auto-generated catch block - e1.printStackTrace(); - } - - } - }; - - thread.start(); + if (!ensureDevicesReady()) { + return; + } + launchDevicePicker(REQUEST_CONNECT_SENSOR_3); } public void disconnectDevice3(View v) { @@ -547,11 +580,12 @@ public void handleMessage(Message msg) { */ @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { - if(requestCode == 2) { - if (resultCode == Activity.RESULT_OK) { - //Get the Bluetooth mac address of the selected device: + if (requestCode == REQUEST_CONNECT_SENSOR_1 + || requestCode == REQUEST_CONNECT_SENSOR_2 + || requestCode == REQUEST_CONNECT_SENSOR_3) { + if (resultCode == Activity.RESULT_OK && data != null) { String macAdd = data.getStringExtra(EXTRA_DEVICE_ADDRESS); - + connectToSelectedDevice(requestCode, macAdd); } }