BLE 扫描在 Android 中不起作用

Posted

技术标签:

【中文标题】BLE 扫描在 Android 中不起作用【英文标题】:BLE Scan not working in Android 【发布时间】:2016-07-03 07:03:37 【问题描述】:

我正在尝试使用以下代码扫描 android 中的其他蓝牙设备。 但是什么都没有被触发,也没有检测到任何设备。

import android.annotation.TargetApi;
import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCallback;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattService;
import android.bluetooth.BluetoothManager;
import android.bluetooth.BluetoothProfile;
import android.bluetooth.le.BluetoothLeScanner;
import android.bluetooth.le.ScanCallback;
import android.bluetooth.le.ScanFilter;
import android.bluetooth.le.ScanResult;
import android.bluetooth.le.ScanSettings;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.support.v7.app.ActionBarActivity;
import android.util.Log;
import android.widget.Toast;

import java.util.ArrayList;
import java.util.List;

@TargetApi(21)
public class MainActivity extends ActionBarActivity 
    private BluetoothAdapter mBluetoothAdapter;
    private int REQUEST_ENABLE_BT = 1;
    private Handler mHandler;
    private static final long SCAN_PERIOD = 1000000;
    private BluetoothLeScanner mLEScanner;
    private ScanSettings settings;
    private List<ScanFilter> filters;
    private BluetoothGatt mGatt;

    @Override
    protected void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mHandler = new Handler();
        if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) 
            Toast.makeText(this, "BLE Not Supported",
                    Toast.LENGTH_SHORT).show();
            finish();
        
        final BluetoothManager bluetoothManager =
                (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
        mBluetoothAdapter = bluetoothManager.getAdapter();

    

    @Override
    protected void onResume() 
        super.onResume();
        if (mBluetoothAdapter == null || !mBluetoothAdapter.isEnabled()) 
            Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
            startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
         else 
            if (Build.VERSION.SDK_INT >= 21) 
                mLEScanner = mBluetoothAdapter.getBluetoothLeScanner();
                settings = new ScanSettings.Builder()
                        .setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY)
                        .build();
                filters = new ArrayList<ScanFilter>();
            
            scanLeDevice(true);
        
    

    @Override
    protected void onPause() 
        super.onPause();
        if (mBluetoothAdapter != null && mBluetoothAdapter.isEnabled()) 
            scanLeDevice(false);
        
    

    @Override
    protected void onDestroy() 
        if (mGatt == null) 
            return;
        
        mGatt.close();
        mGatt = null;
        super.onDestroy();
    

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) 
        if (requestCode == REQUEST_ENABLE_BT) 
            if (resultCode == Activity.RESULT_CANCELED) 
                //Bluetooth not enabled.
                finish();
                return;
            
        
        super.onActivityResult(requestCode, resultCode, data);
    

    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);
                mLEScanner.startScan( 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) 
            Log.i("callbackType", String.valueOf(callbackType));
            Log.i("result", result.toString());
            BluetoothDevice 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 BluetoothAdapter.LeScanCallback mLeScanCallback =
            new BluetoothAdapter.LeScanCallback() 
                @Override
                public void onLeScan(final BluetoothDevice device, int rssi,
                                     byte[] scanRecord) 
                    runOnUiThread(new Runnable() 
                        @Override
                        public void run() 
                            Log.i("onLeScan", device.toString());
                            connectToDevice(device);
                        
                    );
                
            ;

    public void connectToDevice(BluetoothDevice device) 
        if (mGatt == null) 
            mGatt = device.connectGatt(this, false, gattCallback);
            scanLeDevice(false);// will stop after first device detection
        
    

    private final BluetoothGattCallback gattCallback = new BluetoothGattCallback() 
        @Override
        public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) 
            Log.i("onConnectionStateChange", "Status: " + status);
            switch (newState) 
                case BluetoothProfile.STATE_CONNECTED:
                    Log.i("gattCallback", "STATE_CONNECTED");
                    gatt.discoverServices();
                    break;
                case BluetoothProfile.STATE_DISCONNECTED:
                    Log.e("gattCallback", "STATE_DISCONNECTED");
                    break;
                default:
                    Log.e("gattCallback", "STATE_OTHER");
            

        

        @Override
        public void onServicesDiscovered(BluetoothGatt gatt, int status) 
            List<BluetoothGattService> services = gatt.getServices();
            Log.i("onServicesDiscovered", services.toString());
            gatt.readCharacteristic(services.get(1).getCharacteristics().get
                    (0));
        

        @Override
        public void onCharacteristicRead(BluetoothGatt gatt,
                                         BluetoothGattCharacteristic
                                                 characteristic, int status) 
            Log.i("onCharacteristicRead", characteristic.toString());
            gatt.disconnect();
        
    ;

我在清单中有这些。 添加了 BLE 精度所需的粗略位置。

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

<uses-feature android:name="android.hardware.bluetooth_le"  
              android:required="true" />

【问题讨论】:

Plz check it. 对我来说是帮助我。 【参考方案1】:

您必须检查的几件事。

您的安卓设备是否支持BLE? 为此使用 (getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) 如果 android 版本是 6.0 则允许位置访问表单-设置-> 应用 确保您的位置信息已在 Android 设备中启用。

【讨论】:

我都做了,仍然没有检测到任何设备。还有什么我需要照顾的吗?你能检查一下上面的代码是否有任何问题。谢谢 在我的情况下,允许位置权限是有效的。

以上是关于BLE 扫描在 Android 中不起作用的主要内容,如果未能解决你的问题,请参考以下文章

热点插件 scanWifi() 在 Android ionic cordova 中不起作用

Ionic Android 问题:扫描功能不起作用

HBase 扫描时间范围在 Scala 中不起作用

PhoneGap BLE 插件在后台不起作用

为啥 Set.add() 方法在匿名 Runnable 中不起作用?

SwipeRefreshLayout 在 Android 中不起作用