mirror of
https://codeberg.org/Freeyourgadget/Gadgetbridge
synced 2024-11-27 12:26:48 +01:00
Added CompanionDeviceManager support, added target 29 support, refactored the scan display and UI.
This commit is contained in:
parent
1b43468b9e
commit
b76a8267b8
@ -16,13 +16,13 @@ android {
|
||||
sourceCompatibility JavaVersion.VERSION_1_7
|
||||
targetCompatibility JavaVersion.VERSION_1_7
|
||||
}
|
||||
compileSdkVersion 28
|
||||
buildToolsVersion '29.0.2'
|
||||
compileSdkVersion 29
|
||||
buildToolsVersion '29.0.3'
|
||||
|
||||
defaultConfig {
|
||||
applicationId "nodomain.freeyourgadget.gadgetbridge"
|
||||
minSdkVersion 19
|
||||
targetSdkVersion 28
|
||||
targetSdkVersion 29
|
||||
|
||||
// Note: always bump BOTH versionCode and versionName!
|
||||
versionName "0.46.0"
|
||||
|
@ -1,12 +1,21 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
package="nodomain.freeyourgadget.gadgetbridge">
|
||||
|
||||
<!--
|
||||
Comment in for testing Pebble Emulator
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
-->
|
||||
<!-- Used for Bluetooth access -->
|
||||
<uses-permission android:name="android.permission.BLUETOOTH" />
|
||||
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
|
||||
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
|
||||
|
||||
<!-- Since Android 10 -->
|
||||
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
|
||||
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
|
||||
|
||||
<uses-permission android:name="android.permission.READ_CALL_LOG" />
|
||||
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
|
||||
<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS" />
|
||||
@ -16,19 +25,29 @@
|
||||
<uses-permission android:name="android.permission.RECEIVE_SMS" />
|
||||
<uses-permission android:name="android.permission.SEND_SMS" />
|
||||
<uses-permission android:name="android.permission.READ_CONTACTS" />
|
||||
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.READ_CALENDAR" />
|
||||
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
|
||||
<uses-permission android:name="android.permission.MEDIA_CONTENT_CONTROL" />
|
||||
<uses-permission
|
||||
android:name="android.permission.MEDIA_CONTENT_CONTROL"
|
||||
tools:ignore="ProtectedPermissions" />
|
||||
|
||||
<!-- Used for background service -->
|
||||
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
||||
<uses-permission android:name="android.permission.VIBRATE" /> <!-- Used for reverse find device -->
|
||||
<uses-permission android:name="android.permission.REQUEST_COMPANION_RUN_IN_BACKGROUND" />
|
||||
|
||||
<!-- Used for reverse find device -->
|
||||
<uses-permission android:name="android.permission.VIBRATE" />
|
||||
|
||||
<!-- Used for weather provider access -->
|
||||
<uses-permission android:name="cyanogenmod.permission.ACCESS_WEATHER_MANAGER" />
|
||||
<uses-permission android:name="cyanogenmod.permission.READ_WEATHER" />
|
||||
<uses-permission android:name="lineageos.permission.ACCESS_WEATHER_MANAGER" />
|
||||
<uses-permission android:name="lineageos.permission.READ_WEATHER" />
|
||||
<uses-permission android:name="org.omnirom.omnijaws.READ_WEATHER" />
|
||||
|
||||
|
||||
<uses-feature
|
||||
android:name="android.hardware.bluetooth"
|
||||
android:required="true" />
|
||||
@ -38,6 +57,9 @@
|
||||
<uses-feature
|
||||
android:name="android.hardware.telephony"
|
||||
android:required="false" />
|
||||
<uses-feature
|
||||
android:name="android.software.companion_device_setup"
|
||||
android:required="false" />
|
||||
|
||||
<application
|
||||
android:name=".GBApplication"
|
||||
@ -47,7 +69,7 @@
|
||||
android:label="@string/app_name"
|
||||
android:roundIcon="@mipmap/ic_launcher_round"
|
||||
android:theme="@style/GadgetbridgeTheme">
|
||||
<activity android:name=".devices.qhybrid.WidgetSettingsActivity"></activity>
|
||||
<activity android:name=".devices.qhybrid.WidgetSettingsActivity" />
|
||||
<activity
|
||||
android:name=".activities.ControlCenterv2"
|
||||
android:label="@string/title_activity_controlcenter"
|
||||
@ -293,6 +315,7 @@
|
||||
|
||||
<data android:mimeType="application/octet-stream" />
|
||||
</intent-filter>
|
||||
|
||||
<!-- to receive firmwares from the download content provider if recognized as zip -->
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
@ -302,6 +325,7 @@
|
||||
<data android:mimeType="application/zip" />
|
||||
<data android:mimeType="application/x-zip-compressed" />
|
||||
</intent-filter>
|
||||
|
||||
<!-- to receive files from the "share" intent -->
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.SEND" />
|
||||
@ -346,13 +370,21 @@
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
|
||||
<receiver
|
||||
android:name=".externalevents.BluetoothStateChangeReceiver"
|
||||
android:exported="false">
|
||||
android:exported="false"
|
||||
android:permission="android.permission.BLUETOOTH,android.permission.BLUETOOTH_ADMIN">
|
||||
<intent-filter>
|
||||
<action android:name="android.bluetooth.adapter.action.STATE_CHANGED" />
|
||||
<action android:name="android.bluetooth.adapter.action.CONNECTION_STATE_CHANGED" />
|
||||
|
||||
<action android:name="android.bluetooth.device.action.ACL_CONNECTED" />
|
||||
<action android:name="android.bluetooth.device.action.ACL_DISCONNECTED" />
|
||||
<action android:name="android.bluetooth.device.action.ACL_DISCONNECT_REQUESTED" />
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
|
||||
<receiver
|
||||
android:name=".service.receivers.GBMusicControlReceiver"
|
||||
android:exported="false">
|
||||
@ -370,7 +402,7 @@
|
||||
<receiver
|
||||
android:name=".database.PeriodicExporter"
|
||||
android:enabled="true"
|
||||
android:exported="false"></receiver>
|
||||
android:exported="false" />
|
||||
<!--
|
||||
forcing the DebugActivity to portrait mode avoids crashes with the progress
|
||||
dialog when changing orientation
|
||||
@ -415,10 +447,10 @@
|
||||
android:label="@string/title_activity_watch9_calibration" />
|
||||
<activity
|
||||
android:name=".devices.lenovo.LenovoWatchPairingActivity"
|
||||
android:label="@string/title_activity_watch9_pairing" />
|
||||
android:label="@string/title_activity_watch9_pairing" />
|
||||
<activity
|
||||
android:name=".devices.lenovo.LenovoWatchCalibrationActivity"
|
||||
android:label="@string/title_activity_LenovoWatch_calibration" />
|
||||
android:label="@string/title_activity_LenovoWatch_calibration" />
|
||||
<activity
|
||||
android:name=".activities.charts.ChartsActivity"
|
||||
android:label="@string/title_activity_charts"
|
||||
@ -448,10 +480,13 @@
|
||||
android:name=".activities.FindPhoneActivity"
|
||||
android:label="Find Phone" />
|
||||
|
||||
<!--
|
||||
<provider
|
||||
android:name=".contentprovider.PebbleContentProvider"
|
||||
android:authorities="com.getpebble.android.provider"
|
||||
android:exported="true" />
|
||||
-->
|
||||
|
||||
<provider
|
||||
android:name="androidx.core.content.FileProvider"
|
||||
android:authorities="${applicationId}.screenshot_provider"
|
||||
@ -512,6 +547,7 @@
|
||||
<data android:scheme="gadgetbridge" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name=".devices.qhybrid.ConfigActivity"
|
||||
android:exported="true" />
|
||||
@ -525,5 +561,4 @@
|
||||
android:name=".devices.qhybrid.ImageEditActivity"
|
||||
android:exported="true" />
|
||||
</application>
|
||||
|
||||
</manifest>
|
@ -31,19 +31,25 @@ import android.bluetooth.le.ScanFilter;
|
||||
import android.bluetooth.le.ScanRecord;
|
||||
import android.bluetooth.le.ScanResult;
|
||||
import android.bluetooth.le.ScanSettings;
|
||||
import android.companion.AssociationRequest;
|
||||
import android.companion.BluetoothDeviceFilter;
|
||||
import android.companion.CompanionDeviceManager;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.content.IntentSender;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.location.LocationManager;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Message;
|
||||
import android.os.ParcelUuid;
|
||||
import android.os.Parcelable;
|
||||
import android.provider.Settings;
|
||||
import android.view.View;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.Button;
|
||||
@ -52,6 +58,7 @@ import android.widget.ProgressBar;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.RequiresApi;
|
||||
import androidx.core.app.ActivityCompat;
|
||||
import androidx.core.content.ContextCompat;
|
||||
|
||||
@ -73,26 +80,51 @@ import nodomain.freeyourgadget.gadgetbridge.model.DeviceType;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.AndroidUtils;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.DeviceHelper;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.GB;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.Prefs;
|
||||
|
||||
import static nodomain.freeyourgadget.gadgetbridge.util.GB.toast;
|
||||
|
||||
|
||||
public class DiscoveryActivity extends AbstractGBActivity implements AdapterView.OnItemClickListener, AdapterView.OnItemLongClickListener {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(DiscoveryActivity.class);
|
||||
private static final long SCAN_DURATION = 60000; // 60s
|
||||
private static final long SCAN_DURATION = 30000; // 30s
|
||||
private static final int REQUEST_CODE = 1;
|
||||
private ScanCallback newBLEScanCallback = null;
|
||||
|
||||
private ScanCallback newLeScanCallback = null;
|
||||
|
||||
// Disabled for testing, it seems worse for a few people
|
||||
private boolean disableNewBLEScanning = false;
|
||||
/** Use old BLE scanning **/
|
||||
private boolean oldBleScanning = false;
|
||||
/** If already bonded devices are to be ignored when scanning */
|
||||
private boolean ignoreBonded = true;
|
||||
/** If new CompanionDevice-type pairing is enabled on newer Androids **/
|
||||
private boolean enableCompanionDevicePairing = false;
|
||||
|
||||
private final Handler handler = new Handler();
|
||||
private ProgressBar bluetoothProgress;
|
||||
private ProgressBar bluetoothLEProgress;
|
||||
|
||||
private final Runnable stopRunnable = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (isScanning == Scanning.SCANNING_BT_NEXT_BLE) {
|
||||
// Start the next scan in the series
|
||||
stopDiscovery();
|
||||
startDiscovery(Scanning.SCANNING_BLE);
|
||||
} else {
|
||||
stopDiscovery();
|
||||
}
|
||||
}
|
||||
};
|
||||
private DeviceCandidateAdapter deviceCandidateAdapter;
|
||||
private final BroadcastReceiver bluetoothReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
switch (Objects.requireNonNull(intent.getAction())) {
|
||||
case BluetoothAdapter.ACTION_DISCOVERY_STARTED:
|
||||
if (isScanning != Scanning.SCANNING_BTLE && isScanning != Scanning.SCANNING_NEW_BTLE) {
|
||||
discoveryStarted(Scanning.SCANNING_BT);
|
||||
if (isScanning != Scanning.SCANNING_BLE) {
|
||||
if (isScanning != Scanning.SCANNING_BT_NEXT_BLE) {
|
||||
isScanning = Scanning.SCANNING_BT;
|
||||
}
|
||||
startButton.setText(getString(R.string.discovery_stop_scanning));
|
||||
}
|
||||
break;
|
||||
case BluetoothAdapter.ACTION_DISCOVERY_FINISHED:
|
||||
@ -100,13 +132,10 @@ public class DiscoveryActivity extends AbstractGBActivity implements AdapterView
|
||||
@Override
|
||||
public void run() {
|
||||
// continue with LE scan, if available
|
||||
if (isScanning == Scanning.SCANNING_BT) {
|
||||
if (isScanning == Scanning.SCANNING_BT || isScanning == Scanning.SCANNING_BT_NEXT_BLE) {
|
||||
checkAndRequestLocationPermission();
|
||||
if (GBApplication.isRunningLollipopOrLater() && !disableNewBLEScanning) {
|
||||
startDiscovery(Scanning.SCANNING_NEW_BTLE);
|
||||
} else {
|
||||
startDiscovery(Scanning.SCANNING_BTLE);
|
||||
}
|
||||
stopDiscovery();
|
||||
startDiscovery(Scanning.SCANNING_BLE);
|
||||
} else {
|
||||
discoveryFinished();
|
||||
}
|
||||
@ -145,16 +174,16 @@ public class DiscoveryActivity extends AbstractGBActivity implements AdapterView
|
||||
};
|
||||
|
||||
private void connectAndFinish(GBDevice device) {
|
||||
GB.toast(DiscoveryActivity.this, getString(R.string.discovery_trying_to_connect_to, device.getName()), Toast.LENGTH_SHORT, GB.INFO);
|
||||
toast(DiscoveryActivity.this, getString(R.string.discovery_trying_to_connect_to, device.getName()), Toast.LENGTH_SHORT, GB.INFO);
|
||||
GBApplication.deviceService().connect(device, true);
|
||||
finish();
|
||||
}
|
||||
|
||||
private void createBond(final GBDeviceCandidate deviceCandidate, int bondingStyle) {
|
||||
if (bondingStyle == DeviceCoordinator.BONDING_STYLE_NONE) {
|
||||
// Do nothing
|
||||
return;
|
||||
}
|
||||
if (bondingStyle == DeviceCoordinator.BONDING_STYLE_ASK) {
|
||||
} else if (bondingStyle == DeviceCoordinator.BONDING_STYLE_ASK) {
|
||||
new AlertDialog.Builder(this)
|
||||
.setCancelable(true)
|
||||
.setTitle(DiscoveryActivity.this.getString(R.string.discovery_pair_title, deviceCandidate.getName()))
|
||||
@ -176,25 +205,20 @@ public class DiscoveryActivity extends AbstractGBActivity implements AdapterView
|
||||
} else {
|
||||
doCreatePair(deviceCandidate);
|
||||
}
|
||||
LOG.debug("Bonding initiated");
|
||||
}
|
||||
|
||||
private void doCreatePair(GBDeviceCandidate deviceCandidate) {
|
||||
GB.toast(DiscoveryActivity.this, getString(R.string.discovery_attempting_to_pair, deviceCandidate.getName()), Toast.LENGTH_SHORT, GB.INFO);
|
||||
if (deviceCandidate.getDevice().createBond()) {
|
||||
// async, wait for bonding event to finish this activity
|
||||
LOG.info("Bonding in progress...");
|
||||
bondingDevice = deviceCandidate;
|
||||
toast(DiscoveryActivity.this, getString(R.string.discovery_attempting_to_pair, deviceCandidate.getName()), Toast.LENGTH_SHORT, GB.INFO);
|
||||
if (enableCompanionDevicePairing) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
companionDevicePair(deviceCandidate);
|
||||
}
|
||||
} else {
|
||||
GB.toast(DiscoveryActivity.this, getString(R.string.discovery_bonding_failed_immediately, deviceCandidate.getName()), Toast.LENGTH_SHORT, GB.ERROR);
|
||||
deviceBond(deviceCandidate);
|
||||
}
|
||||
}
|
||||
|
||||
private void handleDeviceBonded() {
|
||||
GB.toast(DiscoveryActivity.this, getString(R.string.discovery_successfully_bonded, bondingDevice.getName()), Toast.LENGTH_SHORT, GB.INFO);
|
||||
GBDevice device = DeviceHelper.getInstance().toSupportedDevice(bondingDevice);
|
||||
connectAndFinish(device);
|
||||
}
|
||||
|
||||
private final BluetoothAdapter.LeScanCallback leScanCallback = new BluetoothAdapter.LeScanCallback() {
|
||||
@Override
|
||||
public void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord) {
|
||||
@ -203,38 +227,14 @@ public class DiscoveryActivity extends AbstractGBActivity implements AdapterView
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// why use a method to get callback?
|
||||
// because this callback need API >= 21
|
||||
// we cant add @TARGETAPI("Lollipop") at class header
|
||||
// so use a method with SDK check to return this callback
|
||||
private ScanCallback getScanCallback() {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
newLeScanCallback = new ScanCallback() {
|
||||
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
|
||||
@Override
|
||||
public void onScanResult(int callbackType, ScanResult result) {
|
||||
super.onScanResult(callbackType, result);
|
||||
try {
|
||||
ScanRecord scanRecord = result.getScanRecord();
|
||||
ParcelUuid[] uuids = null;
|
||||
if (scanRecord != null) {
|
||||
//logMessageContent(scanRecord.getBytes());
|
||||
List<ParcelUuid> serviceUuids = scanRecord.getServiceUuids();
|
||||
if (serviceUuids != null) {
|
||||
uuids = serviceUuids.toArray(new ParcelUuid[0]);
|
||||
}
|
||||
}
|
||||
LOG.warn(result.getDevice().getName() + ": " +
|
||||
((scanRecord != null) ? scanRecord.getBytes().length : -1));
|
||||
handleDeviceFound(result.getDevice(), (short) result.getRssi(), uuids);
|
||||
} catch (NullPointerException e) {
|
||||
LOG.warn("Error handling scan result", e);
|
||||
}
|
||||
}
|
||||
};
|
||||
private void deviceBond(GBDeviceCandidate deviceCandidate) {
|
||||
if (deviceCandidate.getDevice().createBond()) {
|
||||
// Async, wait for bonding event to finish this activity
|
||||
LOG.info("Bonding in progress...");
|
||||
bondingDevice = deviceCandidate;
|
||||
} else {
|
||||
toast(DiscoveryActivity.this, getString(R.string.discovery_bonding_failed_immediately, deviceCandidate.getName()), Toast.LENGTH_SHORT, GB.ERROR);
|
||||
}
|
||||
return newLeScanCallback;
|
||||
}
|
||||
|
||||
public void logMessageContent(byte[] value) {
|
||||
@ -243,40 +243,121 @@ public class DiscoveryActivity extends AbstractGBActivity implements AdapterView
|
||||
}
|
||||
}
|
||||
|
||||
private final Runnable stopRunnable = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
stopDiscovery();
|
||||
}
|
||||
};
|
||||
@RequiresApi(Build.VERSION_CODES.O)
|
||||
private void companionDevicePair(final GBDeviceCandidate deviceCandidate) {
|
||||
CompanionDeviceManager deviceManager = getSystemService(CompanionDeviceManager.class);
|
||||
|
||||
BluetoothDeviceFilter deviceFilter = new BluetoothDeviceFilter.Builder()
|
||||
.setAddress(deviceCandidate.getMacAddress())
|
||||
.build();
|
||||
|
||||
AssociationRequest pairingRequest = new AssociationRequest.Builder()
|
||||
.addDeviceFilter(deviceFilter)
|
||||
.setSingleDevice(true)
|
||||
.build();
|
||||
|
||||
deviceManager.associate(pairingRequest,
|
||||
new CompanionDeviceManager.Callback() {
|
||||
@Override
|
||||
public void onFailure(CharSequence error) {
|
||||
toast(DiscoveryActivity.this, getString(R.string.discovery_bonding_failed_immediately, deviceCandidate.getName()), Toast.LENGTH_SHORT, GB.ERROR);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeviceFound(IntentSender chooserLauncher) {
|
||||
try {
|
||||
startIntentSenderForResult(chooserLauncher,
|
||||
REQUEST_CODE, null, 0, 0, 0);
|
||||
} catch (IntentSender.SendIntentException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
},
|
||||
null
|
||||
);
|
||||
}
|
||||
|
||||
@RequiresApi(Build.VERSION_CODES.O)
|
||||
@Override
|
||||
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
if (requestCode == REQUEST_CODE &&
|
||||
resultCode == Activity.RESULT_OK) {
|
||||
|
||||
BluetoothDevice deviceToPair =
|
||||
data.getParcelableExtra(CompanionDeviceManager.EXTRA_DEVICE);
|
||||
|
||||
if (deviceToPair != null) {
|
||||
deviceBond(new GBDeviceCandidate(deviceToPair, (short) 0, null));
|
||||
handleDeviceBonded();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void handleDeviceBonded() {
|
||||
if (bondingDevice == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
toast(DiscoveryActivity.this, getString(R.string.discovery_successfully_bonded, bondingDevice.getName()), Toast.LENGTH_SHORT, GB.INFO);
|
||||
GBDevice device = DeviceHelper.getInstance().toSupportedDevice(bondingDevice);
|
||||
connectAndFinish(device);
|
||||
}
|
||||
|
||||
private ProgressBar progressView;
|
||||
private BluetoothAdapter adapter;
|
||||
private final ArrayList<GBDeviceCandidate> deviceCandidates = new ArrayList<>();
|
||||
private DeviceCandidateAdapter cadidateListAdapter;
|
||||
|
||||
@RequiresApi(Build.VERSION_CODES.LOLLIPOP)
|
||||
private ScanCallback getScanCallback() {
|
||||
if (newBLEScanCallback != null) {
|
||||
return newBLEScanCallback;
|
||||
}
|
||||
|
||||
newBLEScanCallback = new ScanCallback() {
|
||||
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
|
||||
@Override
|
||||
public void onScanResult(int callbackType, ScanResult result) {
|
||||
super.onScanResult(callbackType, result);
|
||||
try {
|
||||
ScanRecord scanRecord = result.getScanRecord();
|
||||
ParcelUuid[] uuids = null;
|
||||
if (scanRecord != null) {
|
||||
//logMessageContent(scanRecord.getBytes());
|
||||
List<ParcelUuid> serviceUuids = scanRecord.getServiceUuids();
|
||||
if (serviceUuids != null) {
|
||||
uuids = serviceUuids.toArray(new ParcelUuid[0]);
|
||||
}
|
||||
}
|
||||
LOG.warn(result.getDevice().getName() + ": " +
|
||||
((scanRecord != null) ? scanRecord.getBytes().length : -1));
|
||||
handleDeviceFound(result.getDevice(), (short) result.getRssi(), uuids);
|
||||
} catch (NullPointerException e) {
|
||||
LOG.warn("Error handling scan result", e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return newBLEScanCallback;
|
||||
}
|
||||
private Button startButton;
|
||||
private Scanning isScanning = Scanning.SCANNING_OFF;
|
||||
private GBDeviceCandidate bondingDevice;
|
||||
|
||||
private boolean ignoreBonded = true;
|
||||
|
||||
|
||||
private enum Scanning {
|
||||
SCANNING_BT,
|
||||
SCANNING_BTLE,
|
||||
SCANNING_NEW_BTLE,
|
||||
SCANNING_OFF
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
ignoreBonded = GBApplication.getPrefs().getBoolean("ignore_bonded_devices", true);
|
||||
Prefs prefs = GBApplication.getPrefs();
|
||||
ignoreBonded = prefs.getBoolean("ignore_bonded_devices", true);
|
||||
|
||||
disableNewBLEScanning = GBApplication.getPrefs().getBoolean("disable_new_ble_scanning", false);
|
||||
if (disableNewBLEScanning) {
|
||||
LOG.info("new BLE scanning disabled via settings, using old method");
|
||||
oldBleScanning = prefs.getBoolean("disable_new_ble_scanning", false);
|
||||
if (oldBleScanning) {
|
||||
LOG.info("New BLE scanning disabled via settings, using old method");
|
||||
}
|
||||
|
||||
enableCompanionDevicePairing = prefs.getBoolean("enable_companiondevice_pairing", false);
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
|
||||
enableCompanionDevicePairing = false; // No support below 26
|
||||
}
|
||||
|
||||
setContentView(R.layout.activity_discovery);
|
||||
@ -288,14 +369,19 @@ public class DiscoveryActivity extends AbstractGBActivity implements AdapterView
|
||||
}
|
||||
});
|
||||
|
||||
progressView = findViewById(R.id.discovery_progressbar);
|
||||
progressView.setProgress(0);
|
||||
progressView.setIndeterminate(true);
|
||||
progressView.setVisibility(View.GONE);
|
||||
ListView deviceCandidatesView = findViewById(R.id.discovery_deviceCandidatesView);
|
||||
bluetoothProgress = findViewById(R.id.discovery_progressbar);
|
||||
bluetoothProgress.setProgress(0);
|
||||
bluetoothProgress.setIndeterminate(true);
|
||||
bluetoothProgress.setVisibility(View.GONE);
|
||||
ListView deviceCandidatesView = findViewById(R.id.discovery_device_candidates_list);
|
||||
|
||||
cadidateListAdapter = new DeviceCandidateAdapter(this, deviceCandidates);
|
||||
deviceCandidatesView.setAdapter(cadidateListAdapter);
|
||||
bluetoothLEProgress = findViewById(R.id.discovery_ble_progressbar);
|
||||
bluetoothLEProgress.setProgress(0);
|
||||
bluetoothLEProgress.setIndeterminate(true);
|
||||
bluetoothLEProgress.setVisibility(View.GONE);
|
||||
|
||||
deviceCandidateAdapter = new DeviceCandidateAdapter(this, deviceCandidates);
|
||||
deviceCandidatesView.setAdapter(deviceCandidateAdapter);
|
||||
deviceCandidatesView.setOnItemClickListener(this);
|
||||
deviceCandidatesView.setOnItemLongClickListener(this);
|
||||
|
||||
@ -310,11 +396,42 @@ public class DiscoveryActivity extends AbstractGBActivity implements AdapterView
|
||||
registerReceiver(bluetoothReceiver, bluetoothIntents);
|
||||
|
||||
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
|
||||
GB.toast(DiscoveryActivity.this, getString(R.string.error_no_location_access), Toast.LENGTH_SHORT, GB.ERROR);
|
||||
toast(DiscoveryActivity.this, getString(R.string.error_no_location_access), Toast.LENGTH_SHORT, GB.ERROR);
|
||||
LOG.error("No permission to access coarse location!");
|
||||
checkAndRequestLocationPermission();
|
||||
|
||||
// We can't be sure location was granted, cancel scan start and wait for user action
|
||||
return;
|
||||
}
|
||||
|
||||
LocationManager locationManager = (LocationManager) DiscoveryActivity.this.getSystemService(Context.LOCATION_SERVICE);
|
||||
try {
|
||||
if (locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER) || locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)) {
|
||||
// Do nothing
|
||||
LOG.debug("Some location provider is enabled, assuming location is enabled");
|
||||
} else {
|
||||
toast(DiscoveryActivity.this, getString(R.string.require_location_provider), Toast.LENGTH_LONG, GB.ERROR);
|
||||
DiscoveryActivity.this.startActivity(new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS));
|
||||
// We can't be sure location was enabled, cancel scan start and wait for new user action
|
||||
return;
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
LOG.error("Exception when checking location status: ", ex);
|
||||
}
|
||||
|
||||
startDiscovery(Scanning.SCANNING_BT_NEXT_BLE);
|
||||
}
|
||||
|
||||
public void onStartButtonClick(View button) {
|
||||
LOG.debug("Start Button clicked");
|
||||
if (isScanning()) {
|
||||
stopDiscovery();
|
||||
} else {
|
||||
startDiscovery();
|
||||
if (GB.supportsBluetoothLE()) {
|
||||
startDiscovery(Scanning.SCANNING_BT_NEXT_BLE);
|
||||
} else {
|
||||
startDiscovery(Scanning.SCANNING_BT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -336,28 +453,21 @@ public class DiscoveryActivity extends AbstractGBActivity implements AdapterView
|
||||
}
|
||||
}
|
||||
|
||||
public void onStartButtonClick(View button) {
|
||||
LOG.debug("Start Button clicked");
|
||||
if (isScanning()) {
|
||||
stopDiscovery();
|
||||
} else {
|
||||
startDiscovery();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
try {
|
||||
unregisterReceiver(bluetoothReceiver);
|
||||
} catch (IllegalArgumentException e) {
|
||||
LOG.warn("Tried to unregister Bluetooth Receiver that wasn't registered.");
|
||||
LOG.warn("Tried to unregister Bluetooth Receiver that wasn't registered");
|
||||
LOG.warn(e.getMessage());
|
||||
}
|
||||
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
private void handleDeviceFound(BluetoothDevice device, short rssi) {
|
||||
if (device.getName() != null) {
|
||||
if (handleDeviceFound(device,rssi, null)) {
|
||||
if (handleDeviceFound(device, rssi, null)) {
|
||||
LOG.info("found supported device " + device.getName() + " without scanning services, skipping service scan.");
|
||||
return;
|
||||
}
|
||||
@ -372,7 +482,6 @@ public class DiscoveryActivity extends AbstractGBActivity implements AdapterView
|
||||
handleDeviceFound(device, rssi, uuids);
|
||||
}
|
||||
|
||||
|
||||
private boolean handleDeviceFound(BluetoothDevice device, short rssi, ParcelUuid[] uuids) {
|
||||
LOG.debug("found device: " + device.getName() + ", " + device.getAddress());
|
||||
if (LOG.isDebugEnabled()) {
|
||||
@ -398,46 +507,55 @@ public class DiscoveryActivity extends AbstractGBActivity implements AdapterView
|
||||
} else {
|
||||
deviceCandidates.add(candidate);
|
||||
}
|
||||
cadidateListAdapter.notifyDataSetChanged();
|
||||
deviceCandidateAdapter.notifyDataSetChanged();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Pre: bluetooth is available, enabled and scanning is off.
|
||||
* Post: BT is discovering
|
||||
*/
|
||||
private void startDiscovery() {
|
||||
private void startDiscovery(Scanning what) {
|
||||
if (isScanning()) {
|
||||
LOG.warn("Not starting discovery, because already scanning.");
|
||||
return;
|
||||
}
|
||||
startDiscovery(Scanning.SCANNING_BT);
|
||||
}
|
||||
|
||||
private void startDiscovery(Scanning what) {
|
||||
LOG.info("Starting discovery: " + what);
|
||||
discoveryStarted(what); // just to make sure
|
||||
if (ensureBluetoothReady()) {
|
||||
if (what == Scanning.SCANNING_BT) {
|
||||
startBTDiscovery();
|
||||
} else if (what == Scanning.SCANNING_BTLE) {
|
||||
if (GB.supportsBluetoothLE()) {
|
||||
startButton.setText(getString(R.string.discovery_stop_scanning));
|
||||
if (ensureBluetoothReady() && isScanning == Scanning.SCANNING_OFF) {
|
||||
if (what == Scanning.SCANNING_BT || what == Scanning.SCANNING_BT_NEXT_BLE) {
|
||||
startBTDiscovery(what);
|
||||
} else if (what == Scanning.SCANNING_BLE && GB.supportsBluetoothLE()) {
|
||||
if (oldBleScanning) {
|
||||
startBTLEDiscovery();
|
||||
} else {
|
||||
discoveryFinished();
|
||||
}
|
||||
} else if (what == Scanning.SCANNING_NEW_BTLE) {
|
||||
if (GB.supportsBluetoothLE()) {
|
||||
startNEWBTLEDiscovery();
|
||||
} else {
|
||||
discoveryFinished();
|
||||
}
|
||||
} else {
|
||||
discoveryFinished();
|
||||
toast(DiscoveryActivity.this, getString(R.string.discovery_enable_bluetooth), Toast.LENGTH_SHORT, GB.ERROR);
|
||||
}
|
||||
} else {
|
||||
discoveryFinished();
|
||||
GB.toast(DiscoveryActivity.this, getString(R.string.discovery_enable_bluetooth), Toast.LENGTH_SHORT, GB.ERROR);
|
||||
toast(DiscoveryActivity.this, getString(R.string.discovery_enable_bluetooth), Toast.LENGTH_SHORT, GB.ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
private void stopDiscovery() {
|
||||
LOG.info("Stopping discovery");
|
||||
if (isScanning()) {
|
||||
Scanning wasScanning = isScanning;
|
||||
if (wasScanning == Scanning.SCANNING_BT || wasScanning == Scanning.SCANNING_BT_NEXT_BLE) {
|
||||
stopBTDiscovery();
|
||||
} else if (wasScanning == Scanning.SCANNING_BLE) {
|
||||
if (oldBleScanning) {
|
||||
stopOldBLEDiscovery();
|
||||
} else {
|
||||
stopBLEDiscovery();
|
||||
}
|
||||
}
|
||||
|
||||
discoveryFinished();
|
||||
handler.removeMessages(0, stopRunnable);
|
||||
}
|
||||
}
|
||||
|
||||
@ -445,57 +563,110 @@ public class DiscoveryActivity extends AbstractGBActivity implements AdapterView
|
||||
return isScanning != Scanning.SCANNING_OFF;
|
||||
}
|
||||
|
||||
private void stopDiscovery() {
|
||||
LOG.info("Stopping discovery");
|
||||
if (isScanning()) {
|
||||
Scanning wasScanning = isScanning;
|
||||
// unfortunately, we don't always get a call back when stopping the scan, so
|
||||
// we do it manually; BEFORE stopping the scan!
|
||||
discoveryFinished();
|
||||
private void startBTLEDiscovery() {
|
||||
LOG.info("Starting old BLE discovery");
|
||||
isScanning = Scanning.SCANNING_BLE;
|
||||
|
||||
if (wasScanning == Scanning.SCANNING_BT) {
|
||||
stopBTDiscovery();
|
||||
} else if (wasScanning == Scanning.SCANNING_BTLE) {
|
||||
stopBTLEDiscovery();
|
||||
} else if (wasScanning == Scanning.SCANNING_NEW_BTLE) {
|
||||
stopNewBTLEDiscovery();
|
||||
}
|
||||
handler.removeMessages(0, stopRunnable);
|
||||
handler.removeMessages(0, stopRunnable);
|
||||
handler.sendMessageDelayed(getPostMessage(stopRunnable), SCAN_DURATION);
|
||||
adapter.startLeScan(leScanCallback);
|
||||
|
||||
bluetoothLEProgress.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
private void stopOldBLEDiscovery() {
|
||||
if (adapter != null) {
|
||||
adapter.stopLeScan(leScanCallback);
|
||||
|
||||
isScanning = Scanning.SCANNING_OFF;
|
||||
bluetoothLEProgress.setVisibility(View.GONE);
|
||||
LOG.info("Stopped old BLE discovery");
|
||||
}
|
||||
}
|
||||
|
||||
private void stopBTLEDiscovery() {
|
||||
if (adapter != null)
|
||||
adapter.stopLeScan(leScanCallback);
|
||||
}
|
||||
// New BTLE Discovery use startScan (List<ScanFilter> filters,
|
||||
// ScanSettings settings,
|
||||
// ScanCallback callback)
|
||||
// It's added on API21
|
||||
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
|
||||
private void startNEWBTLEDiscovery() {
|
||||
// Only use new API when user uses Lollipop+ device
|
||||
LOG.info("Starting BLE discovery");
|
||||
isScanning = Scanning.SCANNING_BLE;
|
||||
|
||||
private void stopBTDiscovery() {
|
||||
if (adapter != null)
|
||||
adapter.cancelDiscovery();
|
||||
handler.removeMessages(0, stopRunnable);
|
||||
handler.sendMessageDelayed(getPostMessage(stopRunnable), SCAN_DURATION);
|
||||
|
||||
// Filters being non-null would be a very good idea with background scan, but in this case,
|
||||
// not really required.
|
||||
adapter.getBluetoothLeScanner().startScan(null, getScanSettings(), getScanCallback());
|
||||
|
||||
bluetoothLEProgress.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
|
||||
private void stopNewBTLEDiscovery() {
|
||||
if (adapter == null)
|
||||
private void stopBLEDiscovery() {
|
||||
if (adapter == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
BluetoothLeScanner bluetoothLeScanner = adapter.getBluetoothLeScanner();
|
||||
if (bluetoothLeScanner == null) {
|
||||
LOG.warn("could not get BluetoothLeScanner()!");
|
||||
LOG.warn("Could not get BluetoothLeScanner()!");
|
||||
return;
|
||||
}
|
||||
if (newLeScanCallback == null) {
|
||||
if (newBLEScanCallback == null) {
|
||||
LOG.warn("newLeScanCallback == null!");
|
||||
return;
|
||||
}
|
||||
try {
|
||||
bluetoothLeScanner.stopScan(newLeScanCallback);
|
||||
bluetoothLeScanner.stopScan(newBLEScanCallback);
|
||||
} catch (NullPointerException e) {
|
||||
LOG.warn("Internal NullPointerException when stopping the scan!");
|
||||
return;
|
||||
}
|
||||
|
||||
isScanning = Scanning.SCANNING_OFF;
|
||||
bluetoothLEProgress.setVisibility(View.GONE);
|
||||
LOG.debug("Stopped BLE discovery");
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts a regular Bluetooth scan
|
||||
*
|
||||
* @param what The scan type, only either SCANNING_BT or SCANNING_BT_NEXT_BLE!
|
||||
*/
|
||||
private void startBTDiscovery(Scanning what) {
|
||||
LOG.info("Starting BT discovery");
|
||||
isScanning = what;
|
||||
|
||||
handler.removeMessages(0, stopRunnable);
|
||||
handler.sendMessageDelayed(getPostMessage(stopRunnable), SCAN_DURATION);
|
||||
if (adapter.startDiscovery()) {
|
||||
LOG.error("Discovery starting failed");
|
||||
}
|
||||
|
||||
bluetoothProgress.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
private void stopBTDiscovery() {
|
||||
if (adapter != null) {
|
||||
adapter.cancelDiscovery();
|
||||
|
||||
bluetoothProgress.setVisibility(View.GONE);
|
||||
isScanning = Scanning.SCANNING_OFF;
|
||||
LOG.info("Stopped BT discovery");
|
||||
}
|
||||
}
|
||||
|
||||
private void discoveryFinished() {
|
||||
if (isScanning != Scanning.SCANNING_OFF) {
|
||||
LOG.warn("Scan was not properly: " + String.valueOf(isScanning));
|
||||
}
|
||||
startButton.setText(getString(R.string.discovery_start_scanning));
|
||||
}
|
||||
|
||||
|
||||
private void bluetoothStateChanged(int newState) {
|
||||
discoveryFinished();
|
||||
if (newState == BluetoothAdapter.STATE_ON) {
|
||||
@ -507,40 +678,16 @@ public class DiscoveryActivity extends AbstractGBActivity implements AdapterView
|
||||
}
|
||||
}
|
||||
|
||||
private void discoveryFinished() {
|
||||
isScanning = Scanning.SCANNING_OFF;
|
||||
progressView.setVisibility(View.GONE);
|
||||
startButton.setText(getString(R.string.discovery_start_scanning));
|
||||
}
|
||||
|
||||
private void discoveryStarted(Scanning what) {
|
||||
isScanning = what;
|
||||
progressView.setVisibility(View.VISIBLE);
|
||||
startButton.setText(getString(R.string.discovery_stop_scanning));
|
||||
}
|
||||
|
||||
private boolean ensureBluetoothReady() {
|
||||
boolean available = checkBluetoothAvailable();
|
||||
startButton.setEnabled(available);
|
||||
if (available) {
|
||||
adapter.cancelDiscovery();
|
||||
// must not return the result of cancelDiscovery()
|
||||
// appears to return false when currently not scanning
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean checkBluetoothAvailable() {
|
||||
BluetoothManager bluetoothService = (BluetoothManager) getSystemService(BLUETOOTH_SERVICE);
|
||||
if (bluetoothService == null) {
|
||||
LOG.warn("No bluetooth available");
|
||||
LOG.warn("No bluetooth service available");
|
||||
this.adapter = null;
|
||||
return false;
|
||||
}
|
||||
BluetoothAdapter adapter = bluetoothService.getAdapter();
|
||||
if (adapter == null) {
|
||||
LOG.warn("No bluetooth available");
|
||||
LOG.warn("No bluetooth adapter available");
|
||||
this.adapter = null;
|
||||
return false;
|
||||
}
|
||||
@ -555,17 +702,40 @@ public class DiscoveryActivity extends AbstractGBActivity implements AdapterView
|
||||
return true;
|
||||
}
|
||||
|
||||
// New BTLE Discovery use startScan (List<ScanFilter> filters,
|
||||
// ScanSettings settings,
|
||||
// ScanCallback callback)
|
||||
// It's added on API21
|
||||
private boolean ensureBluetoothReady() {
|
||||
boolean available = checkBluetoothAvailable();
|
||||
startButton.setEnabled(available);
|
||||
if (available) {
|
||||
adapter.cancelDiscovery();
|
||||
// must not return the result of cancelDiscovery()
|
||||
// appears to return false when currently not scanning
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
|
||||
private void startNEWBTLEDiscovery() {
|
||||
// Only use new API when user uses Lollipop+ device
|
||||
LOG.info("Start New BTLE Discovery");
|
||||
handler.removeMessages(0, stopRunnable);
|
||||
handler.sendMessageDelayed(getPostMessage(stopRunnable), SCAN_DURATION);
|
||||
adapter.getBluetoothLeScanner().startScan(getScanFilters(), getScanSettings(), getScanCallback());
|
||||
private ScanSettings getScanSettings() {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
return new ScanSettings.Builder()
|
||||
.setCallbackType(android.bluetooth.le.ScanSettings.CALLBACK_TYPE_ALL_MATCHES)
|
||||
.setScanMode(android.bluetooth.le.ScanSettings.SCAN_MODE_LOW_LATENCY)
|
||||
.setMatchMode(android.bluetooth.le.ScanSettings.MATCH_MODE_AGGRESSIVE)
|
||||
.setPhy(android.bluetooth.le.ScanSettings.PHY_LE_ALL_SUPPORTED)
|
||||
.setNumOfMatches(android.bluetooth.le.ScanSettings.MATCH_NUM_ONE_ADVERTISEMENT)
|
||||
.build();
|
||||
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
return new ScanSettings.Builder()
|
||||
.setCallbackType(android.bluetooth.le.ScanSettings.CALLBACK_TYPE_ALL_MATCHES)
|
||||
.setScanMode(android.bluetooth.le.ScanSettings.SCAN_MODE_LOW_LATENCY)
|
||||
.setMatchMode(android.bluetooth.le.ScanSettings.MATCH_MODE_AGGRESSIVE)
|
||||
.setNumOfMatches(android.bluetooth.le.ScanSettings.MATCH_NUM_ONE_ADVERTISEMENT)
|
||||
.build();
|
||||
} else {
|
||||
return new ScanSettings.Builder()
|
||||
.setScanMode(android.bluetooth.le.ScanSettings.SCAN_MODE_LOW_LATENCY)
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
||||
private List<ScanFilter> getScanFilters() {
|
||||
@ -576,32 +746,10 @@ public class DiscoveryActivity extends AbstractGBActivity implements AdapterView
|
||||
return allFilters;
|
||||
}
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
|
||||
private ScanSettings getScanSettings() {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
return new ScanSettings.Builder()
|
||||
.setScanMode(android.bluetooth.le.ScanSettings.SCAN_MODE_LOW_LATENCY)
|
||||
.setMatchMode(android.bluetooth.le.ScanSettings.MATCH_MODE_STICKY)
|
||||
.build();
|
||||
} else {
|
||||
return new ScanSettings.Builder()
|
||||
.setScanMode(android.bluetooth.le.ScanSettings.SCAN_MODE_LOW_LATENCY)
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
||||
private void startBTLEDiscovery() {
|
||||
LOG.info("Starting BTLE Discovery");
|
||||
handler.removeMessages(0, stopRunnable);
|
||||
handler.sendMessageDelayed(getPostMessage(stopRunnable), SCAN_DURATION);
|
||||
adapter.startLeScan(leScanCallback);
|
||||
}
|
||||
|
||||
private void startBTDiscovery() {
|
||||
LOG.info("Starting BT Discovery");
|
||||
handler.removeMessages(0, stopRunnable);
|
||||
handler.sendMessageDelayed(getPostMessage(stopRunnable), SCAN_DURATION);
|
||||
adapter.startDiscovery();
|
||||
private Message getPostMessage(Runnable runnable) {
|
||||
Message message = Message.obtain(handler, runnable);
|
||||
message.obj = runnable;
|
||||
return message;
|
||||
}
|
||||
|
||||
private void checkAndRequestLocationPermission() {
|
||||
@ -610,33 +758,6 @@ public class DiscoveryActivity extends AbstractGBActivity implements AdapterView
|
||||
}
|
||||
}
|
||||
|
||||
private Message getPostMessage(Runnable runnable) {
|
||||
Message m = Message.obtain(handler, runnable);
|
||||
m.obj = runnable;
|
||||
return m;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onItemLongClick(AdapterView<?> adapterView, View view, int position, long id) {
|
||||
GBDeviceCandidate deviceCandidate = deviceCandidates.get(position);
|
||||
if (deviceCandidate == null) {
|
||||
LOG.error("Device candidate clicked, but item not found");
|
||||
return true;
|
||||
}
|
||||
|
||||
DeviceCoordinator coordinator = DeviceHelper.getInstance().getCoordinator(deviceCandidate);
|
||||
GBDevice device = DeviceHelper.getInstance().toSupportedDevice(deviceCandidate);
|
||||
if (coordinator.getSupportedDeviceSpecificSettings(device) == null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
Intent startIntent;
|
||||
startIntent = new Intent(this, DeviceSettingsActivity.class);
|
||||
startIntent.putExtra(GBDevice.EXTRA_DEVICE, device);
|
||||
startActivity(startIntent);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
|
||||
GBDeviceCandidate deviceCandidate = deviceCandidates.get(position);
|
||||
@ -654,7 +775,7 @@ public class DiscoveryActivity extends AbstractGBActivity implements AdapterView
|
||||
|
||||
String authKey = sharedPrefs.getString("authkey", null);
|
||||
if (authKey == null || authKey.isEmpty() || authKey.getBytes().length < 34 || !authKey.substring(0, 2).equals("0x")) {
|
||||
GB.toast(DiscoveryActivity.this, getString(R.string.discovery_need_to_enter_authkey), Toast.LENGTH_LONG, GB.WARN);
|
||||
toast(DiscoveryActivity.this, getString(R.string.discovery_need_to_enter_authkey), Toast.LENGTH_LONG, GB.WARN);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -680,14 +801,16 @@ public class DiscoveryActivity extends AbstractGBActivity implements AdapterView
|
||||
createBond(deviceCandidate, bondingStyle);
|
||||
break;
|
||||
}
|
||||
case BluetoothDevice.BOND_BONDING:
|
||||
case BluetoothDevice.BOND_BONDING: {
|
||||
// async, wait for bonding event to finish this activity
|
||||
bondingDevice = deviceCandidate;
|
||||
break;
|
||||
case BluetoothDevice.BOND_BONDED:
|
||||
}
|
||||
case BluetoothDevice.BOND_BONDED: {
|
||||
bondingDevice = deviceCandidate;
|
||||
handleDeviceBonded();
|
||||
break;
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
LOG.error("Error pairing device: " + deviceCandidate.getMacAddress());
|
||||
@ -695,13 +818,56 @@ public class DiscoveryActivity extends AbstractGBActivity implements AdapterView
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onItemLongClick(AdapterView<?> adapterView, View view, int position, long id) {
|
||||
GBDeviceCandidate deviceCandidate = deviceCandidates.get(position);
|
||||
if (deviceCandidate == null) {
|
||||
LOG.error("Device candidate clicked, but item not found");
|
||||
return true;
|
||||
}
|
||||
|
||||
DeviceCoordinator coordinator = DeviceHelper.getInstance().getCoordinator(deviceCandidate);
|
||||
GBDevice device = DeviceHelper.getInstance().toSupportedDevice(deviceCandidate);
|
||||
if (coordinator.getSupportedDeviceSpecificSettings(device) == null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
Intent startIntent;
|
||||
startIntent = new Intent(this, DeviceSettingsActivity.class);
|
||||
startIntent.putExtra(GBDevice.EXTRA_DEVICE, device);
|
||||
startActivity(startIntent);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
stopBTDiscovery();
|
||||
stopBTLEDiscovery();
|
||||
if (GBApplication.isRunningLollipopOrLater() && !disableNewBLEScanning) {
|
||||
stopNewBTLEDiscovery();
|
||||
if (oldBleScanning) {
|
||||
stopOldBLEDiscovery();
|
||||
} else {
|
||||
if (GBApplication.isRunningLollipopOrLater()) {
|
||||
stopBLEDiscovery();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private enum Scanning {
|
||||
/**
|
||||
* Regular Bluetooth scan
|
||||
*/
|
||||
SCANNING_BT,
|
||||
/**
|
||||
* Regular Bluetooth scan but when ends, start BLE scan
|
||||
*/
|
||||
SCANNING_BT_NEXT_BLE,
|
||||
/**
|
||||
* Regular BLE scan
|
||||
*/
|
||||
SCANNING_BLE,
|
||||
/**
|
||||
* Scanning has ended or hasn't been started
|
||||
*/
|
||||
SCANNING_OFF
|
||||
}
|
||||
}
|
||||
|
@ -48,7 +48,7 @@ public class BluetoothStateChangeReceiver extends BroadcastReceiver {
|
||||
return;
|
||||
}
|
||||
|
||||
LOG.info("Bluetooth turned on => connecting...");
|
||||
LOG.info("Bluetooth turned on (ACTION_STATE_CHANGED) => connecting...");
|
||||
GBApplication.deviceService().connect();
|
||||
} else if (intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, -1) == BluetoothAdapter.STATE_OFF) {
|
||||
LOG.info("Bluetooth turned off => disconnecting...");
|
||||
|
@ -1,4 +1,4 @@
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
@ -15,25 +15,58 @@
|
||||
android:weightSum="1">
|
||||
|
||||
<Button
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/discovery_start_scanning"
|
||||
android:id="@+id/discovery_start"
|
||||
android:layout_gravity="center_horizontal" />
|
||||
|
||||
<ProgressBar
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:id="@+id/discovery_progressbar"
|
||||
android:indeterminate="true"
|
||||
android:indeterminateOnly="true"
|
||||
android:visibility="gone"
|
||||
android:layout_gravity="center_horizontal" />
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:text="@string/discovery_start_scanning" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center_vertical">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Bluetooth scan:" />
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/discovery_progressbar"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:indeterminate="true"
|
||||
android:indeterminateOnly="true"
|
||||
android:visibility="gone" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center_vertical">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Bluetooth LE scan:" />
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/discovery_ble_progressbar"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:indeterminate="true"
|
||||
android:indeterminateOnly="true"
|
||||
android:visibility="gone" />
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
<ListView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="0dp"
|
||||
android:id="@+id/discovery_deviceCandidatesView"
|
||||
android:id="@+id/discovery_device_candidates_list"
|
||||
android:layout_gravity="bottom|top"
|
||||
android:layout_weight="0.83" />
|
||||
|
||||
@ -54,9 +87,7 @@
|
||||
android:text="@string/discovery_connected_devices_hint"
|
||||
android:id="@+id/discovery_hint"
|
||||
android:textColor="@color/secondarytext"
|
||||
android:gravity="bottom"
|
||||
android:textIsSelectable="true" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</RelativeLayout>
|
||||
</LinearLayout>
|
||||
|
@ -886,6 +886,9 @@
|
||||
<string name="about_additional_contributions">Many thanks to all unlisted contributors for contributing code, support, ideas, motivation, bug reports, money… ✊</string>
|
||||
<string name="permission_granting_mandatory">All these permissions are required and instability might occur if not granted</string>
|
||||
<string name="error_version_check_extreme_caution">CAUTION: Error when checking version information! You should not continue! Saw version name \"%s\"</string>
|
||||
<string name="require_location_provider">Location must be enabled</string>
|
||||
<string name="companiondevice_pairing">CompanionDevice Pairing</string>
|
||||
<string name="companiondevice_pairing_details">Enables the new CompanionDevice API support (above Android 8 only!) which theoretically increases reliability, requires re-pairing to have an effect</string>
|
||||
<string name="error_background_service">Failed to start background service</string>
|
||||
<string name="error_background_service_reason_truncated">Starting the background service failed because…</string>
|
||||
<string name="device_is_currently_bonded">ALREADY BONDED</string>
|
||||
@ -898,6 +901,7 @@
|
||||
<string name="error_retrieving_devices_database">Error retrieving devices from database</string>
|
||||
<string name="ignore_bonded_devices">Ignore bonded devices</string>
|
||||
<string name="ignore_bonded_devices_description">Enabling this option will ignore devices that have been bonded/paired already when scanning</string>
|
||||
|
||||
<plurals name="widget_alarm_target_hours">
|
||||
<item quantity="one">%d hour</item>
|
||||
<item quantity="two">%d hours</item>
|
||||
|
@ -650,6 +650,12 @@
|
||||
android:key="disable_new_ble_scanning"
|
||||
android:summary="@string/pref_summary_disable_new_ble_scanning"
|
||||
android:title="@string/pref_disable_new_ble_scanning" />
|
||||
<CheckBoxPreference
|
||||
android:defaultValue="false"
|
||||
android:key="enable_companiondevice_pairing"
|
||||
android:layout="@layout/preference_checkbox"
|
||||
android:summary="@string/companiondevice_pairing_details"
|
||||
android:title="@string/companiondevice_pairing" />
|
||||
|
||||
</PreferenceCategory>
|
||||
</PreferenceScreen>
|
||||
|
@ -10,7 +10,6 @@ buildscript {
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:4.0.0'
|
||||
classpath "gradle.plugin.com.github.spotbugs:spotbugs-gradle-plugin:2.0.0"
|
||||
|
||||
classpath 'gradle.plugin.com.github.spotbugs:spotbugs-gradle-plugin:2.0.0'
|
||||
// NOTE: Do not place your application dependencies here; they belong
|
||||
|
Loading…
Reference in New Issue
Block a user