Android 6(棉花糖)中不稳定的BLE连接

Android 6(棉花糖)中不稳定的BLE连接,android,bluetooth,bluetooth-lowenergy,rssi,Android,Bluetooth,Bluetooth Lowenergy,Rssi,我正在开发一款android应用程序,可以使用蓝牙技术。它在安卓4.3或5.0.1以及各种设备上运行良好,但在安卓M(6.0.1)中并不稳定。我编写了一个lite示例项目,该项目具有相同的行为和问题,下面是我的全部代码 @TargetApi(Build.VERSION_CODES.LOLLIPOP) public class MainActivity extends ActionBarActivity { private BluetoothAdapter mBluetoothAdapte

我正在开发一款android应用程序,可以使用蓝牙技术。它在安卓4.3或5.0.1以及各种设备上运行良好,但在安卓M(6.0.1)中并不稳定。我编写了一个lite示例项目,该项目具有相同的行为和问题,下面是我的全部代码

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

    private boolean connectionState = false, isScanning = false;
    private TextView rssiTxt;
    private RSSITimer rssiTimer;

    @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();

        // VIEW
        rssiTxt = (TextView) findViewById(R.id.rssiTxt);

        (rssiTimer = new RSSITimer()).startTimer();
    }

    @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() {
        rssiTimer.stopTimerTask();

        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(isScanning) {
            return;
        } else {
            isScanning = true;
        }

        if (enable) {
            mHandler.postDelayed(new Runnable() {
                @Override
                public void run() {
                    if (Build.VERSION.SDK_INT < 21) {
                        mBluetoothAdapter.stopLeScan(mLeScanCallback);

                        isScanning = false;
                    } else {
                        mLEScanner.stopScan(mScanCallback);

                        isScanning = false;
                    }
                }
            }, 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) {
            Log.i("callbackType", String.valueOf(callbackType));
            Log.i("result", result.toString());
            BluetoothDevice btDevice = result.getDevice();

            if ("PRODi".equals(device.getName()) || "PRODi(TEST)".equals(device.getName())) {
                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());

                            if ("PRODi".equals(device.getName()) || "PRODi(TEST)".equals(device.getName())) {
                                connectToDevice(device);
                            }
                        }
                    });
                }
            };

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

            return;
        } else {
            mGatt.connect();
            scanLeDevice(false);// will stop after first device detection
        }
    }

    private final BluetoothGattCallback gattCallback = new BluetoothGattCallback() {
        @Override
        public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
            switch (newState) {
                case BluetoothProfile.STATE_CONNECTED:

                    Log.i("gattCallback", "STATE_CONNECTED");
                    gatt.discoverServices();
                    connectionState = true;
                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            Toast.makeText(MainActivity.this, "STATE_CONNECTED", Toast.LENGTH_SHORT).show();
                        }
                    });
                    break;
                case BluetoothProfile.STATE_DISCONNECTED:

                    Log.e("gattCallback", "STATE_DISCONNECTED");
                    connectionState = false;
                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            Toast.makeText(MainActivity.this, "STATE_DISCONNECTED", Toast.LENGTH_SHORT).show();
                        }
                    });
                    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();
        }

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

            final int rssi2 = rssi;
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    rssiTxt.setText("RSSI: " + rssi2);
                }
            });
        }
    };

    /*TIMER for Read RSSI*/////////////////////////////////////////////////////////////////////////////////////////
    class RSSITimer {
        //we are going to use a handler to be able to run in our TimerTask
        final Handler handler = new Handler();
        private Timer     timer;
        private TimerTask timerTask;

        private int interval = 1000;

        public void startTimer() {
            //set a new Timer
            timer = new Timer();
            //initialize the TimerTask's job
            initializeTimerTask();
            //schedule the timer, after the first 1000ms the TimerTask will run every [INTERVAL]ms
            timer.schedule(timerTask, 1000, interval); //
        }

        public void stopTimerTask() {
            //stop the timer, if it's not already null
            if (timer != null)
            {
                timer.cancel();
                timer = null;
            }
        }

        public void initializeTimerTask() {
            timerTask = new TimerTask() {
                public void run() {
                    handler.post(new Runnable() {
                        public void run() {

                            if (mBluetoothAdapter.isEnabled()) {
                                if (connectionState == false) {
                                    scanLeDevice(true);
                                } else {
                                    mGatt.readRemoteRssi();
                                }
                            }
                        }
                    });
                }
            };
        }
    }
}
@TargetApi(Build.VERSION\u CODES.LOLLIPOP)
公共类MainActivity扩展了ActionBarActivity{
私人蓝牙适配器mBluetoothAdapter;
私有整数请求\启用\ BT=1;
私人经理人;
专用静态最终长扫描周期=2000;
私人蓝牙扫描仪;
私人扫描设置;
私有列表过滤器;
私人蓝牙GATT mGatt;
私有布尔连接状态=false,isScanning=false;
私有文本视图rssiTxt;
私人RSSITimer RSSITimer;
@凌驾
创建时受保护的void(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mHandler=新处理程序();
如果(!getPackageManager().hasSystemFeature(PackageManager.FEATURE\u BLUETOOTH\u LE)){
Toast.makeText(不支持此选项),
吐司。长度(短)。show();
完成();
}
最终BluetoothManager BluetoothManager=
(BluetoothManager)getSystemService(Context.BLUETOOTH\u服务);
mBluetoothAdapter=bluetoothManager.getAdapter();
//看法
rssiTxt=(TextView)findViewById(R.id.rssiTxt);
(rssiTimer=new rssiTimer()).startTimer();
}
@凌驾
受保护的void onResume(){
super.onResume();
if(mBluetoothAdapter==null | |!mBluetoothAdapter.isEnabled()){
Intent enablebintent=新意图(BluetoothAdapter.ACTION\u REQUEST\u ENABLE);
startActivityForResult(启用BTIntent、请求\启用\ BT);
}否则{
如果(Build.VERSION.SDK_INT>=21){
mLEScanner=mBluetoothAdapter.getBluetoothLeScanner();
设置=新的ScanSettings.Builder()
.setScanMode(扫描设置.SCAN\u模式\u低延迟)
.build();
过滤器=新的ArrayList();
}
扫描设备(真实);
}
}
@凌驾
受保护的void onPause(){
super.onPause();
if(mBluetoothAdapter!=null&&mBluetoothAdapter.isEnabled()){
//扫描设备(假);
}
}
@凌驾
受保护的空onDestroy(){
rssiTimer.stopTimerTask();
如果(mGatt==null){
返回;
}
mGatt.close();
mGatt=null;
super.ondestory();
}
@凌驾
受保护的void onActivityResult(int请求代码、int结果代码、意图数据){
if(requestCode==请求启用){
if(resultCode==Activity.RESULT\u已取消){
//蓝牙未启用。
完成();
返回;
}
}
super.onActivityResult(请求代码、结果代码、数据);
}
专用void扫描设备(最终布尔启用){
如果(正在扫描){
返回;
}否则{
IsScaning=真;
}
如果(启用){
mHandler.postDelayed(新的Runnable(){
@凌驾
公开募捐{
if(Build.VERSION.SDK_INT<21){
mBluetoothAdapter.stopLeScan(mLeScanCallback);
isScanning=false;
}否则{
mLEScanner.stopScan(mScanCallback);
isScanning=false;
}
}
},扫描周期);
if(Build.VERSION.SDK_INT<21){
mBluetoothAdapter.startedscan(mLeScanCallback);
}否则{
mLEScanner.startScan(过滤器、设置、mScanCallback);
}
}否则{
if(Build.VERSION.SDK_INT<21){
mBluetoothAdapter.stopLeScan(mLeScanCallback);
}否则{
mLEScanner.stopScan(mScanCallback);
}
}
}
private ScanCallback mScanCallback=新建ScanCallback(){
@凌驾
公共void onScanResult(int callbackType、ScanResult){
Log.i(“callbackType”,String.valueOf(callbackType));
Log.i(“result”,result.toString());
BluetoothDevice btDevice=result.getDevice();
如果(“PRODi”.equals(device.getName())| |“PRODi(TEST)”.equals(device.getName())){
连接到设备(BTD设备);
}
}
@凌驾
public void onBatchScanResults(列出结果){
用于(扫描结果sr:结果){
Log.i(“ScanResult-Results”,sr.toString());
}
}
@凌驾
公共无效OnScan失败(内部错误代码){
Log.e(“扫描失败”,“错误代码:”+错误代码);
}
};
私有BluetoothAdapter.LeScanCallback mLeScanCallback=
新的BluetoothAdapter.LeScanCallback(){
@凌驾
public void onLeScan(最终蓝牙设备,int rssi,
字节[]扫描记录){
runOnUiThread(新的Runnable(){
@凌驾
公开募捐{
Log.i(“onLeScan”,device.toString());
如果(“PRODi”.equals(device.getName())| |“PRODi(TEST)”.equals(device.getName())){
连接到设备(设备);
}
}
});
}
};
public void connectToDevice(蓝牙设备){
如果(mGatt==null){
mGatt=device.connectGatt(getApplicationContext(),false,gattCallback);
扫描设备(错误);//wi