Android 6.0或更高版本中BleScanner的许可

问题描述 投票:-1回答:1

我正在构建一个试图找到并连接到BLE设备的应用程序。我在Android 5.0的智能手机上测试了它,它的工作原理。

然后我尝试在Android 7.0上安装它,但我不能在任何BLE设备上连接。所以这是我的服务,尝试连接BLE设备并下载它的所有信息。如何更改我的代码以使用Android 6和7的应用程序?

public class BlePowerService extends Service {
    public DbLayer db;
    Setting settingApp;
    List<ScanFilter> filters;
    String[] stringSequence = new String[] {CHARACTERISTIC_FORZA_STRING, CHARACTERISTIC_TEMPERATURA_STRING};
    BluetoothAdapter mBluetoothAdapter;
    BluetoothGatt mGatt;
    BluetoothDevice currDevice;
    static final long SCAN_PERIOD = 1000;
    static String SPLIT_CHAR =";";
    BluetoothLeScanner mLEScanner;
    Handler mHandler;
    int ReadQueueIndex;
    List<BluetoothGattCharacteristic> ReadQueue;
    BluetoothGattCharacteristic caratteristicaDaLeggere;
    ScanSettings settings;
    Integer ultimaForzaLetta,ultimaTemperaturaLetta;
    boolean continuaLetturaForza, continuaLetturaTemperatura;
    private final Object readLock = new Object();
    boolean isReading = true;
    String LOG_CODE = "NOTIFSRV";
    GattClientCallback gattClientCallback;

    public BlePowerService() {
    }

    @Override
    public IBinder onBind(Intent intent) {
      return null;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        mHandler = new Handler();

        Context sharedContext = null;
        try {
            sharedContext = this.createPackageContext(
                    "com.eresult.diabesitycare.devicesensor",
                    Context.CONTEXT_INCLUDE_CODE);
            if (sharedContext == null) {
                return;
            }
            db=new DbLayer(sharedContext);
            db.open();
        } catch (Exception e) {
            String error = e.getMessage();
          //  Log.d(LOG_CODE,"DB error : " + error);
            return;
        }

    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        try {
            //RECUPERO LE IMPOSTAZIONI SETTATE DALL'UTENTE
            settingApp = db.fetchSetting();
            if (settingApp != null && settingApp.getAddressBleSX()!=null) {
                ScanFilter.Builder scanFilterMac = null;
        scanFilterMac = new ScanFilter.Builder().setDeviceAddress(settingApp.getAddressBleSX());
                if(filters==null)
                    filters = new ArrayList<ScanFilter>();
                filters.add(scanFilterMac.build());
                //FILTRO ANCHE PER LA CARATTERISTICA DI FORZA
                ScanFilter filter = null;
                    filter = new ScanFilter.Builder().setServiceUuid(ParcelUuid.fromString(CHARACTERISTIC_FORZA_STRING)).build();
                filters.add(filter);

                mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
                mLEScanner = mBluetoothAdapter.getBluetoothLeScanner();
                    settings = new ScanSettings.Builder()
                            .setScanMode(ScanSettings.SCAN_MODE_LOW_POWER)
                            .build();
                scanLeDevice(true);
                mTimer = new Timer();
                int nMinuti = settingApp.getFrequenzaDownload()!= null ? settingApp.getFrequenzaDownload() : 1;
                mTimer.schedule(timerTask, 10000, 60000 * nMinuti);
            }
        } catch (Exception e) {
           // Log.e("POWER_SERVICE", e.getMessage());
        }
        return super.onStartCommand(intent, flags, startId);
    }

    public void connectToDevice(BluetoothDevice device) {
        //VERIFICO SE IL DEVICE è QUELLO CHE VOGLIO IO
        if (mGatt == null && settingApp != null
                && device.getAddress().equals(settingApp.getAddressBleSX())) {
            currDevice = device;
            gattClientCallback = new GattClientCallback();
            mGatt = currDevice.connectGatt(getBaseContext(), false, gattClientCallback);
            scanLeDevice(false);// will stop after first device detection
        }
    }

