Android Marshmallow [API 23]: Bluetooth UUID возвращает NULL

Только что обновил свой андроид до зефира и понял, что работает не очень хорошо. Я только что создал приложение, которое сообщает об устройствах и службах (с UUID), доступных через классический Bluetooth:

Я тестировал его в:

API 16

введите здесь описание изображения

API 22

введите здесь описание изображения

API 23

введите здесь описание изображения

Мои манифестные разрешения:

<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.BLUETOOTH_PRIVILEGED" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />

И если вы хотите проверить код приложения:

У меня заканчиваются идеи, поэтому любая помощь будет принята с благодарностью

Спасибо!


person Lug    schedule 03.02.2016    source источник


Ответы (3)


Чтобы обеспечить пользователям более высокий уровень защиты данных, начиная с этого выпуска Android удаляет программный доступ к локальному аппаратному идентификатору устройства для приложений, использующих API Wi-Fi и Bluetooth. Методы WifiInfo.getMacAddress() и BluetoothAdapter.getAddress() теперь возвращают постоянное значение 02:00:00:00:00:00.

Чтобы получить доступ к аппаратным идентификаторам ближайших внешних устройств через сканирование Bluetooth и Wi-Fi, ваше приложение теперь должно иметь разрешения ACCESS_FINE_LOCATION или ACCESS_COARSE_LOCATION:

WifiManager.getScanResults();
BluetoothDevice.ACTION_FOUND;
BluetoothLeScanner.startScan();

так что это функция обновления, добавьте эти три метода, которые вы можете получить UUID

person Youhai LU    schedule 21.03.2016
comment
Спасибо за ваш ответ, но, как вы можете видеть в манифесте, эти разрешения уже есть. А если вы заглянете в приложение, то сможете глубже взглянуть на ситуацию. Спасибо еще раз - person Lug; 25.03.2016

После головной боли и часов исследований ответ заключается в том, чтобы создать сокет не с CreateInsecureRfcommSocketToServiceRecord, а с CreateRfcommSocketToServiceRecord и UUID по умолчанию, например "00001101-0000-1000-8000-00805F9B34FB".

person Lug    schedule 13.04.2016

Я должен представить, что у вас та же проблема, что и у меня, для SDK 23 вы должны заставить пользователя подтвердить, что он дает разрешение на ACCESS_COARSE_LOCATION. (Я предполагаю, что вы используете поиск BLE)

взгляните на свой журнал консоли, и я предполагаю, что вы найдете очень добавочную ошибку, которая выглядит так, выделена синим цветом.

java.lang.SecurityException: Need ACCESS_COARSE_LOCATION or ACCESS_FINE_LOCATION permission to get scan results
               at android.os.Parcel.readException(Parcel.java:1627)
               at android.os.Parcel.readException(Parcel.java:1579)
               at android.bluetooth.IBluetoothGatt$Stub$Proxy.startScan(IBluetoothGatt.java:772)
               at android.bluetooth.le.BluetoothLeScanner$BleScanCallbackWrapper.onClientRegistered(BluetoothLeScanner.java:324)
               at android.bluetooth.IBluetoothGattCallback$Stub.onTransact(IBluetoothGattCallback.java:56)
               at android.os.Binder.execTransact(Binder.java:453)

Похоже, вам нужно получить разрешение пользователя (например, приложение для iOS), поэтому вам нужно добавить некоторый код в свой инициал, как это

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M){
        if (this.checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED){
            if (shouldShowRequestPermissionRationale(Manifest.permission.ACCESS_COARSE_LOCATION)){
                if (DEBUG) Log.i(TAG, "EXPLANATION NEEDED");
                AlertDialog.Builder builder = new AlertDialog.Builder(this);
                builder.setTitle("Warning Permission Needed");
                builder.setMessage("If you don't enable the location for this app then we can not connect to the controller");
                builder.setPositiveButton("Change", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                            requestPermissions(new String[]{Manifest.permission.ACCESS_COARSE_LOCATION}, REQUEST_LOCATION);
                        }
                    }
                });
                AlertDialog dialog = builder.create();
                dialog.show();
            }else{
                requestPermissions(new String[]{Manifest.permission.ACCESS_COARSE_LOCATION},REQUEST_LOCATION);
            }
        }
    }

Здесь вы должны решить, что делать, если пользователь не прочитает сообщение и нажмет «Отклонить». поэтому проверьте возврат в методе ниже

@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    if (requestCode == REQUEST_LOCATION){
        if (grantResults[0] != PackageManager.PERMISSION_GRANTED){
           // ask the question again as they denied the permission 
        }
    }

}

После всего этого у вас все это вдруг снова заработает, если ваша проблема была как у меня

person Mark Gilchrist    schedule 18.05.2016