    private BluetoothAdapter.LeScanCallback mLeScanCallback =
            new BluetoothAdapter.LeScanCallback() {
                @Override
                public void onLeScan(final BluetoothDevice device, int rssi,
                                     byte[] scanRecord) {
                    Handler h = new Handler(getApplicationContext().getMainLooper());
                    // Although you need to pass an appropriate context
                    h.post(new Runnable() {
                        @Override
                        public void run() {
                          //  Log.i("onLeScan", device.toString());
                                connectToDevice(device);

                        }
                    });
                }
            };

    private void scanLeDevice(final boolean enable) {
        if (enable) {
            mHandler.postDelayed(new Runnable() {
                @Override
                public void run() {
                    if (Build.VERSION.SDK_INT < 21) {
                        mBluetoothAdapter.stopLeScan(mLeScanCallback);
                    } else {
                        mLEScanner.stopScan(mScanCallback);

                    }
                }
            }, SCAN_PERIOD);
            if (Build.VERSION.SDK_INT < 21) {
                mBluetoothAdapter.startLeScan(mLeScanCallback);
            } else {
                mLEScanner.startScan(filters, settings, mScanCallback);
            }
        } else {
            if (Build.VERSION.SDK_INT < 21) {
                mBluetoothAdapter.stopLeScan(mLeScanCallback);
            } else {
                mLEScanner.stopScan(mScanCallback);
            }
        }
    }


    private ScanCallback mScanCallback = new ScanCallback() {
        @Override
        public void onScanResult(int callbackType, ScanResult result) {
            BluetoothDevice btDevice = null;
               btDevice = result.getDevice();
            connectToDevice(btDevice);
        }

        @Override
        public void onBatchScanResults(List<ScanResult> results) {
            for (ScanResult sr : results) {
                Log.i("ScanResult - Results", sr.toString());
            }
        }

        @Override
        public void onScanFailed(int errorCode) {
           Log.e("Scan Failed", "Error Code: " + errorCode);
        }
    };

    private class GattClientCallback extends BluetoothGattCallback {

        @Override
        public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
            try{
                super.onConnectionStateChange(gatt, status, newState);
                Log.i("tag", "onConnectionStateChange newState: " + newState);

                if (status == BluetoothGatt.GATT_FAILURE) {
                    Log.e("ERROR_SERVICE", "Connection Gatt failure status " + status);
                    if(mGatt == null){

                    }else{
                        disconnectGattServer();
                        mGatt = null;
                    }
                    return;
                } else if (status != BluetoothGatt.GATT_SUCCESS) {
                    // handle anything not SUCCESS as failure
                    Log.e("ERROR_SERVICE", "Connection not GATT sucess status " + status);
                    if(mGatt == null){

                    }else{
                        disconnectGattServer();
                        mGatt = null;
                    }
                    return;
                }

                if (newState == BluetoothProfile.STATE_CONNECTED) {
                    //Log.i("INFO", "Connected to device " + gatt.getDevice().getAddress());
                    gatt.discoverServices();
                } else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
                    Log.i("INFO", "Disconnected from device");
                    if(mGatt == null){

                    }else{
                        disconnectGattServer();
                        mGatt = null;
                    }

                }
            }catch(Exception e){
                Log.e("tag", e.getMessage());
            }
        }

        public void disconnectGattServer() {
          continuaLetturaForza = false;
            continuaLetturaTemperatura = false;
            if (mGatt == null) {

            }
            else{
                try{
                    mGatt.disconnect();
                    mGatt.close();
                }catch(Exception e){
                    mGatt = null;
                }

            }
            mGatt = null;
            currDevice = null;
        }

        @Override
        public void onServicesDiscovered(BluetoothGatt gatt, int status) {
            super.onServicesDiscovered(gatt, status);

            if (status != BluetoothGatt.GATT_SUCCESS) {
             //   Log.i("INFO", "Device service discovery unsuccessful, status " + status);
                return;
            }

            List<BluetoothGattCharacteristic> matchingCharacteristics =
                    BluetoothUtils.findCharacteristics(gatt,stringSequence);
            if (matchingCharacteristics.isEmpty()) {
              //  Log.e("ERROR_SERVICE","Unable to find characteristics.");
                return;
            }else {
                ReadQueue = new ArrayList<>();
                for (BluetoothGattCharacteristic characterist : matchingCharacteristics) {
                    ReadQueue.add(characterist);
                }
              }
        }

        @Override
        public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
            super.onCharacteristicRead(gatt, characteristic, status);
            if (status == BluetoothGatt.GATT_SUCCESS) {
                //TO DO
        } else {
                //TO DO
            }
        }
    }

    public void onDestroy() {
        try {
            db.close();
            Log.d(LOG_CODE,"DB connection closed" );
            mTimer.cancel();
            timerTask.cancel();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


}

我还在我的AndroidManifest.xml中插入了这行代码:

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

如果Android版本是6或更高版本,我可以设置另一个权限吗?

android bluetooth-lowenergy
1个回答
0
投票

不必在运行时请求BLUETOOTH和BLUETOOTH_ADMIN等权限,但必须是ACCESS_COARSE_LOCATION。尝试使用以下代码请求ACCESS_COARSE_LOCATION权限:

// Here, thisActivity is the current activity
    if (ContextCompat.checkSelfPermission(MainActivity.this,
            Manifest.permission.ACCESS_COARSE_LOCATION)
            != PackageManager.PERMISSION_GRANTED) {


        // Should we show an explanation?
        if (ActivityCompat.shouldShowRequestPermissionRationale(MainActivity.this,
                Manifest.permission.ACCESS_COARSE_LOCATION)) {

            // Show an expanation to the user *asynchronously* -- don't block
            // this thread waiting for the user's response! After the user
            // sees the explanation, try again to request the permission.

            Log.d(TAG, "We need to show an explanation...");

            DialogInterface.OnClickListener dialogClickListener = new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    switch (which){
                        case DialogInterface.BUTTON_POSITIVE:
                            ActivityCompat.requestPermissions(MainActivity.this,
                                    new String[]{android.Manifest.permission.ACCESS_COARSE_LOCATION},
                                    MY_PERMISSIONS_REQUEST_COARSE_LOCATION);
                            break;

                        case DialogInterface.BUTTON_NEGATIVE:
                            //No button clicked
                            finish();
                            break;
                    }
                }
            };

            AlertDialog.Builder builder = new AlertDialog.Builder(this);
            builder.setMessage("Access to position is required in order to scan Bluetooth LE devices, please grant this permission to this app.").setPositiveButton("Grant now", dialogClickListener)
                    .setNegativeButton("Grant later", dialogClickListener).show();

        } else {

            // No explanation needed, we can request the permission.

            ActivityCompat.requestPermissions(MainActivity.this,
                    new String[]{Manifest.permission.ACCESS_COARSE_LOCATION},
                    MY_PERMISSIONS_REQUEST_COARSE_LOCATION);

            // MY_PERMISSIONS_REQUEST_READ_CONTACTS is an
            // app-defined int constant. The callback method gets the
            // result of the request.
        }
    } else {
        // You have already the permission
    }

然后,您可以在此回调中检索用户响应:

@Override
public void onRequestPermissionsResult(int requestCode,
                                       String permissions[], int[] grantResults) {
    switch (requestCode) {
        case MY_PERMISSIONS_REQUEST_COARSE_LOCATION: {
            // If request is cancelled, the result arrays are empty.
            if (grantResults.length > 0
                    && grantResults[0] == PackageManager.PERMISSION_GRANTED) {

                // permission was granted, yay! Do the
                // contacts-related task you need to do.

            } else {

                // permission denied, boo! Disable the
                // functionality that depends on this permission.

            }
            return;
        }

        // other 'case' lines to check for other
        // permissions this app might request
    }
}

请记住,ACCESS_COARSE_LOCATION仅对使用“startLeScan”方法扫描BLE设备有用(连接时不是必需的)。在某些情况下,您必须在智能手机上启用GPS才能获得扫描结果。

© www.soinside.com 2019 - 2024. All rights reserved.